aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lua/nvim-lsp-installer/core/functional.lua259
-rw-r--r--lua/nvim-lsp-installer/core/functional/data.lua30
-rw-r--r--lua/nvim-lsp-installer/core/functional/function.lua89
-rw-r--r--lua/nvim-lsp-installer/core/functional/init.lua89
-rw-r--r--lua/nvim-lsp-installer/core/functional/list.lua80
-rw-r--r--lua/nvim-lsp-installer/core/functional/logic.lua44
-rw-r--r--lua/nvim-lsp-installer/core/functional/number.lua34
-rw-r--r--lua/nvim-lsp-installer/core/functional/relation.lua17
-rw-r--r--lua/nvim-lsp-installer/core/functional/string.lua17
-rw-r--r--lua/nvim-lsp-installer/core/functional/table.lua9
-rw-r--r--lua/nvim-lsp-installer/core/functional/type.lua14
-rw-r--r--lua/nvim-lsp-installer/core/managers/composer/init.lua8
-rw-r--r--lua/nvim-lsp-installer/core/managers/gem/init.lua8
-rw-r--r--lua/nvim-lsp-installer/core/managers/github/client.lua27
-rw-r--r--lua/nvim-lsp-installer/core/managers/pip3/init.lua16
-rw-r--r--lua/nvim-lsp-installer/core/process.lua10
-rw-r--r--lua/nvim-lsp-installer/core/ui/init.lua10
-rw-r--r--lua/nvim-lsp-installer/servers/angularls/init.lua12
-rw-r--r--lua/nvim-lsp-installer/servers/dhall_lsp_server/init.lua19
-rw-r--r--lua/nvim-lsp-installer/servers/init.lua25
-rw-r--r--lua/nvim-lsp-installer/ui/components/settings-schema.lua6
-rw-r--r--lua/nvim-lsp-installer/ui/init.lua54
-rw-r--r--scripts/autogen_metadata.lua14
-rw-r--r--tests/core/functional/data_spec.lua28
-rw-r--r--tests/core/functional/function_spec.lua142
-rw-r--r--tests/core/functional/list_spec.lua87
-rw-r--r--tests/core/functional/logic_spec.lua44
-rw-r--r--tests/core/functional/number_spec.lua50
-rw-r--r--tests/core/functional/relation_spec.lua36
-rw-r--r--tests/core/functional/string_spec.lua17
-rw-r--r--tests/core/functional/table_spec.lua7
-rw-r--r--tests/core/functional/type_spec.lua26
-rw-r--r--tests/core/functional_spec.lua247
33 files changed, 946 insertions, 629 deletions
diff --git a/lua/nvim-lsp-installer/core/functional.lua b/lua/nvim-lsp-installer/core/functional.lua
deleted file mode 100644
index 8780c995..00000000
--- a/lua/nvim-lsp-installer/core/functional.lua
+++ /dev/null
@@ -1,259 +0,0 @@
-local functional = {}
-
----@generic T : string
----@param values T[]
----@return table<T, T>
-function functional.enum(values)
- local result = {}
- for i = 1, #values do
- local v = values[i]
- result[v] = v
- end
- return result
-end
-
----@generic T
----@param list T[]
----@return table<T, boolean>
-function functional.set_of(list)
- local set = {}
- for i = 1, #list do
- set[list[i]] = true
- end
- return set
-end
-
----@generic T
----@param list T[]
----@return T[]
-function functional.list_reverse(list)
- local result = {}
- for i = #list, 1, -1 do
- result[#result + 1] = list[i]
- end
- return result
-end
-
----@generic T, U
----@param fn fun(item: T): U
----@param list T[]
----@return U[]
-function functional.list_map(fn, list)
- local result = {}
- for i = 1, #list do
- result[#result + 1] = fn(list[i], i)
- end
- return result
-end
-
-function functional.table_pack(...)
- return { n = select("#", ...), ... }
-end
-
-function functional.list_not_nil(...)
- local result = {}
- local args = functional.table_pack(...)
- for i = 1, args.n do
- if args[i] ~= nil then
- result[#result + 1] = args[i]
- end
- end
- return result
-end
-
-function functional.when(condition, value)
- return condition and value or nil
-end
-
-function functional.lazy_when(condition, fn)
- return condition and fn() or nil
-end
-
-function functional.coalesce(...)
- local args = functional.table_pack(...)
- for i = 1, args.n do
- local variable = args[i]
- if variable ~= nil then
- return variable
- end
- end
-end
-
----@generic T
----@param list T[]
----@return T[] @A shallow copy of the list.
-function functional.list_copy(list)
- local result = {}
- for i = 1, #list do
- result[#result + 1] = list[i]
- end
- return result
-end
-
----@generic T
----@param predicate fun(item: T): boolean
----@param list T[]
----@return T | nil
-function functional.list_find_first(predicate, list)
- local result
- for i = 1, #list do
- local entry = list[i]
- if predicate(entry) then
- return entry
- end
- end
- return result
-end
-
----@generic T
----@param predicate fun(item: T): boolean
----@param list T[]
----@return boolean
-function functional.list_any(predicate, list)
- for i = 1, #list do
- if predicate(list[i]) then
- return true
- end
- end
- return false
-end
-
-function functional.identity(a)
- return a
-end
-
-function functional.always(a)
- return function()
- return a
- end
-end
-
----@generic T : fun(...)
----@param fn T
----@param cache_key_generator (fun(...): string | nil)|nil
----@return T
-function functional.memoize(fn, cache_key_generator)
- cache_key_generator = cache_key_generator or functional.identity
- local cache = {}
- return function(...)
- local key = cache_key_generator(...)
- if not cache[key] then
- cache[key] = functional.table_pack(fn(...))
- end
- return unpack(cache[key], 1, cache[key].n)
- end
-end
-
----@generic T
----@param fn fun(): T
----@return fun(): T
-function functional.lazy(fn)
- local memoized = functional.memoize(fn, functional.always "lazyval")
- return function()
- return memoized()
- end
-end
-
----@generic T
----@param fn fun(...): T
----@return fun(...): T
-function functional.partial(fn, ...)
- local bound_args = functional.table_pack(...)
- return function(...)
- local args = functional.table_pack(...)
- local merged_args = {}
- for i = 1, bound_args.n do
- merged_args[i] = bound_args[i]
- end
- for i = 1, args.n do
- merged_args[bound_args.n + i] = args[i]
- end
- return fn(unpack(merged_args, 1, bound_args.n + args.n))
- end
-end
-
-function functional.compose(...)
- local functions = functional.table_pack(...)
- assert(functions.n > 0, "compose requires at least one function")
- return function(...)
- local result = functional.table_pack(...)
- for i = functions.n, 1, -1 do
- result = functional.table_pack(functions[i](unpack(result, 1, result.n)))
- end
- return unpack(result, 1, result.n)
- end
-end
-
----@generic T
----@param filter_fn fun(item: T): boolean
----@return fun(list: T[]): T[]
-function functional.filter(filter_fn)
- return functional.partial(vim.tbl_filter, filter_fn)
-end
-
----@generic T
----@param fn fun(item: T, index: integer)
----@param list T[]
-function functional.each(fn, list)
- for k, v in pairs(list) do
- fn(v, k)
- end
-end
-
----@generic T
----@param predicates (fun(item: T): boolean)[]
----@return fun(item: T): boolean
-function functional.all_pass(predicates)
- return function(item)
- for i = 1, #predicates do
- if not predicates[i](item) then
- return false
- end
- end
- return true
- end
-end
-
----@generic T
----@param predicate fun(item: T): boolean
----@return fun(item: T): boolean
-function functional.negate(predicate)
- return function(...)
- return not predicate(...)
- end
-end
-
----@param index any
----@return fun(obj: table): any
-function functional.prop(index)
- return function(obj)
- return obj[index]
- end
-end
-
----@param condition fun(...): boolean
----@param a fun(...): any
----@param b fun(...): any
----@return fun(...): any
-function functional.if_else(condition, a, b)
- return function(...)
- if condition(...) then
- return a(...)
- else
- return b(...)
- end
- end
-end
-
----@param pattern string
-function functional.matches(pattern)
- ---@param str string
- return function(str)
- return str:match(pattern) ~= nil
- end
-end
-
-functional.T = functional.always(true)
-functional.F = functional.always(false)
-
-return functional
diff --git a/lua/nvim-lsp-installer/core/functional/data.lua b/lua/nvim-lsp-installer/core/functional/data.lua
new file mode 100644
index 00000000..da6f1efd
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/data.lua
@@ -0,0 +1,30 @@
+local _ = {}
+
+_.table_pack = function(...)
+ return { n = select("#", ...), ... }
+end
+
+---@generic T : string
+---@param values T[]
+---@return table<T, T>
+_.enum = function(values)
+ local result = {}
+ for i = 1, #values do
+ local v = values[i]
+ result[v] = v
+ end
+ return result
+end
+
+---@generic T
+---@param list T[]
+---@return table<T, boolean>
+_.set_of = function(list)
+ local set = {}
+ for i = 1, #list do
+ set[list[i]] = true
+ end
+ return set
+end
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/function.lua b/lua/nvim-lsp-installer/core/functional/function.lua
new file mode 100644
index 00000000..0d70aa92
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/function.lua
@@ -0,0 +1,89 @@
+local data = require "nvim-lsp-installer.core.functional.data"
+
+local _ = {}
+
+---@generic T : fun(...)
+---@param fn T
+---@param arity integer
+---@return T
+_.curryN = function(fn, arity)
+ return function(...)
+ local args = data.table_pack(...)
+ if args.n >= arity then
+ return fn(unpack(args, 1, arity))
+ else
+ return _.curryN(_.partial(fn, unpack(args, 1, args.n)), arity - args.n)
+ end
+ end
+end
+
+_.compose = function(...)
+ local functions = data.table_pack(...)
+ assert(functions.n > 0, "compose requires at least one function")
+ return function(...)
+ local result = data.table_pack(...)
+ for i = functions.n, 1, -1 do
+ result = data.table_pack(functions[i](unpack(result, 1, result.n)))
+ end
+ return unpack(result, 1, result.n)
+ end
+end
+
+---@generic T
+---@param fn fun(...): T
+---@return fun(...): T
+_.partial = function(fn, ...)
+ local bound_args = data.table_pack(...)
+ return function(...)
+ local args = data.table_pack(...)
+ local merged_args = {}
+ for i = 1, bound_args.n do
+ merged_args[i] = bound_args[i]
+ end
+ for i = 1, args.n do
+ merged_args[bound_args.n + i] = args[i]
+ end
+ return fn(unpack(merged_args, 1, bound_args.n + args.n))
+ end
+end
+
+_.identity = function(a)
+ return a
+end
+
+_.always = function(a)
+ return function()
+ return a
+ end
+end
+
+_.T = _.always(true)
+_.F = _.always(false)
+
+---@generic T : fun(...)
+---@param fn T
+---@param cache_key_generator (fun(...): string | nil)|nil
+---@return T
+_.memoize = function(fn, cache_key_generator)
+ cache_key_generator = cache_key_generator or _.identity
+ local cache = {}
+ return function(...)
+ local key = cache_key_generator(...)
+ if not cache[key] then
+ cache[key] = data.table_pack(fn(...))
+ end
+ return unpack(cache[key], 1, cache[key].n)
+ end
+end
+
+---@generic T
+---@param fn fun(): T
+---@return fun(): T
+_.lazy = function(fn)
+ local memoized = _.memoize(fn, _.always "lazyval")
+ return function()
+ return memoized()
+ end
+end
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/init.lua b/lua/nvim-lsp-installer/core/functional/init.lua
new file mode 100644
index 00000000..45a09ea6
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/init.lua
@@ -0,0 +1,89 @@
+local _ = {}
+
+-- data
+local data = require "nvim-lsp-installer.core.functional.data"
+_.table_pack = data.table_pack
+_.enum = data.enum
+_.set_of = data.set_of
+
+-- function
+local fun = require "nvim-lsp-installer.core.functional.function"
+_.curryN = fun.curryN
+_.compose = fun.compose
+_.partial = fun.partial
+_.identity = fun.identity
+_.always = fun.always
+_.T = fun.T
+_.F = fun.F
+_.memoize = fun.memoize
+_.lazy = fun.lazy
+
+-- list
+local list = require "nvim-lsp-installer.core.functional.list"
+_.reverse = list.reverse
+_.list_not_nil = list.list_not_nil
+_.list_copy = list.list_copy
+_.find_first = list.find_first
+_.any = list.any
+_.filter = list.filter
+_.map = list.map
+_.each = list.each
+
+-- relation
+local relation = require "nvim-lsp-installer.core.functional.relation"
+_.equals = relation.equals
+_.prop_eq = relation.prop_eq
+_.prop_satisfies = relation.prop_satisfies
+
+-- logic
+local logic = require "nvim-lsp-installer.core.functional.logic"
+_.all_pass = logic.all_pass
+_.if_else = logic.if_else
+_.is_not = logic.is_not
+_.cond = logic.cond
+
+-- number
+local number = require "nvim-lsp-installer.core.functional.number"
+_.negate = number.negate
+_.gt = number.gt
+_.gte = number.gte
+_.lt = number.lt
+_.lte = number.lte
+_.inc = number.inc
+_.dec = number.dec
+
+-- string
+local string = require "nvim-lsp-installer.core.functional.string"
+_.matches = string.matches
+_.format = string.format
+
+-- table
+local tbl = require "nvim-lsp-installer.core.functional.table"
+_.prop = tbl.prop
+
+-- type
+local typ = require "nvim-lsp-installer.core.functional.type"
+_.is_nil = typ.is_nil
+_.is = typ.is
+
+-- TODO do something else with these
+
+_.coalesce = function(...)
+ local args = _.table_pack(...)
+ for i = 1, args.n do
+ local variable = args[i]
+ if variable ~= nil then
+ return variable
+ end
+ end
+end
+
+_.when = function(condition, value)
+ return condition and value or nil
+end
+
+_.lazy_when = function(condition, value)
+ return condition and value() or nil
+end
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/list.lua b/lua/nvim-lsp-installer/core/functional/list.lua
new file mode 100644
index 00000000..666de4d3
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/list.lua
@@ -0,0 +1,80 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+local data = require "nvim-lsp-installer.core.functional.data"
+
+local _ = {}
+
+---@generic T
+---@param list T[]
+---@return T[]
+_.reverse = function(list)
+ local result = {}
+ for i = #list, 1, -1 do
+ result[#result + 1] = list[i]
+ end
+ return result
+end
+
+_.list_not_nil = function(...)
+ local result = {}
+ local args = data.table_pack(...)
+ for i = 1, args.n do
+ if args[i] ~= nil then
+ result[#result + 1] = args[i]
+ end
+ end
+ return result
+end
+
+---@generic T
+---@param predicate fun(item: T): boolean
+---@param list T[]
+---@return T | nil
+_.find_first = fun.curryN(function(predicate, list)
+ local result
+ for i = 1, #list do
+ local entry = list[i]
+ if predicate(entry) then
+ return entry
+ end
+ end
+ return result
+end, 2)
+
+---@generic T
+---@param predicate fun(item: T): boolean
+---@param list T[]
+---@return boolean
+_.any = fun.curryN(function(predicate, list)
+ for i = 1, #list do
+ if predicate(list[i]) then
+ return true
+ end
+ end
+ return false
+end, 2)
+
+---@generic T
+---@param filter_fn fun(item: T): boolean
+---@return fun(list: T[]): T[]
+_.filter = fun.curryN(vim.tbl_filter, 2)
+
+---@generic T
+---@param map_fn fun(item: T): boolean
+---@return fun(list: T[]): T[]
+_.map = fun.curryN(vim.tbl_map, 2)
+
+---@generic T
+---@param fn fun(item: T, index: integer)
+---@param list T[]
+_.each = fun.curryN(function(fn, list)
+ for k, v in pairs(list) do
+ fn(v, k)
+ end
+end, 2)
+
+---@generic T
+---@param list T[]
+---@return T[] @A shallow copy of the list.
+_.list_copy = _.map(fun.identity)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/logic.lua b/lua/nvim-lsp-installer/core/functional/logic.lua
new file mode 100644
index 00000000..262f04a8
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/logic.lua
@@ -0,0 +1,44 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+
+local _ = {}
+
+---@generic T
+---@param predicates (fun(item: T): boolean)[]
+---@return fun(item: T): boolean
+_.all_pass = fun.curryN(function(predicates, item)
+ for i = 1, #predicates do
+ if not predicates[i](item) then
+ return false
+ end
+ end
+ return true
+end, 2)
+
+---@generic T
+---@param predicate fun(item: T): boolean
+---@param a fun(item: T): any
+---@param b fun(item: T): any
+---@param value T
+_.if_else = fun.curryN(function(predicate, a, b, value)
+ if predicate(value) then
+ return a(value)
+ else
+ return b(value)
+ end
+end, 4)
+
+---@param value boolean
+_.is_not = function(value)
+ return not value
+end
+
+_.cond = fun.curryN(function(predicate_transformer_pairs, value)
+ for _, pair in ipairs(predicate_transformer_pairs) do
+ local predicate, transformer = pair[1], pair[2]
+ if predicate(value) then
+ return transformer(value)
+ end
+ end
+end, 2)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/number.lua b/lua/nvim-lsp-installer/core/functional/number.lua
new file mode 100644
index 00000000..b123eb20
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/number.lua
@@ -0,0 +1,34 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+
+local _ = {}
+
+---@param number number
+_.negate = function(number)
+ return -number
+end
+
+_.gt = fun.curryN(function(number, value)
+ return value > number
+end, 2)
+
+_.gte = fun.curryN(function(number, value)
+ return value >= number
+end, 2)
+
+_.lt = fun.curryN(function(number, value)
+ return value < number
+end, 2)
+
+_.lte = fun.curryN(function(number, value)
+ return value <= number
+end, 2)
+
+_.inc = fun.curryN(function(increment, value)
+ return value + increment
+end, 2)
+
+_.dec = fun.curryN(function(decrement, value)
+ return value - decrement
+end, 2)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/relation.lua b/lua/nvim-lsp-installer/core/functional/relation.lua
new file mode 100644
index 00000000..d9786a6a
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/relation.lua
@@ -0,0 +1,17 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+
+local _ = {}
+
+_.equals = fun.curryN(function(expected, value)
+ return value == expected
+end, 2)
+
+_.prop_eq = fun.curryN(function(property, value, tbl)
+ return tbl[property] == value
+end, 3)
+
+_.prop_satisfies = fun.curryN(function(predicate, property, tbl)
+ return predicate(tbl[property])
+end, 3)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/string.lua b/lua/nvim-lsp-installer/core/functional/string.lua
new file mode 100644
index 00000000..0061a33e
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/string.lua
@@ -0,0 +1,17 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+
+local _ = {}
+
+---@param pattern string
+---@param str string
+_.matches = fun.curryN(function(pattern, str)
+ return str:match(pattern) ~= nil
+end, 2)
+
+---@param template string
+---@param string string
+_.format = fun.curryN(function(template, string)
+ return template:format(string)
+end, 2)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/table.lua b/lua/nvim-lsp-installer/core/functional/table.lua
new file mode 100644
index 00000000..37aee19e
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/table.lua
@@ -0,0 +1,9 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+
+local _ = {}
+
+_.prop = fun.curryN(function(index, tbl)
+ return tbl[index]
+end, 2)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/functional/type.lua b/lua/nvim-lsp-installer/core/functional/type.lua
new file mode 100644
index 00000000..23d961ba
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/functional/type.lua
@@ -0,0 +1,14 @@
+local fun = require "nvim-lsp-installer.core.functional.function"
+local rel = require "nvim-lsp-installer.core.functional.relation"
+
+local _ = {}
+
+_.is_nil = rel.equals(nil)
+
+---@param typ type
+---@param value any
+_.is = fun.curryN(function(typ, value)
+ return type(value) == typ
+end, 2)
+
+return _
diff --git a/lua/nvim-lsp-installer/core/managers/composer/init.lua b/lua/nvim-lsp-installer/core/managers/composer/init.lua
index 338b3fef..e2330c40 100644
--- a/lua/nvim-lsp-installer/core/managers/composer/init.lua
+++ b/lua/nvim-lsp-installer/core/managers/composer/init.lua
@@ -1,4 +1,4 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local process = require "nvim-lsp-installer.core.process"
local path = require "nvim-lsp-installer.core.path"
local Result = require "nvim-lsp-installer.core.result"
@@ -6,8 +6,6 @@ local spawn = require "nvim-lsp-installer.core.spawn"
local Optional = require "nvim-lsp-installer.core.optional"
local installer = require "nvim-lsp-installer.core.installer"
-local list_copy, list_find_first = functional.list_copy, functional.list_find_first
-
local M = {}
---@param packages string[]
@@ -34,7 +32,7 @@ end
---@param packages string[] The composer packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
function M.require(packages)
local ctx = installer.context()
- local pkgs = list_copy(packages)
+ local pkgs = _.list_copy(packages)
if not ctx.fs:file_exists "composer.json" then
ctx.spawn.composer { "init", "--no-interaction", "--stability=stable" }
@@ -77,7 +75,7 @@ function M.check_outdated_primary_package(receipt, install_dir)
cwd = install_dir,
}):map_catching(function(result)
local outdated_packages = vim.json.decode(result.stdout)
- local outdated_package = list_find_first(function(package)
+ local outdated_package = _.find_first(function(package)
return package.name == receipt.primary_source.package
end, outdated_packages.installed)
return Optional.of_nilable(outdated_package)
diff --git a/lua/nvim-lsp-installer/core/managers/gem/init.lua b/lua/nvim-lsp-installer/core/managers/gem/init.lua
index 56385337..e70c89c7 100644
--- a/lua/nvim-lsp-installer/core/managers/gem/init.lua
+++ b/lua/nvim-lsp-installer/core/managers/gem/init.lua
@@ -1,4 +1,4 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local process = require "nvim-lsp-installer.core.process"
local path = require "nvim-lsp-installer.core.path"
local Result = require "nvim-lsp-installer.core.result"
@@ -6,8 +6,6 @@ local spawn = require "nvim-lsp-installer.core.spawn"
local Optional = require "nvim-lsp-installer.core.optional"
local installer = require "nvim-lsp-installer.core.installer"
-local list_copy, list_find_first = functional.list_copy, functional.list_find_first
-
local M = {}
---@param packages string[]
@@ -33,7 +31,7 @@ end
---@param packages string[] @The Gem packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
function M.install(packages)
local ctx = installer.context()
- local pkgs = list_copy(packages or {})
+ local pkgs = _.list_copy(packages or {})
ctx.requested_version:if_present(function(version)
pkgs[1] = ("%s:%s"):format(pkgs[1], version)
@@ -105,7 +103,7 @@ function M.check_outdated_primary_package(receipt, install_dir)
local lines = vim.split(result.stdout, "\n")
local outdated_gems = vim.tbl_map(M.parse_outdated_gem, vim.tbl_filter(not_empty, lines))
- local outdated_gem = list_find_first(function(gem)
+ local outdated_gem = _.find_first(function(gem)
return gem.name == receipt.primary_source.package and gem.current_version ~= gem.latest_version
end, outdated_gems)
diff --git a/lua/nvim-lsp-installer/core/managers/github/client.lua b/lua/nvim-lsp-installer/core/managers/github/client.lua
index 7387723c..bf79fec6 100644
--- a/lua/nvim-lsp-installer/core/managers/github/client.lua
+++ b/lua/nvim-lsp-installer/core/managers/github/client.lua
@@ -1,19 +1,8 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local log = require "nvim-lsp-installer.log"
local fetch = require "nvim-lsp-installer.core.fetch"
local spawn = require "nvim-lsp-installer.core.spawn"
-local list_find_first, all_pass, always, prop, negate, compose, if_else, matches, T =
- functional.list_find_first,
- functional.all_pass,
- functional.always,
- functional.prop,
- functional.negate,
- functional.compose,
- functional.if_else,
- functional.matches,
- functional.T
-
local M = {}
---@alias GitHubReleaseAsset {url: string, id: integer, name: string, browser_download_url: string, created_at: string, updated_at: string, size: integer, download_count: integer}
@@ -56,13 +45,13 @@ end
---@param opts {include_prerelease: boolean, tag_name_pattern: string}
function M.release_predicate(opts)
- local is_not_draft = negate(prop "draft")
- local is_not_prerelease = negate(prop "prerelease")
- local tag_name_matches = compose(matches(opts.tag_name_pattern), prop "tag_name")
+ local is_not_draft = _.prop_eq("draft", false)
+ local is_not_prerelease = _.prop_eq("prerelease", false)
+ local tag_name_matches = _.prop_satisfies(_.matches(opts.tag_name_pattern), "tag_name")
- return all_pass {
- if_else(always(opts.include_prerelease), T, is_not_prerelease),
- if_else(always(opts.tag_name_pattern), tag_name_matches, T),
+ return _.all_pass {
+ _.if_else(_.always(opts.include_prerelease), _.T, is_not_prerelease),
+ _.if_else(_.always(opts.tag_name_pattern), tag_name_matches, _.T),
is_not_draft,
}
end
@@ -83,7 +72,7 @@ function M.fetch_latest_release(repo, opts)
function(releases)
local is_stable_release = M.release_predicate(opts)
---@type GitHubRelease|nil
- local latest_release = list_find_first(is_stable_release, releases)
+ local latest_release = _.find_first(is_stable_release, releases)
if not latest_release then
log.fmt_info("Failed to find latest release. repo=%s, opts=%s", repo, opts)
diff --git a/lua/nvim-lsp-installer/core/managers/pip3/init.lua b/lua/nvim-lsp-installer/core/managers/pip3/init.lua
index 7d599411..b6a82633 100644
--- a/lua/nvim-lsp-installer/core/managers/pip3/init.lua
+++ b/lua/nvim-lsp-installer/core/managers/pip3/init.lua
@@ -1,4 +1,4 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local settings = require "nvim-lsp-installer.settings"
local process = require "nvim-lsp-installer.core.process"
local path = require "nvim-lsp-installer.core.path"
@@ -8,8 +8,6 @@ local installer = require "nvim-lsp-installer.core.installer"
local Result = require "nvim-lsp-installer.core.result"
local spawn = require "nvim-lsp-installer.core.spawn"
-local list_find_first, list_copy, list_not_nil =
- functional.list_find_first, functional.list_copy, functional.list_not_nil
local VENV_DIR = "venv"
local M = {}
@@ -37,20 +35,20 @@ end
---@param packages string[] @The pip packages to install. The first item in this list will be the recipient of the requested version, if set.
function M.install(packages)
local ctx = installer.context()
- local pkgs = list_copy(packages)
+ local pkgs = _.list_copy(packages)
ctx.requested_version:if_present(function(version)
pkgs[1] = ("%s==%s"):format(pkgs[1], version)
end)
- local executables = platform.is_win and list_not_nil(vim.g.python3_host_prog, "python", "python3")
- or list_not_nil(vim.g.python3_host_prog, "python3", "python")
+ local executables = platform.is_win and _.list_not_nil(vim.g.python3_host_prog, "python", "python3")
+ or _.list_not_nil(vim.g.python3_host_prog, "python3", "python")
-- pip3 will hardcode the full path to venv executables, so we need to promote cwd to make sure pip uses the final destination path.
ctx:promote_cwd()
-- Find first executable that manages to create venv
- local executable = list_find_first(function(executable)
+ local executable = _.find_first(function(executable)
return pcall(ctx.spawn[executable], { "-m", "venv", VENV_DIR })
end, executables)
@@ -102,7 +100,7 @@ function M.check_outdated_primary_package(receipt, install_dir)
---@type PipOutdatedPackage[]
local packages = vim.json.decode(result.stdout)
- local outdated_primary_package = list_find_first(function(outdated_package)
+ local outdated_primary_package = _.find_first(function(outdated_package)
return outdated_package.name == normalized_package
and outdated_package.version ~= outdated_package.latest_version
end, packages)
@@ -136,7 +134,7 @@ function M.get_installed_primary_package_version(receipt, install_dir)
}):map_catching(function(result)
local pip_packages = vim.json.decode(result.stdout)
local normalized_pip_package = M.normalize_package(receipt.primary_source.package)
- local pip_package = list_find_first(function(package)
+ local pip_package = _.find_first(function(package)
return package.name == normalized_pip_package
end, pip_packages)
return Optional.of_nilable(pip_package)
diff --git a/lua/nvim-lsp-installer/core/process.lua b/lua/nvim-lsp-installer/core/process.lua
index 98a7e5a1..9841c11c 100644
--- a/lua/nvim-lsp-installer/core/process.lua
+++ b/lua/nvim-lsp-installer/core/process.lua
@@ -1,10 +1,8 @@
local log = require "nvim-lsp-installer.log"
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local platform = require "nvim-lsp-installer.core.platform"
local uv = vim.loop
-local list_any = functional.list_any
-
---@alias luv_pipe any
---@alias luv_handle any
@@ -46,7 +44,7 @@ end
---@param env table<string, string>
---@param excluded_var_names string[]|nil
function M.graft_env(env, excluded_var_names)
- local excluded_var_names_set = excluded_var_names and functional.set_of(excluded_var_names) or {}
+ local excluded_var_names_set = excluded_var_names and _.set_of(excluded_var_names) or {}
local merged_env = {}
for key, val in pairs(initial_environ) do
if not excluded_var_names_set[key] and env[key] == nil then
@@ -64,7 +62,7 @@ end
---@param env_list string[]
local function sanitize_env_list(env_list)
local sanitized_list = {}
- for _, env in ipairs(env_list) do
+ for __, env in ipairs(env_list) do
local safe_envs = {
"GO111MODULE",
"GOBIN",
@@ -73,7 +71,7 @@ local function sanitize_env_list(env_list)
"GEM_HOME",
"GEM_PATH",
}
- local is_safe_env = list_any(function(safe_env)
+ local is_safe_env = _.any(function(safe_env)
return env:find(safe_env .. "=") == 1
end, safe_envs)
if is_safe_env then
diff --git a/lua/nvim-lsp-installer/core/ui/init.lua b/lua/nvim-lsp-installer/core/ui/init.lua
index 1f07855d..5b855949 100644
--- a/lua/nvim-lsp-installer/core/ui/init.lua
+++ b/lua/nvim-lsp-installer/core/ui/init.lua
@@ -1,4 +1,4 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local M = {}
---@alias NodeType
@@ -35,11 +35,13 @@ function M.HlTextNode(lines_with_span_tuples)
return node
end
+local create_unhighlighted_lines = _.map(function(line)
+ return { { line, "" } }
+end)
+
---@param lines string[]
function M.Text(lines)
- return M.HlTextNode(functional.list_map(function(line)
- return { { line, "" } }
- end, lines))
+ return M.HlTextNode(create_unhighlighted_lines(lines))
end
---@alias CascadingStyle
diff --git a/lua/nvim-lsp-installer/servers/angularls/init.lua b/lua/nvim-lsp-installer/servers/angularls/init.lua
index 90209c3a..c10d0a97 100644
--- a/lua/nvim-lsp-installer/servers/angularls/init.lua
+++ b/lua/nvim-lsp-installer/servers/angularls/init.lua
@@ -1,16 +1,12 @@
local server = require "nvim-lsp-installer.server"
local platform = require "nvim-lsp-installer.core.platform"
local npm = require "nvim-lsp-installer.core.managers.npm"
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local path = require "nvim-lsp-installer.core.path"
-local map = functional.list_map
-
-local function append_node_modules(dirs)
- return map(function(dir)
- return path.concat { dir, "node_modules" }
- end, dirs)
-end
+local append_node_modules = _.map(function(dir)
+ return path.concat { dir, "node_modules" }
+end)
return function(name, root_dir)
local function get_cmd(workspace_dir)
diff --git a/lua/nvim-lsp-installer/servers/dhall_lsp_server/init.lua b/lua/nvim-lsp-installer/servers/dhall_lsp_server/init.lua
index 0d35a943..484ae389 100644
--- a/lua/nvim-lsp-installer/servers/dhall_lsp_server/init.lua
+++ b/lua/nvim-lsp-installer/servers/dhall_lsp_server/init.lua
@@ -2,13 +2,11 @@ local server = require "nvim-lsp-installer.server"
local path = require "nvim-lsp-installer.core.path"
local process = require "nvim-lsp-installer.core.process"
local platform = require "nvim-lsp-installer.core.platform"
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local std = require "nvim-lsp-installer.core.managers.std"
local github_client = require "nvim-lsp-installer.core.managers.github.client"
local Optional = require "nvim-lsp-installer.core.optional"
-local coalesce, when, list_find_first = functional.coalesce, functional.when, functional.list_find_first
-
return function(name, root_dir)
return server.Server:new {
name = name,
@@ -29,17 +27,14 @@ return function(name, root_dir)
:get_or_throw()
local asset_name_pattern = assert(
- coalesce(
- when(platform.is_mac, "dhall%-lsp%-server%-.+%-x86_64%-macos.tar.bz2"),
- when(platform.is_linux, "dhall%-lsp%-server%-.+%-x86_64%-linux.tar.bz2"),
- when(platform.is_win, "dhall%-lsp%-server%-.+%-x86_64%-windows.zip")
+ _.coalesce(
+ _.when(platform.is.mac, "dhall%-lsp%-server%-.+%-x86_64%-macos.tar.bz2"),
+ _.when(platform.is.linux_x64, "dhall%-lsp%-server%-.+%-x86_64%-linux.tar.bz2"),
+ _.when(platform.is.win_x64, "dhall%-lsp%-server%-.+%-x86_64%-windows.zip")
)
)
- local dhall_lsp_server_asset = list_find_first(
- ---@param asset GitHubReleaseAsset
- function(asset)
- return asset.name:match(asset_name_pattern)
- end,
+ local dhall_lsp_server_asset = _.find_first(
+ _.prop_satisfies(_.matches(asset_name_pattern), "name"),
gh_release.assets
)
Optional.of_nilable(dhall_lsp_server_asset)
diff --git a/lua/nvim-lsp-installer/servers/init.lua b/lua/nvim-lsp-installer/servers/init.lua
index 8ff7efaf..9d78d651 100644
--- a/lua/nvim-lsp-installer/servers/init.lua
+++ b/lua/nvim-lsp-installer/servers/init.lua
@@ -1,4 +1,4 @@
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local path = require "nvim-lsp-installer.core.path"
local fs = require "nvim-lsp-installer.core.fs"
local settings = require "nvim-lsp-installer.settings"
@@ -31,7 +31,7 @@ local INSTALL_DIRS = {
["yamlls"] = "yaml",
}
-local CORE_SERVERS = functional.set_of {
+local CORE_SERVERS = _.set_of {
"angularls",
"ansiblels",
"arduino_language_server",
@@ -175,7 +175,7 @@ local function scan_server_roots()
result[#result + 1] = entry.name
end
end
- cached_server_roots = functional.set_of(result)
+ cached_server_roots = _.set_of(result)
vim.schedule(function()
cached_server_roots = nil
end)
@@ -239,17 +239,14 @@ function M.get_server(server_name)
):format(server_name, "https://github.com/williamboman/nvim-lsp-installer", server_factory)
end
----@param server_names string[]
----@return Server[]
-local function resolve_servers(server_names)
- return functional.list_map(function(server_name)
- local ok, server = M.get_server(server_name)
- if not ok then
- error(server)
- end
- return server
- end, server_names)
-end
+---@type fun(server_names: string): Server[]
+local resolve_servers = _.map(function(server_name)
+ local ok, server = M.get_server(server_name)
+ if not ok then
+ error(server)
+ end
+ return server
+end)
---@return string[]
function M.get_available_server_names()
diff --git a/lua/nvim-lsp-installer/ui/components/settings-schema.lua b/lua/nvim-lsp-installer/ui/components/settings-schema.lua
index 4954d456..04d8e0d5 100644
--- a/lua/nvim-lsp-installer/ui/components/settings-schema.lua
+++ b/lua/nvim-lsp-installer/ui/components/settings-schema.lua
@@ -1,8 +1,6 @@
-- Here be dragons
local Ui = require "nvim-lsp-installer.core.ui"
-local functional = require "nvim-lsp-installer.core.functional"
-
-local list_map = functional.list_map
+local _ = require "nvim-lsp-installer.core.functional"
local property_type_highlights = {
["string"] = "String",
@@ -135,7 +133,7 @@ local function ServerSettingsSchema(server, schema, key, level, key_width, compo
heading,
toggle_expand_keybind,
Ui.When(node_is_expanded, function()
- local description = list_map(function(line)
+ local description = _.map(function(line)
return { { line, "Comment" } }
end, vim.split(schema.description or "No description available.", "\n"))
diff --git a/lua/nvim-lsp-installer/ui/init.lua b/lua/nvim-lsp-installer/ui/init.lua
index 48791d2a..73548d1f 100644
--- a/lua/nvim-lsp-installer/ui/init.lua
+++ b/lua/nvim-lsp-installer/ui/init.lua
@@ -3,7 +3,7 @@ local Ui = require "nvim-lsp-installer.core.ui"
local display = require "nvim-lsp-installer.core.ui.display"
local fs = require "nvim-lsp-installer.core.fs"
local log = require "nvim-lsp-installer.log"
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local settings = require "nvim-lsp-installer.settings"
local lsp_servers = require "nvim-lsp-installer.servers"
local JobExecutionPool = require "nvim-lsp-installer.jobs.pool"
@@ -35,7 +35,7 @@ local function Indent(children)
return Ui.CascadingStyleNode({ "INDENT" }, children)
end
-local create_vader = functional.memoize(
+local create_vader = _.memoize(
---@param saber_ticks number
function(saber_ticks)
-- stylua: ignore start
@@ -88,7 +88,7 @@ local function Help(is_current_settings_expanded, vader_saber_ticks)
{ "Keyboard shortcuts", "LspInstallerLabel" },
},
},
- functional.list_map(function(keymap_tuple)
+ _.map(function(keymap_tuple)
return { { keymap_tuple[1], "LspInstallerMuted" }, { keymap_tuple[2], "LspInstallerHighlighted" } }
end, keymap_tuples)
)),
@@ -157,7 +157,7 @@ local function Help(is_current_settings_expanded, vader_saber_ticks)
Ui.Keybind("<CR>", "TOGGLE_EXPAND_CURRENT_SETTINGS", nil),
Ui.When(is_current_settings_expanded, function()
local settings_split_by_newline = vim.split(vim.inspect(settings.current), "\n")
- local current_settings = functional.list_map(function(line)
+ local current_settings = _.map(function(line)
return { { line, "LspInstallerMuted" } }
end, settings_split_by_newline)
return Ui.HlTextNode(current_settings)
@@ -211,11 +211,11 @@ end
---@param server ServerState
local function ServerMetadata(server)
- return Ui.Node(functional.list_not_nil(
- functional.lazy_when(server.is_installed and server.deprecated, function()
- return Ui.Node(functional.list_not_nil(
+ return Ui.Node(_.list_not_nil(
+ _.lazy_when(server.is_installed and server.deprecated, function()
+ return Ui.Node(_.list_not_nil(
Ui.HlTextNode { server.deprecated.message, "Comment" },
- functional.lazy_when(server.deprecated.replace_with, function()
+ _.lazy_when(server.deprecated.replace_with, function()
return Ui.Node {
Ui.HlTextNode {
{
@@ -229,8 +229,8 @@ local function ServerMetadata(server)
end)
))
end),
- Ui.Table(functional.list_not_nil(
- functional.lazy_when(server.is_installed, function()
+ Ui.Table(_.list_not_nil(
+ _.lazy_when(server.is_installed, function()
return {
{ "version", "LspInstallerMuted" },
server.installed_version_err and {
@@ -239,7 +239,7 @@ local function ServerMetadata(server)
} or { server.installed_version or "Loading...", "" },
}
end),
- functional.lazy_when(#server.metadata.outdated_packages > 0, function()
+ _.lazy_when(#server.metadata.outdated_packages > 0, function()
return {
{ "latest version", "LspInstallerGreen" },
{
@@ -248,17 +248,17 @@ local function ServerMetadata(server)
},
}
end),
- functional.lazy_when(server.metadata.install_timestamp_seconds, function()
+ _.lazy_when(server.metadata.install_timestamp_seconds, function()
return {
{ "installed", "LspInstallerMuted" },
{ format_time(server.metadata.install_timestamp_seconds), "" },
}
end),
- functional.when(not server.is_installed, {
+ _.when(not server.is_installed, {
{ "filetypes", "LspInstallerMuted" },
{ server.metadata.filetypes, "" },
}),
- functional.when(server.is_installed, {
+ _.when(server.is_installed, {
{ "path", "LspInstallerMuted" },
{ server.metadata.install_dir, "String" },
}),
@@ -323,17 +323,17 @@ end
---@param servers ServerState[]
---@param props ServerGroupProps
local function InstalledServers(servers, props)
- return Ui.Node(functional.list_map(
+ return Ui.Node(_.map(
---@param server ServerState
function(server)
local is_expanded = props.expanded_server == server.name
return Ui.Node {
Ui.HlTextNode {
- functional.list_not_nil(
+ _.list_not_nil(
{ settings.current.ui.icons.server_installed, "LspInstallerGreen" },
{ " " .. server.name .. " ", "" },
{ server.hints, "Comment" },
- functional.when(server.deprecated, { " deprecated", "LspInstallerOrange" })
+ _.when(server.deprecated, { " deprecated", "LspInstallerOrange" })
),
},
Ui.When(
@@ -363,7 +363,7 @@ end
---@param server ServerState
local function TailedOutput(server)
- return Ui.HlTextNode(functional.list_map(function(line)
+ return Ui.HlTextNode(_.map(function(line)
return { { line, "LspInstallerMuted" } }
end, server.installer.tailed_output))
end
@@ -382,21 +382,21 @@ end
---@param servers ServerState[]
local function PendingServers(servers)
- return Ui.Node(functional.list_map(function(_server)
+ return Ui.Node(_.map(function(_server)
---@type ServerState
local server = _server
local has_failed = server.installer.has_run or server.uninstaller.has_run
local note = has_failed and "(failed)" or (server.installer.is_queued and "(queued)" or "(installing)")
return Ui.Node {
Ui.HlTextNode {
- functional.list_not_nil(
+ _.list_not_nil(
{
settings.current.ui.icons.server_pending,
has_failed and "LspInstallerError" or "LspInstallerOrange",
},
{ " " .. server.name, server.installer.is_running and "" or "LspInstallerMuted" },
{ " " .. note, "Comment" },
- functional.when(not has_failed, {
+ _.when(not has_failed, {
(" " .. get_last_non_empty_line(server.installer.tailed_output)),
"Comment",
})
@@ -419,22 +419,22 @@ end
---@param servers ServerState[]
---@param props ServerGroupProps
local function UninstalledServers(servers, props)
- return Ui.Node(functional.list_map(function(_server)
+ return Ui.Node(_.map(function(_server)
---@type ServerState
local server = _server
local is_prioritized = props.prioritized_servers[server.name]
local is_expanded = props.expanded_server == server.name
return Ui.Node {
Ui.HlTextNode {
- functional.list_not_nil(
+ _.list_not_nil(
{
settings.current.ui.icons.server_uninstalled,
is_prioritized and "LspInstallerHighlighted" or "LspInstallerMuted",
},
{ " " .. server.name .. " ", "LspInstallerMuted" },
{ server.hints, "Comment" },
- functional.when(server.uninstaller.has_run, { " (uninstalled) ", "Comment" }),
- functional.when(server.deprecated, { "deprecated ", "LspInstallerOrange" })
+ _.when(server.uninstaller.has_run, { " (uninstalled) ", "Comment" }),
+ _.when(server.deprecated, { "deprecated ", "LspInstallerOrange" })
),
},
Ui.Keybind(settings.current.ui.keymaps.toggle_server_expand, "EXPAND_SERVER", { server.name }),
@@ -468,7 +468,7 @@ local function ServerGroup(props)
subtitle = props.subtitle,
count = total_server_count,
},
- Indent(functional.list_map(function(servers)
+ Indent(_.map(function(servers)
return props.renderer(servers, props)
end, props.servers)),
}
@@ -954,7 +954,7 @@ local function init(all_servers)
mutate_state(function(state)
state.is_showing_help = false
- state.prioritized_servers = functional.set_of(prioritized_servers)
+ state.prioritized_servers = _.set_of(prioritized_servers)
end)
if not has_opened then
diff --git a/scripts/autogen_metadata.lua b/scripts/autogen_metadata.lua
index 608555a7..137055e0 100644
--- a/scripts/autogen_metadata.lua
+++ b/scripts/autogen_metadata.lua
@@ -1,12 +1,10 @@
local a = require "nvim-lsp-installer.core.async"
local Path = require "nvim-lsp-installer.core.path"
local fetch = require "nvim-lsp-installer.core.fetch"
-local functional = require "nvim-lsp-installer.core.functional"
+local _ = require "nvim-lsp-installer.core.functional"
local servers = require "nvim-lsp-installer.servers"
local fs = require "nvim-lsp-installer.core.fs"
-local coalesce = functional.coalesce
-
local generated_dir = Path.concat { vim.fn.getcwd(), "lua", "nvim-lsp-installer", "_generated" }
local schemas_dir = Path.concat { generated_dir, "schemas" }
@@ -54,7 +52,7 @@ local function get_supported_filetypes(server)
end
local config = get_lspconfig(server.name)
local default_options = server:get_default_options()
- local filetypes = coalesce(
+ local filetypes = _.coalesce(
-- nvim-lsp-installer options has precedence
default_options and default_options.filetypes,
config.default_config.filetypes,
@@ -99,9 +97,7 @@ local function create_autocomplete_map()
local autocomplete_candidates = {}
for language, language_servers in pairs(language_map) do
- local non_deprecated_servers = vim.tbl_filter(function(server)
- return server.deprecated == nil
- end, language_servers)
+ local non_deprecated_servers = _.filter(_.prop_eq("deprecated", nil), language_servers)
local is_candidate = #non_deprecated_servers > 0
if #non_deprecated_servers == 1 then
@@ -110,9 +106,7 @@ local function create_autocomplete_map()
end
if is_candidate then
- autocomplete_candidates[language] = vim.tbl_map(function(server)
- return server.name
- end, non_deprecated_servers)
+ autocomplete_candidates[language] = _.map(_.prop "name", non_deprecated_servers)
table.sort(autocomplete_candidates[language])
end
end
diff --git a/tests/core/functional/data_spec.lua b/tests/core/functional/data_spec.lua
new file mode 100644
index 00000000..b89176e2
--- /dev/null
+++ b/tests/core/functional/data_spec.lua
@@ -0,0 +1,28 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: data", function()
+ it("creates enums", function()
+ local colors = _.enum {
+ "BLUE",
+ "YELLOW",
+ }
+ assert.same({
+ ["BLUE"] = "BLUE",
+ ["YELLOW"] = "YELLOW",
+ }, colors)
+ end)
+
+ it("creates sets", function()
+ local colors = _.set_of {
+ "BLUE",
+ "YELLOW",
+ "BLUE",
+ "RED",
+ }
+ assert.same({
+ ["BLUE"] = true,
+ ["YELLOW"] = true,
+ ["RED"] = true,
+ }, colors)
+ end)
+end)
diff --git a/tests/core/functional/function_spec.lua b/tests/core/functional/function_spec.lua
new file mode 100644
index 00000000..4b9cbba6
--- /dev/null
+++ b/tests/core/functional/function_spec.lua
@@ -0,0 +1,142 @@
+local spy = require "luassert.spy"
+local match = require "luassert.match"
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: function", function()
+ it("curries functions", function()
+ local function sum(...)
+ local res = 0
+ for i = 1, select("#", ...) do
+ res = res + select(i, ...)
+ end
+ return res
+ end
+ local arity0 = _.curryN(sum, 0)
+ local arity1 = _.curryN(sum, 1)
+ local arity2 = _.curryN(sum, 2)
+ local arity3 = _.curryN(sum, 3)
+
+ assert.equals(0, arity0(42))
+ assert.equals(42, arity1(42))
+ assert.equals(3, arity2(1)(2))
+ assert.equals(3, arity2(1, 2))
+ assert.equals(6, arity3(1)(2)(3))
+ assert.equals(6, arity3(1, 2, 3))
+
+ -- should discard superfluous args
+ assert.equals(0, arity1(0, 10, 20, 30))
+ end)
+
+ it("coalesces first non-nil value", function()
+ assert.equal("Hello World!", _.coalesce(nil, nil, "Hello World!", ""))
+ end)
+
+ it("should compose functions", function()
+ local function add(x)
+ return function(y)
+ return y + x
+ end
+ end
+ local function subtract(x)
+ return function(y)
+ return y - x
+ end
+ end
+ local function multiply(x)
+ return function(y)
+ return y * x
+ end
+ end
+
+ local big_maths = _.compose(add(1), subtract(3), multiply(5))
+
+ assert.equals(23, big_maths(5))
+ end)
+
+ it("should not allow composing no functions", function()
+ local e = assert.error(function()
+ _.compose()
+ end)
+ assert.equals("compose requires at least one function", e)
+ end)
+
+ it("should partially apply functions", function()
+ local funcy = spy.new()
+ local partially_funcy = _.partial(funcy, "a", "b", "c")
+ partially_funcy("d", "e", "f")
+ assert.spy(funcy).was_called_with("a", "b", "c", "d", "e", "f")
+ end)
+
+ it("should partially apply functions with nil arguments", function()
+ local funcy = spy.new()
+ local partially_funcy = _.partial(funcy, "a", nil, "c")
+ partially_funcy("d", nil, "f")
+ assert.spy(funcy).was_called_with("a", nil, "c", "d", nil, "f")
+ end)
+
+ it("memoizes functions with default cache mechanism", function()
+ local expensive_function = spy.new(function(s)
+ return s
+ end)
+ local memoized_fn = _.memoize(expensive_function)
+ assert.equal("key", memoized_fn "key")
+ assert.equal("key", memoized_fn "key")
+ assert.equal("new_key", memoized_fn "new_key")
+ assert.spy(expensive_function).was_called(2)
+ end)
+
+ it("memoizes function with custom cache mechanism", function()
+ local expensive_function = spy.new(function(arg1, arg2)
+ return arg1 .. arg2
+ end)
+ local memoized_fn = _.memoize(expensive_function, function(arg1, arg2)
+ return arg1 .. arg2
+ end)
+ assert.equal("key1key2", memoized_fn("key1", "key2"))
+ assert.equal("key1key2", memoized_fn("key1", "key2"))
+ assert.equal("key1key3", memoized_fn("key1", "key3"))
+ assert.spy(expensive_function).was_called(2)
+ end)
+
+ it("should evaluate functions lazily", function()
+ local impl = spy.new(function()
+ return {}, {}
+ end)
+ local lazy_fn = _.lazy(impl)
+ assert.spy(impl).was_called(0)
+ local a, b = lazy_fn()
+ assert.spy(impl).was_called(1)
+ assert.is_true(match.is_table()(a))
+ assert.is_true(match.is_table()(b))
+ local new_a, new_b = lazy_fn()
+ assert.spy(impl).was_called(1)
+ assert.is_true(match.is_ref(a)(new_a))
+ assert.is_true(match.is_ref(b)(new_b))
+ end)
+
+ it("should support nil return values in lazy functions", function()
+ local lazy_fn = _.lazy(function()
+ return nil, 2
+ end)
+ local a, b = lazy_fn()
+ assert.is_nil(a)
+ assert.equal(2, b)
+ end)
+
+ it("should provide identity value", function()
+ local obj = {}
+ assert.equals(2, _.identity(2))
+ assert.equals(obj, _.identity(obj))
+ end)
+
+ it("should always return bound value", function()
+ local obj = {}
+ assert.equals(2, _.always(2)())
+ assert.equals(obj, _.always(obj)())
+ end)
+
+ it("true is true and false is false", function()
+ assert.is_true(_.T())
+ assert.is_false(_.F())
+ end)
+end)
diff --git a/tests/core/functional/list_spec.lua b/tests/core/functional/list_spec.lua
new file mode 100644
index 00000000..c553a7d0
--- /dev/null
+++ b/tests/core/functional/list_spec.lua
@@ -0,0 +1,87 @@
+local spy = require "luassert.spy"
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: list", function()
+ it("should produce list without nils", function()
+ assert.same({ 1, 2, 3, 4 }, _.list_not_nil(nil, 1, 2, nil, 3, nil, 4, nil))
+ end)
+
+ it("makes a shallow copy of a list", function()
+ local list = { "BLUE", { nested = "TABLE" }, "RED" }
+ local list_copy = _.list_copy(list)
+ assert.same({ "BLUE", { nested = "TABLE" }, "RED" }, list_copy)
+ assert.is_not.is_true(list == list_copy)
+ assert.is_true(list[2] == list_copy[2])
+ end)
+
+ it("reverses lists", function()
+ local colors = { "BLUE", "YELLOW", "RED" }
+ assert.same({
+ "RED",
+ "YELLOW",
+ "BLUE",
+ }, _.reverse(colors))
+ -- should not modify in-place
+ assert.same({ "BLUE", "YELLOW", "RED" }, colors)
+ end)
+
+ it("maps over list", function()
+ local colors = { "BLUE", "YELLOW", "RED" }
+ assert.same(
+ {
+ "LIGHT_BLUE",
+ "LIGHT_YELLOW",
+ "LIGHT_RED",
+ },
+ _.map(function(color)
+ return "LIGHT_" .. color
+ end, colors)
+ )
+ -- should not modify in-place
+ assert.same({ "BLUE", "YELLOW", "RED" }, colors)
+ end)
+
+ it("finds first item that fulfills predicate", function()
+ local predicate = spy.new(function(item)
+ return item == "Waldo"
+ end)
+
+ assert.equal(
+ "Waldo",
+ _.find_first(predicate, {
+ "Where",
+ "On Earth",
+ "Is",
+ "Waldo",
+ "?",
+ })
+ )
+ assert.spy(predicate).was.called(4)
+ end)
+
+ it("determines whether any item in the list fulfills predicate", function()
+ local predicate = spy.new(function(item)
+ return item == "On Earth"
+ end)
+
+ assert.is_true(_.any(predicate, {
+ "Where",
+ "On Earth",
+ "Is",
+ "Waldo",
+ "?",
+ }))
+
+ assert.spy(predicate).was.called(2)
+ end)
+
+ it("should iterate list in .each", function()
+ local list = { "BLUE", "YELLOW", "RED" }
+ local iterate_fn = spy.new()
+ _.each(iterate_fn, list)
+ assert.spy(iterate_fn).was_called(3)
+ assert.spy(iterate_fn).was_called_with("BLUE", 1)
+ assert.spy(iterate_fn).was_called_with("YELLOW", 2)
+ assert.spy(iterate_fn).was_called_with("RED", 3)
+ end)
+end)
diff --git a/tests/core/functional/logic_spec.lua b/tests/core/functional/logic_spec.lua
new file mode 100644
index 00000000..19ac8bb7
--- /dev/null
+++ b/tests/core/functional/logic_spec.lua
@@ -0,0 +1,44 @@
+local spy = require "luassert.spy"
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: logic", function()
+ it("should check that all_pass checks that all predicates pass", function()
+ local is_waldo = function(i)
+ return i == "waldo"
+ end
+ assert.is_true(_.all_pass { _.T, _.T, is_waldo, _.T } "waldo")
+ assert.is_false(_.all_pass { _.T, _.T, is_waldo, _.F } "waldo")
+ assert.is_false(_.all_pass { _.T, _.T, is_waldo, _.T } "waldina")
+ end)
+
+ it("should branch if_else", function()
+ local a = spy.new()
+ local b = spy.new()
+ _.if_else(_.T, a, b) "a"
+ _.if_else(_.F, a, b) "b"
+ assert.spy(a).was_called(1)
+ assert.spy(a).was_called_with "a"
+ assert.spy(b).was_called(1)
+ assert.spy(b).was_called_with "b"
+ end)
+
+ it("should flip booleans", function()
+ assert.is_true(_.is_not(false))
+ assert.is_false(_.is_not(true))
+ end)
+
+ it("should resolve correct cond", function()
+ local planetary_object = _.cond {
+ {
+ _.equals "Moon!",
+ _.format "to the %s",
+ },
+ {
+ _.equals "World!",
+ _.format "Hello %s",
+ },
+ }
+ assert.equals("Hello World!", planetary_object "World!")
+ assert.equals("to the Moon!", planetary_object "Moon!")
+ end)
+end)
diff --git a/tests/core/functional/number_spec.lua b/tests/core/functional/number_spec.lua
new file mode 100644
index 00000000..644547fb
--- /dev/null
+++ b/tests/core/functional/number_spec.lua
@@ -0,0 +1,50 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: number", function()
+ it("should negate numbers", function()
+ assert.equals(-42, _.negate(42))
+ assert.equals(42, _.negate(-42))
+ end)
+
+ it("should check numbers greater than value", function()
+ local greater_than_life = _.gt(42)
+ assert.is_false(greater_than_life(0))
+ assert.is_false(greater_than_life(42))
+ assert.is_true(greater_than_life(43))
+ end)
+
+ it("should check numbers greater or equal than value", function()
+ local greater_or_equal_to_life = _.gte(42)
+ assert.is_false(greater_or_equal_to_life(0))
+ assert.is_true(greater_or_equal_to_life(42))
+ assert.is_true(greater_or_equal_to_life(43))
+ end)
+
+ it("should check numbers lower than value", function()
+ local lesser_than_life = _.lt(42)
+ assert.is_true(lesser_than_life(0))
+ assert.is_false(lesser_than_life(42))
+ assert.is_false(lesser_than_life(43))
+ end)
+
+ it("should check numbers lower or equal than value", function()
+ local lesser_or_equal_to_life = _.lte(42)
+ assert.is_true(lesser_or_equal_to_life(0))
+ assert.is_true(lesser_or_equal_to_life(42))
+ assert.is_false(lesser_or_equal_to_life(43))
+ end)
+
+ it("should increment numbers", function()
+ local add_5 = _.inc(5)
+ assert.equals(0, add_5(-5))
+ assert.equals(5, add_5(0))
+ assert.equals(7, add_5(2))
+ end)
+
+ it("should decrement numbers", function()
+ local subtract_5 = _.dec(5)
+ assert.equals(5, subtract_5(10))
+ assert.equals(-5, subtract_5(0))
+ assert.equals(-3, subtract_5(2))
+ end)
+end)
diff --git a/tests/core/functional/relation_spec.lua b/tests/core/functional/relation_spec.lua
new file mode 100644
index 00000000..41325cf2
--- /dev/null
+++ b/tests/core/functional/relation_spec.lua
@@ -0,0 +1,36 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: relation", function()
+ it("should check equality", function()
+ local tbl = {}
+ local is_tbl = _.equals(tbl)
+ local is_a = _.equals "a"
+ local is_42 = _.equals(42)
+
+ assert.is_true(is_tbl(tbl))
+ assert.is_true(is_a "a")
+ assert.is_true(is_42(42))
+ assert.is_false(is_a "b")
+ assert.is_false(is_42(32))
+ end)
+
+ it("should check property equality", function()
+ local fn_key = function() end
+ local tbl = { a = "a", b = "b", number = 42, [fn_key] = "fun" }
+ assert.is_true(_.prop_eq("a", "a", tbl))
+ assert.is_true(_.prop_eq(fn_key, "fun", tbl))
+ assert.is_true(_.prop_eq(fn_key) "fun"(tbl))
+ end)
+
+ it("should check whether property satisfies predicate", function()
+ local obj = {
+ low = 0,
+ med = 10,
+ high = 15,
+ }
+
+ assert.is_false(_.prop_satisfies(_.gt(10), "low", obj))
+ assert.is_false(_.prop_satisfies(_.gt(10), "med")(obj))
+ assert.is_true(_.prop_satisfies(_.gt(10)) "high"(obj))
+ end)
+end)
diff --git a/tests/core/functional/string_spec.lua b/tests/core/functional/string_spec.lua
new file mode 100644
index 00000000..53575ce4
--- /dev/null
+++ b/tests/core/functional/string_spec.lua
@@ -0,0 +1,17 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: string", function()
+ it("matches string patterns", function()
+ assert.is_true(_.matches("foo", "foo"))
+ assert.is_true(_.matches("bar", "foobarbaz"))
+ assert.is_true(_.matches("ba+r", "foobaaaaaaarbaz"))
+
+ assert.is_false(_.matches("ba+r", "foobharbaz"))
+ assert.is_false(_.matches("bar", "foobaz"))
+ end)
+
+ it("should format strings", function()
+ assert.equals("Hello World!", _.format("%s", "Hello World!"))
+ assert.equals("special manouvers", _.format("%s manouvers", "special"))
+ end)
+end)
diff --git a/tests/core/functional/table_spec.lua b/tests/core/functional/table_spec.lua
new file mode 100644
index 00000000..25adff59
--- /dev/null
+++ b/tests/core/functional/table_spec.lua
@@ -0,0 +1,7 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: table", function()
+ it("retrieves property of table", function()
+ assert.equals("hello", _.prop("a", { a = "hello" }))
+ end)
+end)
diff --git a/tests/core/functional/type_spec.lua b/tests/core/functional/type_spec.lua
new file mode 100644
index 00000000..b99262b5
--- /dev/null
+++ b/tests/core/functional/type_spec.lua
@@ -0,0 +1,26 @@
+local _ = require "nvim-lsp-installer.core.functional"
+
+describe("functional: type", function()
+ it("should check nil value", function()
+ assert.is_true(_.is_nil(nil))
+ assert.is_false(_.is_nil(1))
+ assert.is_false(_.is_nil {})
+ assert.is_false(_.is_nil(function() end))
+ end)
+
+ it("should check types", function()
+ local is_fun = _.is "function"
+ local is_string = _.is "string"
+ local is_number = _.is "number"
+ local is_boolean = _.is "boolean"
+
+ assert.is_true(is_fun(function() end))
+ assert.is_false(is_fun(1))
+ assert.is_true(is_string "")
+ assert.is_false(is_string(1))
+ assert.is_true(is_number(1))
+ assert.is_false(is_number "")
+ assert.is_true(is_boolean(true))
+ assert.is_false(is_boolean(1))
+ end)
+end)
diff --git a/tests/core/functional_spec.lua b/tests/core/functional_spec.lua
deleted file mode 100644
index 54433629..00000000
--- a/tests/core/functional_spec.lua
+++ /dev/null
@@ -1,247 +0,0 @@
-local functional = require "nvim-lsp-installer.core.functional"
-local spy = require "luassert.spy"
-local match = require "luassert.match"
-
-describe("functional", function()
- it("creates enums", function()
- local colors = functional.enum {
- "BLUE",
- "YELLOW",
- }
- assert.same({
- ["BLUE"] = "BLUE",
- ["YELLOW"] = "YELLOW",
- }, colors)
- end)
-
- it("creates sets", function()
- local colors = functional.set_of {
- "BLUE",
- "YELLOW",
- "BLUE",
- "RED",
- }
- assert.same({
- ["BLUE"] = true,
- ["YELLOW"] = true,
- ["RED"] = true,
- }, colors)
- end)
-
- it("reverses lists", function()
- local colors = { "BLUE", "YELLOW", "RED" }
- assert.same({
- "RED",
- "YELLOW",
- "BLUE",
- }, functional.list_reverse(colors))
- -- should not modify in-place
- assert.same({ "BLUE", "YELLOW", "RED" }, colors)
- end)
-
- it("maps over list", function()
- local colors = { "BLUE", "YELLOW", "RED" }
- assert.same(
- {
- "LIGHT_BLUE1",
- "LIGHT_YELLOW2",
- "LIGHT_RED3",
- },
- functional.list_map(function(color, i)
- return "LIGHT_" .. color .. i
- end, colors)
- )
- -- should not modify in-place
- assert.same({ "BLUE", "YELLOW", "RED" }, colors)
- end)
-
- it("coalesces first non-nil value", function()
- assert.equal("Hello World!", functional.coalesce(nil, nil, "Hello World!", ""))
- end)
-
- it("makes a shallow copy of a list", function()
- local list = { "BLUE", { nested = "TABLE" }, "RED" }
- local list_copy = functional.list_copy(list)
- assert.same({ "BLUE", { nested = "TABLE" }, "RED" }, list_copy)
- assert.is_not.is_true(list == list_copy)
- assert.is_true(list[2] == list_copy[2])
- end)
-
- it("finds first item that fulfills predicate", function()
- local predicate = spy.new(function(item)
- return item == "Waldo"
- end)
-
- assert.equal(
- "Waldo",
- functional.list_find_first(predicate, {
- "Where",
- "On Earth",
- "Is",
- "Waldo",
- "?",
- })
- )
- assert.spy(predicate).was.called(4)
- end)
-
- it("determines whether any item in the list fulfills predicate", function()
- local predicate = spy.new(function(item)
- return item == "On Earth"
- end)
-
- assert.is_true(functional.list_any(predicate, {
- "Where",
- "On Earth",
- "Is",
- "Waldo",
- "?",
- }))
-
- assert.spy(predicate).was.called(2)
- end)
-
- it("memoizes functions with default cache mechanism", function()
- local expensive_function = spy.new(function(s)
- return s
- end)
- local memoized_fn = functional.memoize(expensive_function)
- assert.equal("key", memoized_fn "key")
- assert.equal("key", memoized_fn "key")
- assert.equal("new_key", memoized_fn "new_key")
- assert.spy(expensive_function).was_called(2)
- end)
-
- it("memoizes function with custom cache mechanism", function()
- local expensive_function = spy.new(function(arg1, arg2)
- return arg1 .. arg2
- end)
- local memoized_fn = functional.memoize(expensive_function, function(arg1, arg2)
- return arg1 .. arg2
- end)
- assert.equal("key1key2", memoized_fn("key1", "key2"))
- assert.equal("key1key2", memoized_fn("key1", "key2"))
- assert.equal("key1key3", memoized_fn("key1", "key3"))
- assert.spy(expensive_function).was_called(2)
- end)
-
- it("should evaluate functions lazily", function()
- local impl = spy.new(function()
- return {}, {}
- end)
- local lazy_fn = functional.lazy(impl)
- assert.spy(impl).was_called(0)
- local a, b = lazy_fn()
- assert.spy(impl).was_called(1)
- assert.is_true(match.is_table()(a))
- assert.is_true(match.is_table()(b))
- local new_a, new_b = lazy_fn()
- assert.spy(impl).was_called(1)
- assert.is_true(match.is_ref(a)(new_a))
- assert.is_true(match.is_ref(b)(new_b))
- end)
-
- it("should support nil return values in lazy functions", function()
- local lazy_fn = functional.lazy(function()
- return nil, 2
- end)
- local a, b = lazy_fn()
- assert.is_nil(a)
- assert.equal(2, b)
- end)
-
- it("should partially apply functions", function()
- local funcy = spy.new()
- local partially_funcy = functional.partial(funcy, "a", "b", "c")
- partially_funcy("d", "e", "f")
- assert.spy(funcy).was_called_with("a", "b", "c", "d", "e", "f")
- end)
-
- it("should partially apply functions with nil arguments", function()
- local funcy = spy.new()
- local partially_funcy = functional.partial(funcy, "a", nil, "c")
- partially_funcy("d", nil, "f")
- assert.spy(funcy).was_called_with("a", nil, "c", "d", nil, "f")
- end)
-
- it("should compose functions", function()
- local function add(x)
- return function(y)
- return y + x
- end
- end
- local function subtract(x)
- return function(y)
- return y - x
- end
- end
- local function multiply(x)
- return function(y)
- return y * x
- end
- end
-
- local big_maths = functional.compose(add(1), subtract(3), multiply(5))
-
- assert.equals(23, big_maths(5))
- end)
-
- it("should not allow composing no functions", function()
- local e = assert.error(function()
- functional.compose()
- end)
- assert.equals("compose requires at least one function", e)
- end)
-
- it("should iterate list in .each", function()
- local list = { "BLUE", "YELLOW", "RED" }
- local iterate_fn = spy.new()
- functional.each(iterate_fn, list)
- assert.spy(iterate_fn).was_called(3)
- assert.spy(iterate_fn).was_called_with("BLUE", 1)
- assert.spy(iterate_fn).was_called_with("YELLOW", 2)
- assert.spy(iterate_fn).was_called_with("RED", 3)
- end)
-
- it("should negate predicates", function()
- local predicate = spy.new(function(item)
- return item == "Waldo"
- end)
- local negated_predicate = functional.negate(predicate)
- assert.is_false(negated_predicate "Waldo")
- assert.is_true(negated_predicate "Where")
- assert.spy(predicate).was_called(2)
- end)
-
- it("should check that all_pass checks that all predicates pass", function()
- local t = functional.always(true)
- local f = functional.always(false)
- local is_waldo = function(i)
- return i == "waldo"
- end
- assert.is_true(functional.all_pass { t, t, is_waldo, t } "waldo")
- assert.is_false(functional.all_pass { t, t, is_waldo, f } "waldo")
- assert.is_false(functional.all_pass { t, t, is_waldo, t } "waldina")
- end)
-
- it("should index object by prop", function()
- local waldo = functional.prop "where is he"
- assert.equals("nowhere to be found", waldo { ["where is he"] = "nowhere to be found" })
- end)
-
- it("should branch if_else", function()
- local a = spy.new()
- local b = spy.new()
- functional.if_else(functional.T, a, b)("a", 1)
- functional.if_else(functional.F, a, b)("b", 2)
- assert.spy(a).was_called(1)
- assert.spy(a).was_called_with("a", 1)
- assert.spy(b).was_called(1)
- assert.spy(b).was_called_with("b", 2)
- end)
-
- it("should check if string matches", function()
- assert.is_false(functional.matches "a" "b")
- assert.is_true(functional.matches "a" "a")
- end)
-end)