diff --git a/src/climate.mli b/src/climate.mli index 996b5b7..b6e4468 100644 --- a/src/climate.mli +++ b/src/climate.mli @@ -219,7 +219,10 @@ module Command : sig (** A command that has the side effect of printing the completion script of the entire command it's contained inside. It's safe to - bury this inside a hidden command group of internal commands. *) + bury this inside a hidden command group of internal + commands. The command takes some arguments to configure the + generated completion script, similar to the arguments of the + function [completion_script_bash]. *) val print_completion_script_bash : _ t (** Returns a bash script that can be sourced in a shell to register diff --git a/tests/completion_tests/basic/main.ml b/tests/completion_tests/basic/basic.ml similarity index 100% rename from tests/completion_tests/basic/main.ml rename to tests/completion_tests/basic/basic.ml diff --git a/tests/completion_tests/basic/dune b/tests/completion_tests/basic/dune index e36f3f6..3e4d343 100644 --- a/tests/completion_tests/basic/dune +++ b/tests/completion_tests/basic/dune @@ -1,6 +1,6 @@ (executable - (public_name main) + (public_name basic) (libraries climate)) (cram - (deps main.exe)) + (deps basic.exe)) diff --git a/tests/completion_tests/basic/test.t b/tests/completion_tests/basic/test.t index b761e0c..9b072d9 100644 --- a/tests/completion_tests/basic/test.t +++ b/tests/completion_tests/basic/test.t @@ -1,4 +1,4 @@ - $ ./main.exe > completion.sh + $ ./basic.exe > completion.sh $ x() { ../print_completions.sh ./completion.sh _basic_complete "$1" "$2"; } $ x "basic " \ diff --git a/tests/completion_tests/fake_git/dune b/tests/completion_tests/fake_git/dune new file mode 100644 index 0000000..09de433 --- /dev/null +++ b/tests/completion_tests/fake_git/dune @@ -0,0 +1,6 @@ +(executable + (public_name fake_git) + (libraries climate unix)) + +(cram + (deps fake_git.exe)) diff --git a/tests/completion_tests/fake_git/fake_git.ml b/tests/completion_tests/fake_git/fake_git.ml new file mode 100644 index 0000000..34d0288 --- /dev/null +++ b/tests/completion_tests/fake_git/fake_git.ml @@ -0,0 +1,74 @@ +open Climate + +let ls dir = + let dir_handle = Unix.opendir dir in + let rec loop files = + try + let file = Unix.readdir dir_handle in + loop (file :: files) + with + | End_of_file -> files + in + List.rev (loop []) +;; + +(* Fake protocol for defining branches so the list of branches can be + updated dynamically by tests. *) +let list_branches () = + ls "./.git/branches" + |> List.filter (Fun.negate @@ String.starts_with ~prefix:".") + |> List.sort String.compare +;; + +let branch_conv = + let open Arg_parser in + { string with + default_value_name = "BRANCH" + ; completion = Some (Completion.reentrant_thunk list_branches) + } +;; + +(* A command which mixes reentrant completion with file completion *) +let checkout = + let open Arg_parser in + let+ _create_branch = flag [ "b" ] + and+ _branch_name = pos_req 0 branch_conv + and+ _files = pos_right 1 file in + () +;; + +(* A command which mixes reentrant completion with a named argument + with a value completed with an enum *) +let log = + let open Arg_parser in + let+ _pretty = + named_opt [ "pretty"; "p" ] (string_enum [ "full"; "fuller"; "short"; "oneline" ]) + and+ _branch_name = pos_req 0 branch_conv in + () +;; + +(* A command which mixes positional arguments and subcommands *) +let bisect op = + let open Arg_parser in + match op with + | `Mark -> + let+ _status = pos_opt 0 (string_enum [ "good"; "bad" ]) in + () + | `Start | `Reset -> unit +;; + +let () = + let open Command in + group + [ subcommand "checkout" (singleton checkout) + ; subcommand "log" (singleton log) + ; subcommand "bisect" + @@ group + ~default_arg_parser:(bisect `Mark) + [ subcommand "start" (singleton (bisect `Start)) + ; subcommand "reset" (singleton (bisect `Reset)) + ] + ; subcommand "completions" ~hidden:true print_completion_script_bash + ] + |> run +;; diff --git a/tests/completion_tests/fake_git/test.t b/tests/completion_tests/fake_git/test.t new file mode 100644 index 0000000..fe2ff8b --- /dev/null +++ b/tests/completion_tests/fake_git/test.t @@ -0,0 +1,101 @@ + $ ./fake_git.exe completions --program-name=fake-git --global-symbol-prefix=_fake_git_ > completion.sh + $ x() { ../print_completions.sh ./completion.sh _fake_git_complete "$1" "$2"; } + +Make a fake .git directory with some branches. + $ mkdir -p .git/branches + $ touch .git/branches/foo + $ touch .git/branches/bar + + $ x "fake-git " \ + > " ^" + checkout + log + bisect + + $ x "fake-git checkout " \ + > " ^" + bar + foo + + $ x "fake-git checkout foo " \ + > " ^" + .git + completion.sh + fake_git.exe + + $ x "fake-git checkout foo a.txt " \ + > " ^" + .git + completion.sh + fake_git.exe + + $ x "fake-git checkout foo a.txt " \ + > " ^ " + bar + foo + + $ x "fake-git checkout foo a.txt " \ + > " ^ " + .git + completion.sh + fake_git.exe + + $ x "fake-git log " \ + > " ^" + bar + foo + + $ x "fake-git log -" \ + > " ^" + --help + --pretty + -h + -p + + $ x "fake-git log --" \ + > " ^" + --help + --pretty + + $ x "fake-git log --pretty " \ + > " ^" + full + fuller + short + oneline + + $ x "fake-git log --pretty f" \ + > " ^" + full + fuller + + $ x "fake-git log --pretty full " \ + > " ^" + bar + foo + + + $ x "fake-git log --pretty full foo " \ + > " ^" + --help + --pretty + -h + -p + +Test that positional arguments and subcommands are both listed. + $ x "fake-git bisect " \ + > " ^" + start + reset + good + bad + + $ x "fake-git bisect -" \ + > " ^" + --help + -h + + $ x "fake-git bisect start " \ + > " ^" + --help + -h