1use super::super::{
2 cli::InitArgs,
3 constants::SCRIPT_ROOT_ENVIRONMENT_VARIABLE,
4 shell_type::{get_shell_type, ShellType},
5};
6
7macro_rules! bash_zsh_init_body {
12 () => {
13 r#"
14if [[ -n ${{ZSH_VERSION-}} ]]; then
15 # bash completion emulation requires that zsh's completion has
16 # already been initialized. In addition, running the autoload
17 # expression with the ampersands seems to always result in
18 # compinit being executed, which clear completions that were
19 # previously bound by tome, resulting in the inability to
20 # instantiate multiple tome command sets.
21 if ! type complete > /dev/null; then
22 # add -C "" to skip compaudit, which forces
23 # an interactive dialog for compinit which doesn't
24 # work for interactive shells.
25 autoload +X compinit && compinit -C ""
26 fi
27 autoload +X bashcompinit && bashcompinit
28
29fi
30
31# completion is accomplished by three parts:
32# 1. passing all possible completions to {tome_executable}
33# 2. filtering for valid options using compgen
34# 3. appending to the valid option environment variable.
35function {function_name} {{
36 export {script_root_environment_variable}="{script_root}"
37 # capturing the results as a variable led to the command
38 # being to long for zsh to execute. (literally raising
39 # "command too long" )
40 eval `{tome_executable} command-execute {script_root} -s {shell} -- "$@"`
41}}
42
43function _{function_name}_completions {{
44 export {script_root_environment_variable}="{script_root}"
45 local token_to_complete tome_args
46 token_to_complete="${{COMP_WORDS[COMP_CWORD]}}";
47 tome_args="${{COMP_WORDS[@]:1}}"; # strip the first argument prefix, which is the function name
48 # strip the partial token_to_complete, if there is one
49 tome_args="${{tome_args%$token_to_complete}}";
50 all_options=`{tome_executable} command-complete {script_root} -s {shell} -- $tome_args`
51 valid_options=$(compgen -W "$all_options" -- "$token_to_complete")
52 COMPREPLY=($valid_options)
53}}
54
55complete -F _{function_name}_completions {function_name}
56"#
57 };
58}
59
60macro_rules! fish_init_body {
61 () => {
62 r#"
63# Note: to perform debugging when interface for tome changes
64# set set -l fish_trace on before the buggy part of fish script
65function __fish_tome_help_message
66 echo -e "--help\tPrint help\n"
67end
68
69function __fish_tome_complete_subcommands
70 # Arguments: tome command-complete ./example -s fish -- ARGS
71 $argv[1] $argv[2] $argv[3] $argv[4] $argv[5] $argv[6..-1] | tr " " "\n"
72 return 0
73end
74
75function __fish_tome_completion_inner
76 set -l help_msg
77 set -l tokens $argv
78 switch (count $tokens)
79 case 0
80 # Being used as function in fish
81 __fish_tome_complete_subcommands $tokens
82 case '*'
83 __fish_tome_complete_subcommands $tokens
84 end
85end
86
87function __fish_tome_completion_binary
88 set -l help_msg
89 set -l tokens $argv
90 switch (count $tokens)
91 case 0
92 echo "Bad codepath"
93 exit 1
94 case 1
95 # > tome
96 # needs commands
97 __fish_tome_help_message
98 echo -e "command-complete\tCompletions\n"
99 echo -e "command-execute\tExecute\n"
100 echo -e "help\tHelp\n"
101 echo -e "init\tInitialize Tome\n"
102 case 2
103 # > tome CMD
104 # return all current directories
105 ls -d -1 */
106 __fish_tome_help_message
107 case 3
108 echo -e "--shell\tShell\n"
109 case 4
110 echo -e "bash\tBash\n"
111 echo -e "zsh\tZsh\n"
112 echo -e "fish\tFish\n"
113 case 5
114 echo -e "--\tSeparator\n"
115 case '*'
116 __fish_tome_complete_subcommands $tokens
117 end
118end
119
120function __fish_tome_completion
121 set -l args (commandline -co)
122 set -x {script_root_environment_variable} "{script_root}"
123 switch $args[1]
124 case 'tome'
125 __fish_tome_completion_binary $args
126 case '*'
127 echo "Bad codepath"
128 exit 1
129 end
130end
131
132function __fish_tome_completion_fn
133 set -l dir $argv[1]
134 set -l cmdline (commandline -co)
135 # Drop function name
136 set -l cmd $cmdline[2..-1]
137 set -l args "{tome_executable}" command-complete $dir -s "{shell}" -- $cmd
138 __fish_tome_completion_inner $args
139end
140
141complete -c tome -f -a "(__fish_tome_completion)"
142
143# Alias for tome command
144function {function_name}
145 set -x {script_root_environment_variable} "{script_root}"
146 eval ({tome_executable} command-execute {script_root} -s {shell} -- $argv)
147end
148complete -c {function_name} -f -a "(__fish_tome_completion_fn {script_root} $argv)"
149# End tome alias
150"#
151 };
152}
153
154pub fn init(tome_executable: &str, init_args: &InitArgs) -> Result<String, String> {
157 let shell = get_shell_type(&init_args.shell_type_or_path)?;
158 match shell {
167 ShellType::FISH => Ok(format!(
168 fish_init_body!(),
169 tome_executable = tome_executable,
170 shell = &init_args.shell_type_or_path,
171 script_root = init_args.command_directory_path,
172 function_name = init_args.command_name,
173 script_root_environment_variable = SCRIPT_ROOT_ENVIRONMENT_VARIABLE,
174 )),
175 ShellType::BASH | ShellType::ZSH => Ok(format!(
176 bash_zsh_init_body!(),
177 tome_executable = tome_executable,
178 shell = &init_args.shell_type_or_path,
179 script_root = init_args.command_directory_path,
180 function_name = init_args.command_name,
181 script_root_environment_variable = SCRIPT_ROOT_ENVIRONMENT_VARIABLE,
182 )),
183 ShellType::UNKNOWN => Err(format!(
184 "could not determine shell from {}. Unable to init.",
185 &init_args.shell_type_or_path
186 )),
187 }
188}