| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "utils/link" | 
					
						
							| 
									
										
										
										
											2021-01-12 16:27:25 -05:00
										 |  |  | require "settings" | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  | require "erb" | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  | module Homebrew | 
					
						
							|  |  |  |   # Helper functions for generating shell completions. | 
					
						
							|  |  |  |   module Completions | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |     Variables = Struct.new( | 
					
						
							|  |  |  |       :aliases, | 
					
						
							|  |  |  |       :builtin_command_descriptions, | 
					
						
							|  |  |  |       :completion_functions, | 
					
						
							|  |  |  |       :function_mappings, | 
					
						
							|  |  |  |       keyword_init: true, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     COMPLETIONS_DIR = T.let((HOMEBREW_REPOSITORY/"completions").freeze, Pathname) | 
					
						
							|  |  |  |     TEMPLATE_DIR = T.let((HOMEBREW_LIBRARY_PATH/"completions").freeze, Pathname) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     SHELLS = %w[bash fish zsh].freeze | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |     COMPLETIONS_EXCLUSION_LIST = %w[
 | 
					
						
							|  |  |  |       instal | 
					
						
							|  |  |  |       uninstal | 
					
						
							|  |  |  |       update-report | 
					
						
							|  |  |  |     ].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     BASH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING = T.let({ | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       formula:           "__brew_complete_formulae", | 
					
						
							|  |  |  |       installed_formula: "__brew_complete_installed_formulae", | 
					
						
							|  |  |  |       outdated_formula:  "__brew_complete_outdated_formulae", | 
					
						
							|  |  |  |       cask:              "__brew_complete_casks", | 
					
						
							|  |  |  |       installed_cask:    "__brew_complete_installed_casks", | 
					
						
							|  |  |  |       outdated_cask:     "__brew_complete_outdated_casks", | 
					
						
							|  |  |  |       tap:               "__brew_complete_tapped", | 
					
						
							|  |  |  |       installed_tap:     "__brew_complete_tapped", | 
					
						
							|  |  |  |       command:           "__brew_complete_commands", | 
					
						
							| 
									
										
										
										
											2023-02-23 18:36:51 -07:00
										 |  |  |       diagnostic_check:  '__brewcomp "${__HOMEBREW_DOCTOR_CHECKS=$(brew doctor --list-checks)}"', | 
					
						
							| 
									
										
										
										
											2021-01-18 13:30:47 -05:00
										 |  |  |       file:              "__brew_complete_files", | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     }.freeze, T::Hash[Symbol, String]) | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING = T.let({ | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |       formula:           "__brew_formulae", | 
					
						
							|  |  |  |       installed_formula: "__brew_installed_formulae", | 
					
						
							|  |  |  |       outdated_formula:  "__brew_outdated_formulae", | 
					
						
							|  |  |  |       cask:              "__brew_casks", | 
					
						
							|  |  |  |       installed_cask:    "__brew_installed_casks", | 
					
						
							|  |  |  |       outdated_cask:     "__brew_outdated_casks", | 
					
						
							|  |  |  |       tap:               "__brew_any_tap", | 
					
						
							|  |  |  |       installed_tap:     "__brew_installed_taps", | 
					
						
							|  |  |  |       command:           "__brew_commands", | 
					
						
							|  |  |  |       diagnostic_check:  "__brew_diagnostic_checks", | 
					
						
							|  |  |  |       file:              "__brew_formulae_or_ruby_files", | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     }.freeze, T::Hash[Symbol, String]) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     FISH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING = T.let({ | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |       formula:           "__fish_brew_suggest_formulae_all", | 
					
						
							|  |  |  |       installed_formula: "__fish_brew_suggest_formulae_installed", | 
					
						
							|  |  |  |       outdated_formula:  "__fish_brew_suggest_formulae_outdated", | 
					
						
							|  |  |  |       cask:              "__fish_brew_suggest_casks_all", | 
					
						
							|  |  |  |       installed_cask:    "__fish_brew_suggest_casks_installed", | 
					
						
							|  |  |  |       outdated_cask:     "__fish_brew_suggest_casks_outdated", | 
					
						
							|  |  |  |       tap:               "__fish_brew_suggest_taps_installed", | 
					
						
							|  |  |  |       installed_tap:     "__fish_brew_suggest_taps_installed", | 
					
						
							|  |  |  |       command:           "__fish_brew_suggest_commands", | 
					
						
							|  |  |  |       diagnostic_check:  "__fish_brew_suggest_diagnostic_checks", | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     }.freeze, T::Hash[Symbol, String]) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     sig { void } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.link! | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       Settings.write :linkcompletions, true | 
					
						
							| 
									
										
										
										
											2024-03-06 20:58:34 -08:00
										 |  |  |       Tap.installed.each do |tap| | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |         Utils::Link.link_completions tap.path, "brew completions link" | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     sig { void } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.unlink! | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       Settings.write :linkcompletions, false | 
					
						
							| 
									
										
										
										
											2024-03-06 20:58:34 -08:00
										 |  |  |       Tap.installed.each do |tap| | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |         next if tap.official? | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |         Utils::Link.unlink_completions tap.path | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.link_completions? | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       Settings.read(:linkcompletions) == "true" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.completions_to_link? | 
					
						
							| 
									
										
										
										
											2024-03-06 20:58:34 -08:00
										 |  |  |       Tap.installed.each do |tap| | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |         next if tap.official? | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |         SHELLS.each do |shell| | 
					
						
							|  |  |  |           return true if (tap.path/"completions/#{shell}").exist? | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |     sig { void } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.show_completions_message_if_needed | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       return if Settings.read(:completionsmessageshown) == "true" | 
					
						
							|  |  |  |       return unless completions_to_link? | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       ohai "Homebrew completions for external commands are unlinked by default!" | 
					
						
							|  |  |  |       puts <<~EOS | 
					
						
							| 
									
										
										
										
											2021-05-08 11:20:01 +10:00
										 |  |  |         To opt-in to automatically linking external tap shell completion files, run: | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |           brew completions link | 
					
						
							|  |  |  |         Then, follow the directions at #{Formatter.url("https://docs.brew.sh/Shell-Completion")} | 
					
						
							|  |  |  |       EOS | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:16:09 -05:00
										 |  |  |       Settings.write :completionsmessageshown, true | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sig { void } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.update_shell_completions! | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       commands = Commands.commands(external: false, aliases: true).sort | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 16:42:28 -05:00
										 |  |  |       puts "Writing completions to #{COMPLETIONS_DIR}" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       (COMPLETIONS_DIR/"bash/brew").atomic_write generate_bash_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |       (COMPLETIONS_DIR/"zsh/_brew").atomic_write generate_zsh_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |       (COMPLETIONS_DIR/"fish/brew.fish").atomic_write generate_fish_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(command: String).returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.command_gets_completions?(command) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       command_options(command).any? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |     sig { params(description: String, fish: T::Boolean).returns(String) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.format_description(description, fish: false) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |       description = if fish | 
					
						
							|  |  |  |         description.gsub("'", "\\\\'") | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         description.gsub("'", "'\\\\''") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       description.gsub(/[<>]/, "").tr("\n", " ").chomp(".") | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |     sig { params(command: String).returns(T::Hash[String, String]) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.command_options(command) | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |       options = {} | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       Commands.command_options(command)&.each do |option| | 
					
						
							|  |  |  |         next if option.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         name = option.first | 
					
						
							| 
									
										
										
										
											2021-01-24 16:42:28 -05:00
										 |  |  |         desc = option.second | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |         if name.start_with? "--[no-]" | 
					
						
							| 
									
										
										
										
											2024-01-02 16:54:18 -08:00
										 |  |  |           options[name.gsub("[no-]", "")] = desc | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |           options[name.sub("[no-]", "no-")] = desc | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |           options[name] = desc | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |       options | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(command: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_bash_subcommand_completion(command) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |       return unless command_gets_completions? command | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       named_completion_string = "" | 
					
						
							| 
									
										
										
										
											2021-02-12 18:33:37 +05:30
										 |  |  |       if (types = Commands.named_args_type(command)) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |         named_args_strings, named_args_types = types.partition { |type| type.is_a? String } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         named_args_types.each do |type| | 
					
						
							|  |  |  |           next unless BASH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING.key? type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           named_completion_string += "\n  #{BASH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING[type]}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         named_completion_string += "\n  __brewcomp \"#{named_args_strings.join(" ")}\"" if named_args_strings.any? | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <<~COMPLETION | 
					
						
							|  |  |  |         _brew_#{Commands.method_name command}() { | 
					
						
							|  |  |  |           local cur="${COMP_WORDS[COMP_CWORD]}" | 
					
						
							| 
									
										
										
										
											2021-05-02 14:26:12 +05:30
										 |  |  |           case "${cur}" in | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |             -*) | 
					
						
							|  |  |  |               __brewcomp "
 | 
					
						
							| 
									
										
										
										
											2021-01-24 03:12:52 -05:00
										 |  |  |               #{command_options(command).keys.sort.join("\n      ")} | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |               "
 | 
					
						
							|  |  |  |               return | 
					
						
							|  |  |  |               ;; | 
					
						
							| 
									
										
										
										
											2023-02-23 18:36:51 -07:00
										 |  |  |             *) ;; | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  |           esac#{named_completion_string} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       COMPLETION | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |     sig { params(commands: T::Array[String]).returns(String) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_bash_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       variables = Variables.new( | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         completion_functions: commands.filter_map do |command| | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           generate_bash_subcommand_completion command | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end, | 
					
						
							|  |  |  |         function_mappings:    commands.filter_map do |command| | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           next unless command_gets_completions? command | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           "#{command}) _brew_#{Commands.method_name command} ;;" | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end, | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-01-05 22:44:39 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ERB.new((TEMPLATE_DIR/"bash.erb").read, trim_mode: ">").result(variables.instance_eval { binding }) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sig { params(command: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_zsh_subcommand_completion(command) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |       return unless command_gets_completions? command | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |       options = command_options(command) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |       args_options = [] | 
					
						
							| 
									
										
										
										
											2021-02-12 18:33:37 +05:30
										 |  |  |       if (types = Commands.named_args_type(command)) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |         named_args_strings, named_args_types = types.partition { |type| type.is_a? String } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         named_args_types.each do |type| | 
					
						
							|  |  |  |           next unless ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING.key? type | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |           args_options << "- #{type}" | 
					
						
							| 
									
										
										
										
											2021-03-16 10:52:18 +05:30
										 |  |  |           opt = "--#{type.to_s.gsub(/(installed|outdated)_/, "")}" | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |           if options.key?(opt) | 
					
						
							|  |  |  |             desc = options[opt] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if desc.blank? | 
					
						
							|  |  |  |               args_options << opt | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |               conflicts = generate_zsh_option_exclusions(command, opt) | 
					
						
							|  |  |  |               args_options << "#{conflicts}#{opt}[#{format_description desc}]" | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             options.delete(opt) | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           args_options << "*::#{type}:#{ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING[type]}" | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |         if named_args_strings.any? | 
					
						
							|  |  |  |           args_options << "- subcommand" | 
					
						
							|  |  |  |           args_options << "*::subcommand:(#{named_args_strings.join(" ")})" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       options = options.sort.map do |opt, desc| | 
					
						
							|  |  |  |         next opt if desc.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         conflicts = generate_zsh_option_exclusions(command, opt) | 
					
						
							|  |  |  |         "#{conflicts}#{opt}[#{format_description desc}]" | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |       options += args_options | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       <<~COMPLETION | 
					
						
							|  |  |  |         # brew #{command} | 
					
						
							|  |  |  |         _brew_#{Commands.method_name command}() { | 
					
						
							|  |  |  |           _arguments \\ | 
					
						
							| 
									
										
										
										
											2021-03-14 00:54:45 +05:30
										 |  |  |             #{options.map! { |opt| opt.start_with?("- ") ? opt : "'#{opt}'" }.join(" \\\n    ")} | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |       COMPLETION | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 13:01:31 -04:00
										 |  |  |     sig { params(command: String, option: String).returns(String) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_zsh_option_exclusions(command, option) | 
					
						
							| 
									
										
										
										
											2024-09-26 20:23:08 -04:00
										 |  |  |       conflicts = Commands.option_conflicts(command, option.gsub(/^--?/, "")) | 
					
						
							| 
									
										
										
										
											2021-01-27 13:45:11 +11:00
										 |  |  |       return "" unless conflicts.presence | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 20:23:08 -04:00
										 |  |  |       "(#{conflicts.map { |conflict| "-#{"-" if conflict.size > 1}#{conflict}" }.join(" ")})" | 
					
						
							| 
									
										
										
										
											2021-01-27 13:45:11 +11:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  |     sig { params(commands: T::Array[String]).returns(String) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_zsh_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       variables = Variables.new( | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         aliases:                      Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.filter_map do |alias_cmd, command| | 
					
						
							|  |  |  |           alias_cmd = "'#{alias_cmd}'" if alias_cmd.start_with? "-" | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           command = "'#{command}'" if command.start_with? "-" | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |           "#{alias_cmd} #{command}" | 
					
						
							|  |  |  |         end, | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         builtin_command_descriptions: commands.filter_map do |command| | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           next if Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.key? command | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           description = Commands.command_description(command, short: true) | 
					
						
							|  |  |  |           next if description.blank? | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           description = format_description description | 
					
						
							|  |  |  |           "'#{command}:#{description}'" | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end, | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         completion_functions:         commands.filter_map do |command| | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           generate_zsh_subcommand_completion command | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end, | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-01-24 01:59:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ERB.new((TEMPLATE_DIR/"zsh.erb").read, trim_mode: ">").result(variables.instance_eval { binding }) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sig { params(command: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_fish_subcommand_completion(command) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |       return unless command_gets_completions? command | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       command_description = format_description Commands.command_description(command, short: true), fish: true | 
					
						
							| 
									
										
										
										
											2024-11-20 09:41:29 -06:00
										 |  |  |       lines = if COMPLETIONS_EXCLUSION_LIST.include?(command) | 
					
						
							|  |  |  |         [] | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         ["__fish_brew_complete_cmd '#{command}' '#{command_description}'"] | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |       options = command_options(command).sort.filter_map do |opt, desc| | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |         arg_line = "__fish_brew_complete_arg '#{command}' -l #{opt.sub(/^-+/, "")}" | 
					
						
							|  |  |  |         arg_line += " -d '#{format_description desc, fish: true}'" if desc.present? | 
					
						
							|  |  |  |         arg_line | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       subcommands = [] | 
					
						
							|  |  |  |       named_args = [] | 
					
						
							| 
									
										
										
										
											2021-02-12 18:33:37 +05:30
										 |  |  |       if (types = Commands.named_args_type(command)) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |         named_args_strings, named_args_types = types.partition { |type| type.is_a? String } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         named_args_types.each do |type| | 
					
						
							|  |  |  |           next unless FISH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING.key? type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           named_arg_function = FISH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING[type] | 
					
						
							| 
									
										
										
										
											2021-04-27 19:42:28 -04:00
										 |  |  |           named_arg_prefix = "__fish_brew_complete_arg '#{command}; and not __fish_seen_argument" | 
					
						
							| 
									
										
										
										
											2021-03-09 13:48:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 19:42:28 -04:00
										 |  |  |           formula_option = command_options(command).key?("--formula") | 
					
						
							|  |  |  |           cask_option = command_options(command).key?("--cask") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           named_args << if formula_option && cask_option && type.to_s.end_with?("formula") | 
					
						
							| 
									
										
										
										
											2021-03-09 13:48:07 +08:00
										 |  |  |             "#{named_arg_prefix} -l cask -l casks' -a '(#{named_arg_function})'" | 
					
						
							| 
									
										
										
										
											2021-04-27 19:42:28 -04:00
										 |  |  |           elsif formula_option && cask_option && type.to_s.end_with?("cask") | 
					
						
							| 
									
										
										
										
											2021-03-09 13:48:07 +08:00
										 |  |  |             "#{named_arg_prefix} -l formula -l formulae' -a '(#{named_arg_function})'" | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             "__fish_brew_complete_arg '#{command}' -a '(#{named_arg_function})'" | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         named_args_strings.each do |subcommand| | 
					
						
							|  |  |  |           subcommands << "__fish_brew_complete_sub_cmd '#{command}' '#{subcommand}'" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       lines += subcommands + options + named_args | 
					
						
							|  |  |  |       <<~COMPLETION | 
					
						
							|  |  |  |         #{lines.join("\n").chomp} | 
					
						
							|  |  |  |       COMPLETION | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(commands: T::Array[String]).returns(String) } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.generate_fish_completion_file(commands) | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       variables = Variables.new( | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         completion_functions: commands.filter_map do |command| | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |           generate_fish_subcommand_completion command | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end, | 
					
						
							| 
									
										
										
										
											2023-02-28 12:24:22 -08:00
										 |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:47:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ERB.new((TEMPLATE_DIR/"fish.erb").read, trim_mode: ">").result(variables.instance_eval { binding }) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-11 12:24:48 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2021-01-08 11:10:24 -05:00
										 |  |  | end |