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
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
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