Skip to content

Instantly share code, notes, and snippets.

@narutaro
Created September 6, 2020 02:26
Show Gist options
  • Save narutaro/137c39c483cdde4fdbaedf6f6c73452c to your computer and use it in GitHub Desktop.
Save narutaro/137c39c483cdde4fdbaedf6f6c73452c to your computer and use it in GitHub Desktop.

Revisions

  1. narutaro created this gist Sep 6, 2020.
    50 changes: 50 additions & 0 deletions tab-completion-with-multi-command.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    require "readline"
    require "yaml"

    command_tree = {"pet"=>
    {"buy"=>{"dog"=>nil, "cat"=>nil},
    "sell"=>{"bird"=>nil, "fox"=>nil},
    "sellGroup"=>{"pig"=>nil, "kingfisher"=>nil},
    "list"=>{"all"=>nil, "filter_by"=>nil}},
    "store"=>
    {"find"=>{"by_name"=>nil, "by_tag"=>nil, "by_address"=>nil}, "list"=>nil},
    "user"=>{"login"=>nil, "logout"=>nil, "sign_up"=>nil},
    "petGroup"=>{"login"=>nil, "loout"=>nil, "sign_up"=>nil},
    }

    pp command_tree

    def get_current_option(command_tree, line_buffer)
    current_option = command_tree.keys
    commands = line_buffer.split

    commands.each_with_index do |command, i|

    # Don't go down to the lower level(and return current_option) in case current command matches two candidates such as "pet" and "petGroup"
    return current_option if i == commands.size-1 and !line_buffer.end_with?("\s")

    # Go down
    if command_tree.has_key?(command)
    if command_tree[command].nil? # invalid command or key at leaf
    current_option = []
    else
    command_tree = command_tree[command]
    current_option = command_tree.keys
    end
    end
    end
    current_option
    end

    # Evaluate the proc when pressing <tab>
    comp = proc do |input|
    get_current_option(command_tree, Readline.line_buffer).select { |name| name.to_s.start_with?(input) }
    end

    Readline.completion_proc = comp
    #Readline.completion_append_character = " "

    while input = Readline.readline("$ ", true)
    break if input == "q"
    p Readline.line_buffer.split if !input.empty?
    end