class DocoptCompgen::Generator

Public Class Methods

new(command, node, command_name: nil, namespace: nil) click to toggle source
# File lib/docopt_compgen/generator.rb, line 3
def initialize(command, node, command_name: nil, namespace: nil)
    @command = command ? File.basename(command) : command_name
    @node = node
    @command_name = command_name || Util.slugify(@command)
    @namespace = '_' + namespace
end

Public Instance Methods

get_op(node) click to toggle source
# File lib/docopt_compgen/generator.rb, line 14
def get_op(node)
    if node.subcommands.length > 0
        'eq'
    else
        'ge'
    end
end
include_files?(node) click to toggle source
# File lib/docopt_compgen/generator.rb, line 30
def include_files?(node)
    return path_arguments?(node.arguments) || path_options?(node.options)
end
indent(str, level) click to toggle source
# File lib/docopt_compgen/generator.rb, line 10
def indent(str, level)
    "\n" + str.strip.lines.map { |s| (' ' * level) + s }.join
end
make(command_name, node, level) click to toggle source
# File lib/docopt_compgen/generator.rb, line 46
def make(command_name, node, level)
    subcommand_switch = make_subcommand_switch(
        command_name,
        level,
        node.subcommands,
    )

    op = get_op(node)
    include_files, words = make_compreply(node)

    functions = [
        make_function(
            command_name,
            op,
            level,
            words,
            include_files,
            subcommand_switch,
        ),
    ]

    node.subcommands.each do |subcommand_name, subcommand_node|
        functions << make(
            '%s_%s' % [command_name, subcommand_name],
            subcommand_node,
            level + 1,
        )
    end

    return functions.join("\n")
end
make_compreply(node) click to toggle source
# File lib/docopt_compgen/generator.rb, line 34
def make_compreply(node)
    words = []

    if node.options.length > 0
        words << node.options
    end

    words << node.subcommands.keys

    return [include_files?(node), words.flatten.join(' ')]
end
make_function(command_name, op, level, words, include_files, subcommand_switch) click to toggle source
# File lib/docopt_compgen/generator.rb, line 78
        def make_function(command_name, op, level, words, include_files, subcommand_switch) # rubocop:disable Metrics/ParameterLists
            files = ''
            if include_files
                files = indent(<<~EOF, 8)
                    local IFS=$'\\n' # Handle filenames with spaces.
                    COMPREPLY+=($(compgen -f -- "$cur"))
                EOF
            end

            return <<~EOF
                function #{@namespace}_#{command_name} {
                    local cur
                    cur="${COMP_WORDS[COMP_CWORD]}"

                    if [ "$COMP_CWORD" -#{op} #{level} ]; then
                        COMPREPLY=($(compgen -W '#{words}' -- "$cur"))#{files}#{subcommand_switch}
                    fi
                }
            EOF
        end
make_subcommand_switch(command_name, level, subcommands) click to toggle source
# File lib/docopt_compgen/generator.rb, line 99
        def make_subcommand_switch(command_name, level, subcommands)
            if subcommands.length == 0
                return ''
            end

            cases = subcommands.map do |subcommand_name, _node|
                "#{subcommand_name}) #{@namespace}_#{command_name}_#{subcommand_name} ;;"
            end.join("\n        ")

            return indent(<<~EOF, 4)
                else
                    case ${COMP_WORDS[#{level}]} in
                        #{cases}
                    esac
            EOF
        end
path_arguments?(arguments) click to toggle source
# File lib/docopt_compgen/generator.rb, line 22
def path_arguments?(arguments)
    arguments.any? { |a| %w[<file> <dir> <path>].include?(a) }
end
path_options?(options) click to toggle source
# File lib/docopt_compgen/generator.rb, line 26
def path_options?(options)
    options.any? { |a| %w[--file --dir --path].include?(a) }
end
to_s() click to toggle source
# File lib/docopt_compgen/generator.rb, line 116
        def to_s
            content = make(@command_name, @node, 1)

            return <<~EOF
                #!/bin/bash
                # shellcheck disable=SC2207

                #{content}
                complete -o bashdefault -o default -o filenames -F #{@namespace}_#{@command_name} #{@command}
            EOF
        end