Ah, es ist ärgerlich, den Browser zu starten. Ich war wieder einmal begeistert von der Erstellung von Befehlszeilen-Tools. Etwas wie das.
Dieses Mal werde ich einen Befehl definieren, damit er mit TAB
gespeichert werden kann. Ich konnte keine gute Probe finden, also habe ich es während der Untersuchung gemacht [^ 2]
[^ 1]: REPL (Read-Eval-Print Loop) ist eine Eingabe- / Auswertungs- / Ausgabeschleife. Ein Interpreter, mit dem der Benutzer und der Interpreter Codeteile interaktiv ausführen können. Ich persönlich nenne es einen Cisco-Typ.
[^ 2]: Vor langer Zeit habe ich einen Artikel wie Autocomplete with my own command line tool geschrieben, aber es ist die "Ruby" -Version. Als kleiner Unterschied zum letzten Mal ist es diesmal wie "REPL" [^ 1]
Diesmal bis ich so etwas mache
Die Vorlage ist im Grunde so mit "Readline". ① wird von TAB aufgerufen und ② dreht sich um
Einstufiger Befehl
require "readline"
#Befehle für Abschlusskandidaten
pet_store = [ "pet", "store", "user"]
#① Wird aufgerufen, um die Tabulatortaste zu drücken und die Auswahl abzuschließen
Readline.completion_proc = proc do |input|
pet_store.select { |name| name.start_with?(input) }
end
#② Drücken Sie zum Drehen die Eingabetaste
while input = Readline.readline("$ ", false)
if input
break if input == "q"
p Readline.line_buffer.split if !input.empty?
end
end
Bei einer Schicht ist dies einfach, da die Befehlskandidaten festgelegt sind
Bei einem mehrschichtigen Befehl sollte der Befehl des Abschlusskandidaten im vorherigen Beispiel entsprechend dem aktuellen Kontext geändert werden (zuvor ausgewählter Befehl).
Der Punkt ist, dass der "nächste Kandidat" dynamisch gemäß dem "aktuell ausgewählten Befehl" ersetzt werden sollte. Definieren wir also so etwas wie einen Befehlsbaum. Da es sich um eine Baumstruktur handelt, versuchen Sie es mit YAML
.
petstore.rb
require "readline"
require "yaml"
command_tree = <<-YAML
pet:
buy:
dog:
cat:
sell:
bird:
fox:
list:
all:
filter_by:
store:
find:
by_name:
by_tag:
by_address:
list:
user:
login:
loout:
sign_up:
YAML
command_tree = YAML.load(command_tree)
#pp command_tree
#Wechseln Sie dynamisch "nächster Kandidat" gemäß "aktuell ausgewähltem Befehl" (gehen Sie den Baum hinunter)
def current_option(command_tree, line_buffer)
current_option = command_tree.keys
line_buffer.split.each do |command|
command_tree = command_tree[command]
if command_tree.nil?
current_option
else
current_option = command_tree.keys
end
end
current_option
end
comp = proc do |input|
current_option(command_tree, Readline.line_buffer).select { |name| name.to_s.start_with?(input) }
end
Readline.completion_proc = comp
while input = Readline.readline("$ ", true)
break if input == "q"
p Readline.line_buffer.split if !input.empty?
end
Was mache ich:
Es ist wie
Es mag ein kleiner Fall sein, aber mit der obigen Methode wird der richtige Kandidat angezeigt, wenn mehrere Kandidaten noch übereinstimmen, selbst wenn die Befehlskandidaten bis zu "pet" wie "pet" und "petGroup" abgeschlossen sind. nicht. Dies möchte einen Kandidaten für "pet" oder "petGroup" finden, wenn bis "pet" abgeschlossen ist, aber es entspricht dem Hash-Schlüssel "pet" und geht eine Ebene tiefer, also unter "pet" Dies liegt daran, dass die Hierarchie ein Kandidat wird. Um dies zu vermeiden, habe ich Folgendes versucht: 1.
def get_current_option(command_tree, line_buffer)
current_option = command_tree.keys
commands = line_buffer.split
commands.each_with_index do |command, i|
# 1. Don't go down to the lower level(and return current_option) in case current command matches multiple candidates such as "pet" and "petGroup"
return current_option if i == commands.size-1 and !line_buffer.end_with?("\s")
# 2. 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
Jetzt haben Sie das erwartete Verhalten und können bequem tippen.
Nun, da es funktioniert, gehen wir zum Befehl Parsen und Verarbeiten. Wenn es eine bessere Implementierungsmethode für die Ergänzung gibt, geben Sie mir bitte einen Rat!