From a82e71cea790882312e87dbe85b176eb14771435 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 8 Aug 2019 20:23:48 -0500 Subject: [PATCH] Added support for Console auto-complete --- i-mic-fps.rb | 1 + lib/ui/command.rb | 38 ++++++++++++++++++++++++++------- lib/ui/commands/fps_command.rb | 5 +++++ lib/ui/commands/help_command.rb | 2 ++ lib/ui/console.rb | 33 ++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 1a73395..0bd854d 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -1,5 +1,6 @@ require "fiddle" require "yaml" +require "abbrev" require "opengl" require "glu" diff --git a/lib/ui/command.rb b/lib/ui/command.rb index 1fd6afd..58c4c34 100644 --- a/lib/ui/command.rb +++ b/lib/ui/command.rb @@ -26,7 +26,10 @@ class IMICFPS @list ||= [] @commands = [] @list.each do |subclass| - @commands << subclass.new + cmd = subclass.new + raise "Command '#{cmd.command}' from '#{cmd.class}' already exists!" if @commands.detect { |c| c.command == cmd.command } + + @commands << cmd end end @@ -58,6 +61,7 @@ class IMICFPS def setup; end def subcommand(command, type) + raise "Subcommand '#{command}' for '#{self.command}' already exists!" if @subcommands.detect { |subcmd| subcmd.command == command.to_sym } @subcommands << SubCommand.new(self, command, type) end @@ -81,6 +85,9 @@ class IMICFPS raise NotImplementedError end + def autocomplete(console) + end + def handle_subcommand(arguments, console) if arguments.size == 0 console.stdin(usage) @@ -113,6 +120,11 @@ class IMICFPS end def handle(arguments, console) + if arguments.size > 1 + console.stdin("to many arguments for #{Style.highlight("#{command}")}, got #{Style.error(arguments.size)} expected #{Style.notice(1)}.") + return + end + case @type when :boolean case arguments.last @@ -125,6 +137,8 @@ class IMICFPS when "off" var = @parent.set(command.to_sym, false) console.stdin("#{command} => #{Style.highlight(var)}") + else + console.stdin("Invalid argument for #{Style.highlight("#{command}")}, got #{Style.error(arguments.last)} expected #{Style.notice("on")}, or #{Style.notice("off")}.") end when :string case arguments.last @@ -141,8 +155,12 @@ class IMICFPS var = @parent.get(command.to_sym) ? @parent.get(command.to_sym) : "nil" console.stdin("#{command}: #{Style.highlight(var)}") else - var = @parent.set(command.to_sym, arguments.last.to_i) - console.stdin("#{command} => #{Style.highlight(var)}") + begin + var = @parent.set(command.to_sym, Integer(arguments.last)) + console.stdin("#{command} => #{Style.highlight(var)}") + rescue ArgumentError + console.stdin("Error: #{Style.error("Expected an integer, got '#{arguments.last}'")}") + end end when :decimal case arguments.last @@ -150,8 +168,12 @@ class IMICFPS var = @parent.get(command.to_sym) ? @parent.get(command.to_sym) : "nil" console.stdin("#{command}: #{Style.highlight(var)}") else - var = @parent.set(command.to_sym, arguments.last.to_f) - console.stdin("#{command} => #{Style.highlight(var)}") + begin + var = @parent.set(command.to_sym, Float(arguments.last)) + console.stdin("#{command} => #{Style.highlight(var)}") + rescue ArgumentError + console.stdin("Error: #{Style.error("Expected a decimal or integer, got '#{arguments.last}'")}") + end end else raise RuntimeError @@ -163,11 +185,11 @@ class IMICFPS when :boolean "#{Style.highlight(command)} #{Style.notice("[on|off]")}" when :string - "#{Style.highlight(command)} #{Style.notice("[on|off]")}" + "#{Style.highlight(command)} #{Style.notice("[string]")}" when :integer - "#{Style.highlight(command)} #{Style.notice("[on|off]")}" + "#{Style.highlight(command)} #{Style.notice("[0]")}" when :decimal - "#{Style.highlight(command)} #{Style.notice("[on|off]")}" + "#{Style.highlight(command)} #{Style.notice("[0.0]")}" end end end diff --git a/lib/ui/commands/fps_command.rb b/lib/ui/commands/fps_command.rb index 18f38eb..70d53a1 100644 --- a/lib/ui/commands/fps_command.rb +++ b/lib/ui/commands/fps_command.rb @@ -10,6 +10,11 @@ class IMICFPS end def handle(arguments, console) + if arguments.size > 1 + console.stdin("to many arguments for #{Style.highlight("#{command}")}, got #{Style.error(arguments.size)} expected #{Style.notice(1)}.") + return + end + case arguments.last when "", nil console.stdin("#{Style.highlight("fps")}: #{$debug.get(:fps)}") diff --git a/lib/ui/commands/help_command.rb b/lib/ui/commands/help_command.rb index 0650bc0..4b68c7e 100644 --- a/lib/ui/commands/help_command.rb +++ b/lib/ui/commands/help_command.rb @@ -17,6 +17,8 @@ class IMICFPS if command if cmd = Command.find(command) cmd.usage + else + "#{Style.error(command)} is not a command" end else "Available commands:\n#{Command.list_commands.map { |cmd| "#{Style.highlight(cmd.command)}" }.join(', ')}" diff --git a/lib/ui/console.rb b/lib/ui/console.rb index a018e0a..050a4a3 100644 --- a/lib/ui/console.rb +++ b/lib/ui/console.rb @@ -86,6 +86,24 @@ class IMICFPS @text_input.text = @command_history[@command_history_index] end + when Gosu::KbTab + split = @text_input.text.split(" ") + + if !@text_input.text.end_with?(" ") && split.size == 1 + list = command_search(@text_input.text) + + if list.size == 1 + @text_input.text = "#{list.first} " + else + @history.text += "\n#{list.map { |cmd| Commands::Style.highlight(cmd)}.join(", ")}" + update_history + end + else + if split.size > 0 && cmd = Commands::Command.find(split.first) + cmd.autocomplete(self) + end + end + when Gosu::KbBacktick # Removed backtick character from input if @text_input.text.size > 1 @@ -112,6 +130,21 @@ class IMICFPS IMICFPS::Commands::Command.use(command, arguments, self) end + def command_search(text) + return [] unless text.length > 0 + + @command_search ||= Abbrev.abbrev(Commands::Command.list_commands.map { |cmd| cmd.command.to_s}) + + list = [] + @command_search.each do |abbrev, value| + next unless abbrev && abbrev.start_with?(text) + + list << value + end + + return list.uniq + end + def stdin(string) @history.text += "\n#{string}" update_history