Class: Doing::Completion::BashCompletions

Inherits:
Object
  • Object
show all
Defined in:
lib/doing/completion/bash_completion.rb

Overview

Generate completions for Bash

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeBashCompletions

Returns a new instance of BashCompletions.



125
126
127
128
129
130
131
132
# File 'lib/doing/completion/bash_completion.rb', line 125

def initialize
  data = Completion.get_help_sections
  @global_options = Completion.parse_options(data[:global_options])
  @commands = Completion.parse_commands(data[:commands])
  @bar = TTY::ProgressBar.new("\033[0;0;33mGenerating Bash completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'Reading subcommands')
  width = TTY::Screen.columns - 45
  @bar.resize(width)
end

Instance Attribute Details

#commandsObject

Returns the value of attribute commands.



7
8
9
# File 'lib/doing/completion/bash_completion.rb', line 7

def commands
  @commands
end

#global_optionsObject

Returns the value of attribute global_options.



7
8
9
# File 'lib/doing/completion/bash_completion.rb', line 7

def global_options
  @global_options
end

Instance Method Details

#command_function(command, options, type) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/doing/completion/bash_completion.rb', line 63

def command_function(command, options, type)
  long_options = []
  short_options = []

  options.each do |o|
    next if o.nil?

    long_options << o[:long] if o[:long]
    short_options << o[:short] if o[:short]
  end

  long = long_options.map! {|o| "--#{o}"}.join(' ')
  short = short_options.map! {|o| "-#{o}"}.join(' ')
  words = ''
  logic = ''
  words, logic = get_words(type) if type && type.is_a?(String)

  func = <<~ENDFUNC
  _doing_#{command}() {
    #{words}
    if [[ "$token" == --* ]]; then
      COMPREPLY=( $( compgen -W '#{long}' -- $token ) )
    elif [[ "$token" == -* ]]; then
      COMPREPLY=( $( compgen -W '#{short} #{long}' -- $token ) )
    #{logic}
    fi
  }
  ENDFUNC

  func
end

#generate_completionsObject



134
135
136
137
138
139
140
141
142
# File 'lib/doing/completion/bash_completion.rb', line 134

def generate_completions
  @bar.start
  out = []
  out << main_function
  out << 'complete -F _doing doing'
  @bar.advance(status: '')
  @bar.finish
  out.join("\n")
end

#get_words(type) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/doing/completion/bash_completion.rb', line 95

def get_words(type)
  func = <<~EOFUNC
    OLD_IFS="$IFS"
    local token=${COMP_WORDS[$COMP_CWORD]}
    IFS=$'\t'
    local words=$(doing #{type})
    IFS="$OLD_IFS"
  EOFUNC

  logic = <<~EOLOGIC
    else
      local nocasematchWasOff=0
      shopt nocasematch >/dev/null || nocasematchWasOff=1
      (( nocasematchWasOff )) && shopt -s nocasematch
      local w matches=()
      OLD_IFS="$IFS"
      IFS=$'\t'‰
      for w in $words; do
        if [[ "$w" == "$token"* ]]; then
          matches+=("${w// /\ }")
        fi
      done
      IFS="$OLD_IFS"
      (( nocasematchWasOff )) && shopt -u nocasematch
      COMPREPLY=("${matches[@]}")
  EOLOGIC

  [func, logic]
end

#main_functionObject



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/doing/completion/bash_completion.rb', line 9

def main_function
  first = true
  out = []
  logic = []

  @commands.each_with_index do |cmd, i|
    @bar.advance(status: cmd[:commands].first)

    data = Completion.get_help_sections(cmd[:commands].first)

    arg = data[:synopsis].join(' ').strip.split(/ /).last
    case arg
    when /(path|file)/i
      type = :file
    when /sect/i
      type = 'sections'
    when /view/i
      type = 'views'
    else
      type = nil
    end

    if data[:command_options]
      options = Completion.parse_options(data[:command_options])
      out << command_function(cmd[:commands].first, options, type)

      if first
        op = 'if'
        first = false
      else
        op = 'elif'
      end
      logic << %(#{op} [[ $last =~ (#{cmd[:commands].join('|')}) ]]; then _doing_#{cmd[:commands].first})
    end
  end

  out << <<~EOFUNC
    _doing()
    {
      local last="${@: -1}"
      local token=${COMP_WORDS[$COMP_CWORD]}

      #{logic.join("\n    ")}
      else
        OLD_IFS="$IFS"
        IFS=$'\n'
        COMPREPLY=( $(compgen -W "$(doing help -c)" -- $token) )
        IFS="$OLD_IFS"
      fi
    }
  EOFUNC
  out.join("\n")
end