Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/net/lewisship/cli_tools/builtins.clj
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
(ns net.lewisship.cli-tools.builtins
"Built-in commands, available to any tool."
{:command-category "Built-in"
:command-category-order 100}
(:require [net.lewisship.cli-tools.impl :as impl]
[net.lewisship.cli-tools :as cli :refer [defcommand]]))

(defcommand help
"List available commands.

If a search term is provided, the --commands option is ignored."
[output-level (cli/select-option "-c" "--commands FILTER" "Print commands: " #{:none :root :all}
[output-level (cli/select-option "-c" "--commands FILTER" "Print commands:"
#{:none :root :all}
:default :default)
:args
search-term ["SEARCH" "Filter shown commands to those that match this term"
:optional true]]
(if search-term
(impl/print-search-results search-term)
(impl/print-tool-help output-level)))

12 changes: 7 additions & 5 deletions src/net/lewisship/cli_tools/completions.clj
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@
(defn- extract-command
[fn-prefix [command-name command-map]]
(let [{:keys [fn]} command-map
title (binding [ansi/*color-enabled* false]
(impl/extract-command-title command-map))
title (-> (impl/extract-command-title command-map)
ansi/compose
string/trim)
fn-name (simplify fn-prefix command-name)]
;; TODO: Support messy group/command combos
(if fn
Expand Down Expand Up @@ -110,7 +111,8 @@
io/output-stream
io/writer)]
(try
(binding [*out* w]
(binding [*out* w
ansi/*color-enabled* false]
(print-tool tool-name command-root groups))
(catch Throwable t
(abort 1 [:red
Expand All @@ -119,5 +121,5 @@
(class t))]))))
(perr [:cyan "Wrote " output-path]))
;; Just write to standard output
(print-tool tool-name command-root groups)))))

(binding [ansi/*color-enabled* false]
(print-tool tool-name command-root groups))))))
2 changes: 1 addition & 1 deletion src/net/lewisship/cli_tools/impl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@
frequencies)]
[:faint
(when command-count
(list
(str
(h/numberword command-count) " "
(inflect/pluralize-noun command-count "sub-command")))
(when (and command-count group-count)
Expand Down
53 changes: 53 additions & 0 deletions test-resources/expected/messy-completions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#compdef _messy messy

_messy() {
local line state

_arguments -C \
"1: :->cmds" \
"*::arg:->args"

case "$state" in
cmds)
_values "messy command" \
"completions[Generate zsh command completions]" \
"simple[Simple command]" \
"messy[Messy command]" \
"help[List available commands]"
;;
args)
case $line[1] in
completions) _messy_completions ;;

simple) _messy_simple ;;

messy) _messy_messy ;;

help) _messy_help ;;

esac
;;
esac
}

_messy_completions() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_messy_simple() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_messy_messy() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_messy_help() {
_arguments -s \
'(-c --commands)'{-c,--commands}$'[Print commands: all, none, root]':FILTER \
'(-h --help)'{-h,--help}$'[This command summary]'
}

45 changes: 45 additions & 0 deletions test-resources/expected/simple-completions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#compdef _simple simple

_simple() {
local line state

_arguments -C \
"1: :->cmds" \
"*::arg:->args"

case "$state" in
cmds)
_values "simple command" \
"colors[Shows available foreground and background colors]" \
"completions[Generate zsh command completions]" \
"help[List available commands]"
;;
args)
case $line[1] in
colors) _simple_colors ;;

completions) _simple_completions ;;

help) _simple_help ;;

esac
;;
esac
}

_simple_colors() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_simple_completions() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_simple_help() {
_arguments -s \
'(-c --commands)'{-c,--commands}$'[Print commands: all, none, root]':FILTER \
'(-h --help)'{-h,--help}$'[This command summary]'
}

68 changes: 68 additions & 0 deletions test-resources/expected/subgroup-completions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#compdef _subgroup subgroup

_subgroup() {
local line state

_arguments -C \
"1: :->cmds" \
"*::arg:->args"

case "$state" in
cmds)
_values "subgroup command" \
"completions[Generate zsh command completions]" \
"help[List available commands]" \
"subgroup[one sub-command]"
;;
args)
case $line[1] in
completions) _subgroup_completions ;;

help) _subgroup_help ;;

subgroup) _subgroup_subgroup ;;

esac
;;
esac
}

_subgroup_completions() {
_arguments -s \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_subgroup_help() {
_arguments -s \
'(-c --commands)'{-c,--commands}$'[Print commands: all, none, root]':FILTER \
'(-h --help)'{-h,--help}$'[This command summary]'
}

_subgroup_subgroup() {
local state line

_arguments -C \
"1: :->cmds" \
"*::arg:->args"

case "$state" in
cmds)
_values "subgroup subgroup subcommands" \
"example[Does something interesting]"
;;
args)
case $line[1] in
example) _subgroup_subgroup_example ;;
esac
;;
esac
}


_subgroup_subgroup_example() {
_arguments -s \
'(-v --verbose)'{-v,--verbose}$'[Extra output]' \
'(-l --limit)'{-l,--limit}$'[Maximum globnars to frobnicate]':NUMBER \
'(-h --help)'{-h,--help}$'[This command summary]'
}

8 changes: 7 additions & 1 deletion test/net/lewisship/cli_tools/aux.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns net.lewisship.cli-tools.aux
(:require [clojure.test :refer [is]]
[net.lewisship.cli-tools.test :refer [with-exit]]))
[net.lewisship.cli-tools :as cli-tools]
[net.lewisship.cli-tools.test :refer [with-exit capture-result]]))

(defmacro with-exit-errors
[expected-errors & body]
Expand All @@ -9,3 +10,8 @@
(reset! *errors# errors#))]
(with-exit 1 ~@body))
(is (= @*errors# ~expected-errors))))

(defn dispatch-with-result
[options]
(capture-result
(cli-tools/dispatch (assoc options :cache-dir nil))))
10 changes: 10 additions & 0 deletions test/net/lewisship/cli_tools/completion_group.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(ns net.lewisship.cli-tools.completion-group
(:require [net.lewisship.cli-tools :refer [defcommand]]))

(defcommand example
"Does something interesting."
[verbose? ["-v" "--verbose" "Extra output"]
limit ["-l" "--limit NUMBER" "Maximum globnars to frobnicate"]]
;; Make linter happy
{:verbose? verbose?
:limit limit})
53 changes: 53 additions & 0 deletions test/net/lewisship/cli_tools/completions_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
(ns net.lewisship.cli-tools.completions-test
"Tests related to command completions."
(:require [clojure.java.io :as io]
[clojure.string :as string]
[clojure.test :refer [deftest is]]
[net.lewisship.cli-tools.aux :refer [dispatch-with-result]]))

(defn- expected [file]
(-> (str "expected/" file)
io/resource
slurp
string/split-lines))

(defn- dispatch
([options]
(-> options
(assoc :arguments ["completions"])
dispatch-with-result
:out-lines))
([to options]
(let [result (-> options
(assoc :arguments ["completions"])
dispatch-with-result
:out)]
(-> (str "test-resources/expected/" to)
io/file
(spit result))
(println result))))

(deftest simple-completions
(is (match? (expected "simple-completions.txt")
(dispatch '{:tool-name "simple"
:namespaces [net.lewisship.cli-tools.colors
net.lewisship.cli-tools.completions]}))))

(deftest subgroup-completion
(is (match? (expected "subgroup-completions.txt")
(dispatch
'{:tool-name "subgroup"
:namespaces [net.lewisship.cli-tools.completions]
:groups
{"subgroup" {:namespaces [net.lewisship.cli-tools.completion-group]}}}))))

(deftest messy-completions
;; where command name and group name collide
;; Not sure the current behavior is correct
(is (match? (expected "messy-completions.txt")
(dispatch
{:tool-name "messy"
:namespaces '[net.lewisship.cli-tools.completions
net.lewisship.messy-commands]
:groups {"messy" {:namespaces '[net.lewisship.messy]
:doc "Messy command and group at same time"}}}))))
Loading