module Doing::Completion
Completion
script generator
Constants
- COMMAND_RX
- OPTIONS_RX
- SECTIONS_RX
Public Class Methods
generate_completion(type: 'zsh', file: :default, link: true)
click to toggle source
Generate a completion script and output to file or stdout
@param type [String] shell to generate for (zsh|bash|fish) @param file [String] Path to save to, or ‘stdout’
# File lib/doing/completion.rb, line 68 def generate_completion(type: 'zsh', file: :default, link: true) return generate_all if type =~ /^all$/i file = file == :default ? default_file(type) : file file = validate_target(file) result = generate_type(type) if file =~ /^stdout$/i $stdout.puts result else File.open(file, 'w') { |f| f.puts result } Doing.logger.warn('File written:', "#{type} completions written to #{file}") link_completion_type(type, file) if link end end
get_help_sections(command = "")
click to toggle source
# File lib/doing/completion.rb, line 19 def get_help_sections(command = "") res = `doing help #{command}|command cat`.strip scanned = res.scan(SECTIONS_RX) sections = {} scanned.each do |sect| title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?) sections[title] = content end sections end
install_builtin(type)
click to toggle source
# File lib/doing/completion.rb, line 96 def install_builtin(type) FileUtils.mkdir_p(default_dir) src = File.expand_path(File.join(File.dirname(__FILE__), '..', 'completion', default_filenames[type])) if File.exist?(File.join(default_dir, default_filenames[type])) return unless Doing::Prompt.yn("Update #{type} completion script", default_response: 'n') end FileUtils.cp(src, default_dir) Doing.logger.warn('File written:', "#{type} completions saved to #{default_file(type)}") end
link_default(type)
click to toggle source
# File lib/doing/completion.rb, line 85 def link_default(type) type = normalize_type(type) raise InvalidArgument, 'Unrecognized shell specified' if type == :invalid return %i[zsh bash fish fig].each { |t| link_default(t) } if type == :all install_builtin(type) link_completion_type(type, File.join(default_dir, default_filenames[type])) end
normalize_type(type)
click to toggle source
# File lib/doing/completion.rb, line 109 def normalize_type(type) case type.to_s when /^fig/i :fig when /^f/i :fish when /^b/i :bash when /^z/i :zsh when /^a/i :all else :invalid end end
parse_command(command)
click to toggle source
# File lib/doing/completion.rb, line 47 def parse_command(command) res = command.match(COMMAND_RX) commands = [res['cmd']] commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias'] { commands: commands, description: res['desc'].short_desc } end
parse_commands(commands)
click to toggle source
# File lib/doing/completion.rb, line 58 def parse_commands(commands) commands.map { |cmd| parse_command(cmd) } end
parse_option(option)
click to toggle source
# File lib/doing/completion.rb, line 31 def parse_option(option) res = option.match(OPTIONS_RX) return nil unless res { short: res['short'], long: res['long'], arg: res['arg'], description: res['desc'].short_desc } end
parse_options(options)
click to toggle source
# File lib/doing/completion.rb, line 43 def parse_options(options) options.map { |opt| parse_option(opt) } end
Private Class Methods
default_dir()
click to toggle source
# File lib/doing/completion.rb, line 153 def default_dir File.expand_path('~/.local/share/doing/completion') end
default_file(type)
click to toggle source
# File lib/doing/completion.rb, line 161 def default_file(type) type = normalize_type(type) File.join(default_dir, default_filenames[type]) end
default_filenames()
click to toggle source
# File lib/doing/completion.rb, line 157 def default_filenames { zsh: '_doing.zsh', bash: 'doing.bash', fish: 'doing.fish', fig: 'doing.ts' } end
generate_all()
click to toggle source
# File lib/doing/completion.rb, line 189 def generate_all Doing.logger.log_now(:warn, 'Generating:', 'all completion types, will use default paths') generate_completion(type: 'fish', file: 'lib/completion/doing.fish', link: false) Doing.logger.warn('File written:', 'fish completions written to lib/completion/doing.fish') generate_completion(type: 'zsh', file: 'lib/completion/_doing.zsh', link: false) Doing.logger.warn('File written:', 'zsh completions written to lib/completion/_doing.zsh') generate_completion(type: 'bash', file: 'lib/completion/doing.bash', link: false) Doing.logger.warn('File written:', 'bash completions written to lib/completion/doing.bash') generate_completion(type: 'fig', file: 'lib/completion/doing.ts', link: false) Doing.logger.warn('File written:', 'Fig completions written to lib/completion/doing.ts') end
generate_type(type)
click to toggle source
# File lib/doing/completion.rb, line 128 def generate_type(type) generator = case type.to_s when /^fig/i FigCompletions.new when /^f/i FishCompletions.new when /^b/i BashCompletions.new else ZshCompletions.new end generator.generate_completions end
link_completion(file, targets, filename)
click to toggle source
# File lib/doing/completion.rb, line 218 def link_completion(file, targets, filename) return if targets.map { |t| File.expand_path(t) }.include?(File.dirname(file)) found = false linked = false targets.each do |target| next unless File.directory?(File.expand_path(target)) found = true target_file = File.join(File.expand_path(target), filename) next unless Doing::Prompt.yn("Create link to #{target_file}", default_response: 'n') FileUtils.ln_s(File.expand_path(file), target_file, force: true) Doing.logger.warn('File linked:', "#{File.expand_path(file)} -> #{target_file}") linked = true break end return if linked unless found $stdout.puts 'No known auto-load directory found for specified shell'.red $stdout.puts "Looked for #{targets.join(', ')}, found no existing directory".yellow end $stdout.puts 'If you don\'t want to autoload completions'.yellow $stdout.puts 'you can source the script directly in your shell\'s startup file:'.yellow $stdout.puts %(source "#{file}").boldwhite end
link_completion_type(type, file)
click to toggle source
# File lib/doing/completion.rb, line 201 def link_completion_type(type, file) dir = File.dirname(file) case type.to_s when /^b/i unless dir =~ %r{(\.bash_it/completion|bash_completion/completions)} link_completion(file, ['~/.bash_it/completion/enabled', '/usr/share/bash-completion/completions', '/usr/share/bash_completion/completions'], 'doing.bash') end when /^fig/i when /^f/i link_completion(file, ['~/.config/fish/completions'], 'doing.fish') unless dir =~ %r{.config/fish/completions} when /^z/i unless dir =~ %r{(\.oh-my-zsh/completions|share/site-functions)} link_completion(file, ['~/.oh-my-zsh/completions', '/usr/local/share/zsh/site-functions'], '_doing.zsh') end end end
validate_dir(file)
click to toggle source
# File lib/doing/completion.rb, line 178 def validate_dir(file) dir = File.dirname(file) unless File.directory?(dir) res = Doing::Prompt.yn("#{dir} doesn't exist, create it", default_response: 'y') raise UserCancelled unless res FileUtils.mkdir_p(dir) end dir end
validate_file(file)
click to toggle source
# File lib/doing/completion.rb, line 167 def validate_file(file) file = File.expand_path(file) if File.exist?(file) res = Doing::Prompt.yn("Overwrite #{file}", default_response: 'y') raise UserCancelled unless res FileUtils.rm(file) if res end file end
validate_target(file)
click to toggle source
# File lib/doing/completion.rb, line 143 def validate_target(file) unless file =~ /stdout/i file = validate_file(file) validate_dir(file) end file end