clean up configuration code a little bit

This commit is contained in:
XeroOl 2025-07-22 20:49:01 -05:00
parent 9be6628bf0
commit ef9cf289c5
3 changed files with 58 additions and 60 deletions

View File

@ -13,7 +13,7 @@ to server.configuration. Every other use case should be read-only."
(local utils (require :fennel-ls.utils)) (local utils (require :fennel-ls.utils))
(local lint (require :fennel-ls.lint)) (local lint (require :fennel-ls.lint))
(local message (require :fennel-ls.message)) (local message (require :fennel-ls.message))
(local {: view} (require :fennel)) (local {: view &as fennel} (require :fennel))
(local option-mt {}) (local option-mt {})
(fn option [default-value ?validate] (fn option [default-value ?validate]
@ -41,43 +41,43 @@ to server.configuration. Every other use case should be read-only."
?root (.. ?root "." extra) ?root (.. ?root "." extra)
extra)) extra))
(fn make-configuration-from-template [template ?user ?parent ?path invalid] (fn apply-default-configuration [default ?flsproject ?parent ?name invalid]
(if (= (getmetatable template) option-mt) (if (= (getmetatable default) option-mt)
(let [setting (case-try ?user (let [setting (case-try ?flsproject
nil (?. ?parent :all) nil (?. ?parent :all)
nil template.default-value)] nil default.default-value)]
(if (not= (type setting) (type template.default-value)) (if (not= (type setting) (type default.default-value))
(do (invalid (.. (or ?path "flsproject.fnl") " must be a " (type template.default-value)) ?user ?parent) (do (invalid (.. (or ?name "flsproject.fnl") " must be a " (type default.default-value)) ?flsproject ?parent)
template.default-value) default.default-value)
template.validate default.validate
(case-try (template.validate setting #(invalid $ ?user ?parent)) (case-try (default.validate setting #(invalid $ ?flsproject ?parent))
nil template.default-value) nil default.default-value)
setting)) setting))
(= :table (type template)) (= :table (type default))
(case (type ?user) (case (type ?flsproject)
(where (or :table :nil)) (where (or :table :nil))
(do (do
(when (= (type ?user) :table) (when (= (type ?flsproject) :table)
(each [k (pairs ?user)] (each [k (pairs ?flsproject)]
(when (not (. template k)) (when (not (. default k))
(invalid (.. "didn't expect " (or (extend-path ?path k) "flsproject.fnl") "\n" (invalid (.. "didn't expect " (or (extend-path ?name k) "flsproject.fnl") "\n"
"valid keys: " (view (doto (icollect [k (pairs template)] k) "valid keys: " (view (doto (icollect [k (pairs default)] k)
table.sort))) table.sort)))
(. ?user k) (. ?flsproject k)
?user)))) ?flsproject))))
(collect [k (pairs template)] (collect [k (pairs default)]
k (make-configuration-from-template k (apply-default-configuration
(. template k) (. default k)
(?. ?user k) (?. ?flsproject k)
?user ?flsproject
(extend-path ?path k) (extend-path ?name k)
invalid))) invalid)))
_ (do (invalid (.. "expected " (or ?path "flsproject.fnl") " to be a table") ?user ?parent) _ (do (invalid (.. "expected " (or ?name "flsproject.fnl") " to be a table") ?flsproject ?parent)
(make-configuration-from-template template nil ?parent ?path invalid))) (apply-default-configuration default nil ?parent ?name invalid)))
(error (.. "This is a bug with fennel-ls: default-configuration has a key that isn't a table or option: " ?path)))) (error (.. "This is a bug with fennel-ls: default-configuration has a key that isn't a table or option: " ?name))))
(λ make-configuration [?c invalid] (λ make-configuration [?flsproject invalid]
(make-configuration-from-template default-configuration ?c nil nil invalid)) (apply-default-configuration default-configuration ?flsproject nil nil invalid))
(λ choose-position-encoding [init-params] (λ choose-position-encoding [init-params]
"fennel-ls natively uses utf-8, so the goal is to choose positionEncoding=\"utf-8\". "fennel-ls natively uses utf-8, so the goal is to choose positionEncoding=\"utf-8\".
@ -92,28 +92,26 @@ However, when not an option, fennel-ls will fall back to positionEncoding=\"utf-
(= encoding :utf8))) (= encoding :utf8)))
false)] false)]
(if utf8? (if utf8?
:utf-8 :utf-8
:utf-16))) :utf-16)))
(λ parse-flsconfig [{: text : uri}] (fn flsproject-path [server]
(local fennel (require :fennel)) (-?> server.root-uri
(local [ok? _err result] [(pcall (fennel.parser text uri))]) utils.uri->path
(if ok? result)) (utils.path-join "flsproject.fnl")
utils.path->uri))
(λ load-config [server invalid]
"This is where we can put anything that needs to react to config changes"
(make-configuration
(-?> server.root-uri
utils.uri->path
(utils.path-join "flsproject.fnl")
utils.path->uri
(->> (files.read-file server))
parse-flsconfig)
invalid))
(λ reload [server] (λ reload [server]
;; clear out macros from fennel
(each [k (pairs fennel.macro-loaded)]
(tset fennel.macro-loaded k nil))
(set server.configuration (set server.configuration
(load-config server (make-configuration
(case-try (flsproject-path server)
path (files.read-file server path)
{: text : uri} (let [[ok? _err result] [(pcall (fennel.parser text uri))]]
(if ok? result))
(catch _ nil))
;; according to the spec it is valid to send showMessage during initialization ;; according to the spec it is valid to send showMessage during initialization
;; but eglot will only flash the message briefly before replacing it with ;; but eglot will only flash the message briefly before replacing it with
;; another message, and probably other clients will do similarly. so queue ;; another message, and probably other clients will do similarly. so queue
@ -137,4 +135,5 @@ However, when not an option, fennel-ls will fall back to positionEncoding=\"utf-
{: initialize {: initialize
: reload : reload
: make-configuration} : make-configuration
: flsproject-path}

View File

@ -21,7 +21,9 @@ Every time the client sends a message, it gets handled by a function in the corr
(config.initialize server params) (config.initialize server params)
(let [capabilities (let [capabilities
{:positionEncoding server.position-encoding {:positionEncoding server.position-encoding
:textDocumentSync {:openClose true :change 2} :textDocumentSync {:openClose true
:change 2
:save true}
;; :notebookDocumentSync nil ;; :notebookDocumentSync nil
:completionProvider {:workDoneProgress false :completionProvider {:workDoneProgress false
:resolveProvider server.can-do-good-completions? :resolveProvider server.can-do-good-completions?
@ -229,9 +231,8 @@ Every time the client sends a message, it gets handled by a function in the corr
(λ notifications.textDocument/didSave [server _send {:textDocument {: uri}}] (λ notifications.textDocument/didSave [server _send {:textDocument {: uri}}]
(when (utils.endswith uri "flsproject.fnl") (when (utils.endswith uri "flsproject.fnl")
(config.reload server)) (config.reload server))
;; TODO recompute for files when macro is changed ;; TODO recompute for files when macro is changed
(set fennel.macro-loaded [])) (each [k (pairs fennel.macro-loaded)] (tset fennel.macro-loaded k nil)))
(λ notifications.textDocument/didClose [server _send {:textDocument {: uri}}] (λ notifications.textDocument/didClose [server _send {:textDocument {: uri}}]
(local file (files.get-by-uri server uri)) (local file (files.get-by-uri server uri))

View File

@ -775,13 +775,11 @@ You can read more about how to add lints in docs/linting.md"
:since :0.2.2-dev :since :0.2.2-dev
:type :other :type :other
:impl (fn [server file] :impl (fn [server file]
(when (and (= file.uri (-?> server.root-uri (let [config-module :fennel-ls.config
utils.uri->path config (require config-module)]
(utils.path-join "flsproject.fnl") (when (and (= file.uri (config.flsproject-path server))
utils.path->uri)) (not (. file.diagnostics 1)))
(not (. file.diagnostics 1))) ;; circular dependency! don't tell anyone ^_^
;; circular dependency! don't tell anyone ^_^
(let [config (require :fennel-ls.config)]
(config.make-configuration (. file.ast 1) (config.make-configuration (. file.ast 1)
#(coroutine.yield {:code :invalid-flsproject-settings #(coroutine.yield {:code :invalid-flsproject-settings
:range (or (message.ast->range server file $2) :range (or (message.ast->range server file $2)