mirror of
https://github.com/logseq/logseq.git
synced 2026-05-29 23:19:38 +00:00
enhance(cli): options cleanup in list cmds
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
(ns logseq.cli.command.list
|
||||
"List-related CLI commands."
|
||||
(:require [clojure.string :as string]
|
||||
[logseq.cli.command.add :as add-command]
|
||||
[logseq.cli.command.core :as core]
|
||||
[logseq.cli.command.task-status :as task-status-command]
|
||||
[logseq.cli.server :as cli-server]
|
||||
[logseq.cli.transport :as transport]
|
||||
[promesa.core :as p]))
|
||||
@@ -124,13 +124,11 @@
|
||||
(merge-with
|
||||
merge
|
||||
list-common-spec
|
||||
{:status {:desc "Filter by task status"
|
||||
:validate #{"todo" "doing" "done" "now" "later" "wait" "waiting"
|
||||
"backlog" "canceled" "cancelled"
|
||||
"in-review" "in_review" "inreview" "in-progress"}}
|
||||
{:status {:desc "Filter by task status"}
|
||||
:priority {:desc "Filter by task priority"
|
||||
:validate #{"low" "medium" "high" "urgent"}}
|
||||
:content {:desc "Filter by task title content"}
|
||||
:content {:desc "Filter by task title content"
|
||||
:alias :c}
|
||||
:sort {:validate (set (keys list-task-field-map))}
|
||||
:fields {:multiple-values (keys list-task-field-map)}}))
|
||||
|
||||
@@ -279,18 +277,29 @@
|
||||
[action config]
|
||||
(-> (p/let [cfg (cli-server/ensure-server! config (:repo action))
|
||||
options (:options action)
|
||||
normalized-options (cond-> options
|
||||
(seq (some-> (:status options) string/trim))
|
||||
(assoc :status (add-command/normalize-status (:status options)))
|
||||
(seq (some-> (:priority options) string/trim))
|
||||
(assoc :priority (normalize-priority (:priority options))))
|
||||
items (transport/invoke cfg :thread-api/cli-list-tasks false
|
||||
[(:repo action) normalized-options])
|
||||
sort-field (effective-sort-field normalized-options)
|
||||
order (or (:order normalized-options) "asc")
|
||||
fields (parse-field-list (:fields normalized-options))
|
||||
sorted (apply-sort items sort-field order list-task-field-map)
|
||||
limited (apply-offset-limit sorted (:offset normalized-options) (:limit normalized-options))
|
||||
final (apply-fields limited fields list-task-field-map)]
|
||||
{:status :ok
|
||||
:data {:items final}})))
|
||||
status-input (some-> (:status options) string/trim)
|
||||
available-statuses (when (seq status-input)
|
||||
(transport/invoke cfg :thread-api/q false
|
||||
[(:repo action)
|
||||
[task-status-command/status-closed-values-query]]))
|
||||
resolved-status (when (seq status-input)
|
||||
(task-status-command/resolve-status-ident status-input available-statuses))]
|
||||
(if (and (seq status-input) (not resolved-status))
|
||||
{:status :error
|
||||
:error {:code :invalid-options
|
||||
:message (task-status-command/invalid-status-message status-input available-statuses)}}
|
||||
(let [normalized-options (cond-> options
|
||||
resolved-status
|
||||
(assoc :status resolved-status)
|
||||
(seq (some-> (:priority options) string/trim))
|
||||
(assoc :priority (normalize-priority (:priority options))))]
|
||||
(p/let [items (transport/invoke cfg :thread-api/cli-list-tasks false
|
||||
[(:repo action) normalized-options])
|
||||
sort-field (effective-sort-field normalized-options)
|
||||
order (or (:order normalized-options) "asc")
|
||||
fields (parse-field-list (:fields normalized-options))
|
||||
sorted (apply-sort items sort-field order list-task-field-map)
|
||||
limited (apply-offset-limit sorted (:offset normalized-options) (:limit normalized-options))
|
||||
final (apply-fields limited fields list-task-field-map)]
|
||||
{:status :ok
|
||||
:data {:items final}}))))))
|
||||
|
||||
74
src/main/logseq/cli/command/task_status.cljs
Normal file
74
src/main/logseq/cli/command/task_status.cljs
Normal file
@@ -0,0 +1,74 @@
|
||||
(ns logseq.cli.command.task-status
|
||||
"Runtime task status helpers for graph-derived validation."
|
||||
(:require [clojure.string :as string]
|
||||
[logseq.cli.command.add :as add-command]))
|
||||
|
||||
(def status-closed-values-query
|
||||
'[:find [?status-ident ...]
|
||||
:where
|
||||
[?property :db/ident :logseq.property/status]
|
||||
[?value :block/closed-value-property ?property]
|
||||
[?value :db/ident ?status-ident]])
|
||||
|
||||
(defn- status-ident->value
|
||||
[ident]
|
||||
(when (keyword? ident)
|
||||
(let [n (name ident)]
|
||||
(when (string/starts-with? n "status.")
|
||||
(subs n (count "status."))))))
|
||||
|
||||
(defn- normalize-token
|
||||
[value]
|
||||
(some-> value
|
||||
str
|
||||
string/trim
|
||||
string/lower-case
|
||||
(string/replace #"^:+" "")
|
||||
(string/replace #"^logseq\.property/status\." "")
|
||||
(string/replace #"^status\." "")
|
||||
(string/replace #"[\s_]+" "-")))
|
||||
|
||||
(defn normalize-available-statuses
|
||||
"Normalize db-worker status values into sorted maps of
|
||||
`{:ident <kw> :value <string>}` for deterministic matching/output."
|
||||
[statuses]
|
||||
(->> statuses
|
||||
(keep (fn [item]
|
||||
(let [ident (cond
|
||||
(keyword? item) item
|
||||
(map? item) (:ident item)
|
||||
:else nil)
|
||||
value (or (when (map? item)
|
||||
(some-> (:value item) normalize-token))
|
||||
(some-> ident status-ident->value normalize-token))]
|
||||
(when (and ident (seq value))
|
||||
{:ident ident :value value}))))
|
||||
(sort-by (juxt :value (comp str :ident)))
|
||||
distinct
|
||||
vec))
|
||||
|
||||
(defn resolve-status-ident
|
||||
"Resolve user `status-input` to one of `available-statuses` idents.
|
||||
Returns nil when unresolved."
|
||||
[status-input available-statuses]
|
||||
(let [available-statuses (normalize-available-statuses available-statuses)
|
||||
available-idents (set (map :ident available-statuses))
|
||||
by-value (into {} (map (juxt :value :ident) available-statuses))
|
||||
legacy (add-command/normalize-status status-input)
|
||||
token (normalize-token status-input)
|
||||
ident-from-token (when (seq token)
|
||||
(keyword "logseq.property" (str "status." token)))]
|
||||
(or (when (contains? available-idents legacy) legacy)
|
||||
(get by-value token)
|
||||
(when (contains? available-idents ident-from-token)
|
||||
ident-from-token))))
|
||||
|
||||
(defn invalid-status-message
|
||||
[status-input available-statuses]
|
||||
(let [values (map :value (normalize-available-statuses available-statuses))
|
||||
available-text (if (seq values)
|
||||
(string/join ", " values)
|
||||
"(none)")]
|
||||
(str "Invalid value for option :status: " status-input
|
||||
". Available values (from current graph): "
|
||||
available-text)))
|
||||
@@ -3,6 +3,7 @@
|
||||
(:require [clojure.string :as string]
|
||||
[logseq.cli.command.add :as add-command]
|
||||
[logseq.cli.command.core :as core]
|
||||
[logseq.cli.command.task-status :as task-status-command]
|
||||
[logseq.cli.command.update :as update-command]
|
||||
[logseq.cli.server :as cli-server]
|
||||
[logseq.cli.transport :as transport]
|
||||
@@ -32,10 +33,6 @@
|
||||
:blocks-file {:desc "EDN file of blocks [create only]"
|
||||
:coerce common-graph/expand-home
|
||||
:complete :file}
|
||||
:status {:desc "Set task status"
|
||||
:validate #{"todo" "doing" "done" "now" "later" "wait" "waiting"
|
||||
"backlog" "canceled" "cancelled"
|
||||
"in-review" "in_review" "inreview" "in-progress"}}
|
||||
:update-tags {:desc "Tags to add/update (EDN vector)"}
|
||||
:update-properties {:desc "Properties to add/update (EDN map)"}
|
||||
:remove-tags {:desc "Tags to remove (EDN vector) [update only]"}
|
||||
@@ -70,9 +67,7 @@
|
||||
:complete :pages}
|
||||
:pos {:desc "Position. Default: last-child"
|
||||
:validate #{"first-child" "last-child" "sibling"}}
|
||||
:status {:desc "Set task status"
|
||||
:validate #{"todo" "doing" "done" "now" "later" "wait" "waiting"
|
||||
"backlog" "canceled" "cancelled" "in-review" "in-progress"}}
|
||||
:status {:desc "Set task status"}
|
||||
:priority {:desc "Set task priority"
|
||||
:validate #{"low" "medium" "high" "urgent"}}
|
||||
:update-tags {:desc "Tags to add/update (EDN vector)"}
|
||||
@@ -107,8 +102,7 @@
|
||||
"logseq upsert block --graph my-graph --id 123 --content \"Updated content\""
|
||||
"logseq upsert block --graph my-graph --id 123 --target-page Home"
|
||||
"logseq upsert block --graph my-graph --target-page Meeting Notes --content \"AI summary of the discussion\" --update-tags '[\"AI-GENERATED\"]'"
|
||||
"logseq upsert block --graph my-graph --blocks '[{:block/title \"A\"} {:block/title \"B\"}]'"
|
||||
"logseq upsert block --graph my-graph --id 123 --status done"]})
|
||||
"logseq upsert block --graph my-graph --blocks '[{:block/title \"A\"} {:block/title \"B\"}]'"]})
|
||||
(core/command-entry ["upsert" "page"] :upsert-page "Upsert page" upsert-page-spec
|
||||
{:examples ["logseq upsert page --graph my-graph --page Home --update-tags '[\"project\"]'"
|
||||
"logseq upsert page --graph my-graph --id 999 --update-properties '{:logseq.property/description \"Example\"}'"]})
|
||||
@@ -379,7 +373,7 @@
|
||||
:error {:code :invalid-options
|
||||
:message invalid-message}}
|
||||
|
||||
(and status-provided? (not status))
|
||||
(and status-provided? (not (seq status-text)))
|
||||
{:ok? false
|
||||
:error {:code :invalid-options
|
||||
:message (str "invalid status: " (:status options))}}
|
||||
@@ -426,6 +420,7 @@
|
||||
(some? id) (assoc :id id)
|
||||
(seq uuid) (assoc :uuid uuid)
|
||||
(seq page) (assoc :page page)
|
||||
(seq status-text) (assoc :status-input status-text)
|
||||
(and (seq content) (not= mode :page)) (assoc :content content))}))))
|
||||
|
||||
(defn build-tag-action
|
||||
@@ -863,34 +858,65 @@
|
||||
:error {:code (or (get-in (ex-data e) [:code]) :exception)
|
||||
:message (or (ex-message e) (str e))}}))))
|
||||
|
||||
(defn- normalize-status-input
|
||||
[value]
|
||||
(when (some? value)
|
||||
(let [text (string/trim (if (string? value) value (str value)))]
|
||||
(when (seq text)
|
||||
text))))
|
||||
|
||||
(defn- resolve-task-status-action
|
||||
[action cfg]
|
||||
(let [status-input (or (normalize-status-input (:status-input action))
|
||||
(normalize-status-input (:status action)))]
|
||||
(if (seq status-input)
|
||||
(p/let [available-statuses (transport/invoke cfg :thread-api/q false
|
||||
[(:repo action)
|
||||
[task-status-command/status-closed-values-query]])
|
||||
resolved-status (task-status-command/resolve-status-ident status-input available-statuses)]
|
||||
(if resolved-status
|
||||
{:ok? true
|
||||
:action (-> action
|
||||
(assoc :status resolved-status)
|
||||
(dissoc :status-input))}
|
||||
{:ok? false
|
||||
:error {:code :invalid-options
|
||||
:message (task-status-command/invalid-status-message status-input available-statuses)}}))
|
||||
(p/resolved {:ok? true :action action}))))
|
||||
|
||||
(defn execute-upsert-task
|
||||
[action config]
|
||||
(-> (p/let [cfg (cli-server/ensure-server! config (:repo action))]
|
||||
(case (:mode action)
|
||||
:create
|
||||
(p/let [result (add-command/execute-add-block (assoc action :type :add-block) config)
|
||||
created-ids (vec (or (get-in result [:data :result]) []))
|
||||
_ (execute-upsert-task-ops! action cfg created-ids)]
|
||||
{:status :ok
|
||||
:data {:result created-ids}})
|
||||
|
||||
:page
|
||||
(p/let [page (ensure-page-entity! cfg (:repo action) (:page action))
|
||||
page-id (:db/id page)
|
||||
_ (execute-upsert-task-ops! action cfg [page-id])]
|
||||
{:status :ok
|
||||
:data {:result [page-id]}})
|
||||
|
||||
:update
|
||||
(p/let [entity (ensure-task-node! cfg (:repo action) action)
|
||||
node-id (:db/id entity)
|
||||
_ (execute-upsert-task-ops! action cfg [node-id])]
|
||||
{:status :ok
|
||||
:data {:result [node-id]}})
|
||||
|
||||
(-> (p/let [cfg (cli-server/ensure-server! config (:repo action))
|
||||
status-check (resolve-task-status-action action cfg)]
|
||||
(if-not (:ok? status-check)
|
||||
{:status :error
|
||||
:error {:code :invalid-options
|
||||
:message "invalid upsert task mode"}}))
|
||||
:error (:error status-check)}
|
||||
(let [action* (:action status-check)]
|
||||
(case (:mode action*)
|
||||
:create
|
||||
(p/let [result (add-command/execute-add-block (assoc action* :type :add-block) config)
|
||||
created-ids (vec (or (get-in result [:data :result]) []))
|
||||
_ (execute-upsert-task-ops! action* cfg created-ids)]
|
||||
{:status :ok
|
||||
:data {:result created-ids}})
|
||||
|
||||
:page
|
||||
(p/let [page (ensure-page-entity! cfg (:repo action*) (:page action*))
|
||||
page-id (:db/id page)
|
||||
_ (execute-upsert-task-ops! action* cfg [page-id])]
|
||||
{:status :ok
|
||||
:data {:result [page-id]}})
|
||||
|
||||
:update
|
||||
(p/let [entity (ensure-task-node! cfg (:repo action*) action*)
|
||||
node-id (:db/id entity)
|
||||
_ (execute-upsert-task-ops! action* cfg [node-id])]
|
||||
{:status :ok
|
||||
:data {:result [node-id]}})
|
||||
|
||||
{:status :error
|
||||
:error {:code :invalid-options
|
||||
:message "invalid upsert task mode"}}))))
|
||||
(p/catch (fn [e]
|
||||
{:status :error
|
||||
:error {:code (or (get-in (ex-data e) [:code]) :exception)
|
||||
|
||||
@@ -181,6 +181,10 @@
|
||||
(re-find #"Unknown option:\s*:properties" (or message "")))
|
||||
"unknown option: --properties; use --update-properties"
|
||||
|
||||
(and (= ["upsert" "block"] subcommand)
|
||||
(re-find #"Unknown option:\s*:status" (or message "")))
|
||||
"unknown option: --status; use upsert task --status"
|
||||
|
||||
(and (= ["upsert" "page"] subcommand)
|
||||
(re-find #"Unknown option:\s*:tags" (or message "")))
|
||||
"unknown option: --tags; use --update-tags"
|
||||
|
||||
@@ -92,6 +92,11 @@
|
||||
add-command/resolve-property-identifiers (fn [_ _ _ _] (p/resolved []))
|
||||
transport/invoke (fn [_ method _ args]
|
||||
(case method
|
||||
:thread-api/q
|
||||
(p/resolved [:logseq.property/status.todo
|
||||
:logseq.property/status.doing
|
||||
:logseq.property/status.done])
|
||||
|
||||
:thread-api/pull
|
||||
(let [[_ selector lookup] args]
|
||||
(cond
|
||||
|
||||
@@ -1092,7 +1092,13 @@
|
||||
(is (= 10 (get-in result [:options :limit])))
|
||||
(is (= 2 (get-in result [:options :offset])))
|
||||
(is (= "priority" (get-in result [:options :sort])))
|
||||
(is (= "desc" (get-in result [:options :order]))))))
|
||||
(is (= "desc" (get-in result [:options :order])))))
|
||||
|
||||
(testing "list task supports short -c alias for --content"
|
||||
(let [result (commands/parse-args ["list" "task" "-c" "alpha"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :list-task (:command result)))
|
||||
(is (= "alpha" (get-in result [:options :content]))))))
|
||||
|
||||
(deftest test-search-subcommand-parse
|
||||
(testing "search block parses --content option"
|
||||
@@ -1181,7 +1187,13 @@
|
||||
(testing "list task rejects invalid priority"
|
||||
(let [result (commands/parse-args ["list" "task" "--priority" "wat"])]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :invalid-options (get-in result [:error :code]))))))
|
||||
(is (= :invalid-options (get-in result [:error :code])))))
|
||||
|
||||
(testing "list task defers unknown --status to runtime validation"
|
||||
(let [result (commands/parse-args ["list" "task" "--status" "custom-review"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :list-task (:command result)))
|
||||
(is (= "custom-review" (get-in result [:options :status]))))))
|
||||
|
||||
(deftest test-list-execute-default-sort-updated-at
|
||||
(async done
|
||||
@@ -1255,6 +1267,67 @@
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally done))))
|
||||
|
||||
(deftest test-task-runtime-invalid-status-includes-graph-values
|
||||
(async done
|
||||
(let [list-calls* (atom [])
|
||||
upsert-calls* (atom [])]
|
||||
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
|
||||
transport/invoke (fn [_ method _ args]
|
||||
(let [repo (first args)]
|
||||
(cond
|
||||
(= method :thread-api/q)
|
||||
(do
|
||||
(if (= repo "demo")
|
||||
(swap! list-calls* conj method)
|
||||
(swap! upsert-calls* conj method))
|
||||
[:logseq.property/status.todo
|
||||
:logseq.property/status.done
|
||||
:logseq.property/status.doing])
|
||||
|
||||
(= method :thread-api/cli-list-tasks)
|
||||
(do
|
||||
(swap! list-calls* conj method)
|
||||
[])
|
||||
|
||||
(= method :thread-api/pull)
|
||||
(do
|
||||
(swap! upsert-calls* conj method)
|
||||
{:db/id 1})
|
||||
|
||||
(= method :thread-api/apply-outliner-ops)
|
||||
(do
|
||||
(swap! upsert-calls* conj method)
|
||||
{:result :ok})
|
||||
|
||||
:else
|
||||
(throw (ex-info "unexpected invoke" {:method method :args args})))))]
|
||||
(p/let [list-result (list-command/execute-list-task
|
||||
{:repo "demo"
|
||||
:options {:status "invalid-status"}}
|
||||
{})
|
||||
upsert-result (upsert-command/execute-upsert-task
|
||||
{:repo "upsert-demo"
|
||||
:mode :update
|
||||
:id 1
|
||||
:status "invalid-status"}
|
||||
{})
|
||||
list-message (or (some-> (get-in list-result [:error :message]) strip-ansi) "")
|
||||
upsert-message (or (some-> (get-in upsert-result [:error :message]) strip-ansi) "")]
|
||||
(is (= :error (:status list-result)))
|
||||
(is (= :invalid-options (get-in list-result [:error :code])))
|
||||
(is (string/includes? list-message "Invalid value for option :status: invalid-status"))
|
||||
(is (string/includes? list-message "Available values (from current graph): doing, done, todo"))
|
||||
(is (= [:thread-api/q] @list-calls*))
|
||||
|
||||
(is (= :error (:status upsert-result)))
|
||||
(is (= :invalid-options (get-in upsert-result [:error :code])))
|
||||
(is (string/includes? upsert-message "Invalid value for option :status: invalid-status"))
|
||||
(is (string/includes? upsert-message "Available values (from current graph): doing, done, todo"))
|
||||
(is (= [:thread-api/q] @upsert-calls*))))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally done)))))
|
||||
|
||||
(deftest test-verb-subcommand-parse-upsert-remove
|
||||
(testing "remove block parses with id"
|
||||
(let [result (commands/parse-args ["remove" "block" "--id" "10"])]
|
||||
@@ -1389,13 +1462,14 @@
|
||||
(is (= :upsert-block (:command result)))
|
||||
(is (= "11111111-1111-1111-1111-111111111111" (get-in result [:options :uuid])))))
|
||||
|
||||
(testing "upsert block update mode accepts status-only updates"
|
||||
(testing "upsert block rejects --status and guides migration to upsert task"
|
||||
(let [result (commands/parse-args ["upsert" "block" "--id" "1"
|
||||
"--status" "done"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :upsert-block (:command result)))
|
||||
(is (= 1 (get-in result [:options :id])))
|
||||
(is (= "done" (get-in result [:options :status])))))
|
||||
"--status" "done"])
|
||||
message (strip-ansi (get-in result [:error :message]))]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :invalid-options (get-in result [:error :code])))
|
||||
(is (string/includes? message "--status"))
|
||||
(is (string/includes? message "upsert task"))))
|
||||
|
||||
(testing "upsert block update mode accepts content-only updates"
|
||||
(let [result (commands/parse-args ["upsert" "block" "--id" "1"
|
||||
@@ -1563,6 +1637,14 @@
|
||||
(is (= "done" (get-in result [:options :status])))
|
||||
(is (= "medium" (get-in result [:options :priority])))))
|
||||
|
||||
(testing "upsert task defers unknown --status to runtime validation"
|
||||
(let [result (commands/parse-args ["upsert" "task"
|
||||
"--id" "42"
|
||||
"--status" "custom-review"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :upsert-task (:command result)))
|
||||
(is (= "custom-review" (get-in result [:options :status])))))
|
||||
|
||||
(testing "upsert task requires selector, page, or content"
|
||||
(let [result (commands/parse-args ["upsert" "task"])]
|
||||
(is (false? (:ok? result)))
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
(let [entries list-command/entries
|
||||
page-entry (first (filter #(= :list-page (:command %)) entries))
|
||||
tag-entry (first (filter #(= :list-tag (:command %)) entries))
|
||||
property-entry (first (filter #(= :list-property (:command %)) entries))]
|
||||
property-entry (first (filter #(= :list-property (:command %)) entries))
|
||||
task-entry (first (filter #(= :list-task (:command %)) entries))]
|
||||
(testing "page-spec :sort has some correct values"
|
||||
(is (contains? (get-in page-entry [:spec :sort :validate]) "title")))
|
||||
(testing "tag-spec :sort has some correct values"
|
||||
@@ -68,7 +69,9 @@
|
||||
(let [mv (get-in tag-entry [:spec :fields :multiple-values])]
|
||||
(is (seq mv))
|
||||
(is (some #{"title"} mv))
|
||||
(is (some #{"uuid"} mv))))))
|
||||
(is (some #{"uuid"} mv))))
|
||||
(testing "list task :content has -c alias"
|
||||
(is (= :c (get-in task-entry [:spec :content :alias]))))))
|
||||
|
||||
(deftest test-upsert-spec-metadata
|
||||
(let [entries upsert-command/entries
|
||||
@@ -79,8 +82,8 @@
|
||||
(testing "block-spec :pos has :validate set"
|
||||
(is (= #{"first-child" "last-child" "sibling"}
|
||||
(get-in block-entry [:spec :pos :validate]))))
|
||||
(testing "block-spec :status has :validate set"
|
||||
(is (seq (get-in block-entry [:spec :status :validate]))))
|
||||
(testing "block-spec does not expose :status option"
|
||||
(is (nil? (get-in block-entry [:spec :status]))))
|
||||
(testing "block-spec :target-page has :complete :pages"
|
||||
(is (= :pages (get-in block-entry [:spec :target-page :complete]))))
|
||||
(testing "block-spec :blocks-file has :complete :file"
|
||||
@@ -275,7 +278,8 @@
|
||||
(is (not (string/includes? output "-c[Path to cli.edn (default ~/logseq/cli.edn)]:file:_files'"))))
|
||||
(testing "-c is available as content alias in command-specific completion"
|
||||
(is (re-find #"(?s)_logseq_search_block\(\).*?-c\[Search content text\]" output))
|
||||
(is (re-find #"(?s)_logseq_upsert_block\(\).*?-c\[Block content" output)))
|
||||
(is (re-find #"(?s)_logseq_upsert_block\(\).*?-c\[Block content" output))
|
||||
(is (re-find #"(?s)_logseq_list_task\(\).*?-c\[Filter by task title content\]" output)))
|
||||
(testing ":alias emits grouping without --no- for global flags"
|
||||
(is (re-find #"\(-h --help\)" output)))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user