Class: WifiWand::CommandLineInterface
- Inherits:
-
Object
- Object
- WifiWand::CommandLineInterface
- Defined in:
- lib/wifi-wand/command_line_interface.rb
Defined Under Namespace
Classes: BadCommandError, Command, OpenResource, OpenResources
Constant Summary collapse
- PROJECT_URL =
'https://github.com/keithrbennett/wifiwand'
- OPEN_RESOURCES =
OpenResources.new([ OpenResource.new('ipl', 'https://www.iplocation.net/', 'IP Location'), OpenResource.new('ipw', 'https://www.whatismyip.com', 'What is My IP'), OpenResource.new('spe', 'http://speedtest.net/', 'Speed Test'), OpenResource.new('this', 'https://github.com/keithrbennett/wifiwand', 'wifi-wand home page'), ])
- HELP_TEXT =
Help text to be used when requested by ‘h’ command, in case of unrecognized or nonexistent command, etc.
" Command Line Switches: [wifi-wand version #{WifiWand::VERSION} at https://github.com/keithrbennett/wifiwand] -o {i,j,k,p,y} - outputs data in inspect, JSON, pretty JSON, puts, or YAML format when not in shell mode -p wifi_port_name - override automatic detection of port name with this name -s - run in shell mode -v - verbose mode (prints OS commands and their outputs) Commands: a[vail_nets] - array of names of the available networks ci - connected to Internet (not just wifi on)? co[nnect] network-name - turns wifi on, connects to network-name cy[cle] - turns wifi off, then on, preserving network selection d[isconnect] - disconnects from current network, does not turn off wifi f[orget] name1 [..name_n] - removes network-name(s) from the preferred networks list in interactive mode, can be a single array of names, e.g. returned by `pref_nets` h[elp] - prints this help i[nfo] - a hash of wifi-related information l[s_avail_nets] - details about available networks, in descending order of signal strength na[meservers] - nameservers: 'show' or no arg to show, 'clear' to clear, or IP addresses to set, e.g. '9.9.9.9 8.8.8.8' ne[twork_name] - name (SSID) of currently connected network on - turns wifi on of[f] - turns wifi off pa[ssword] network-name - password for preferred network-name pr[ef_nets] - preferred (saved) networks q[uit] - exits this program (interactive shell mode only) (see also 'x') ro[pen] - open resource (#{OPEN_RESOURCES.help_string}) t[ill] - returns when the desired Internet connection state is true. Options: 1) 'on'/:on, 'off'/:off, 'conn'/:conn, or 'disc'/:disc 2) wait interval between tests, in seconds (optional, defaults to 0.5 seconds) w[ifi_on] - is the wifi on? x[it] - exits this program (interactive shell mode only) (see also 'q') When in interactive shell mode: * remember to quote string literals. * for pry commands, use prefix `%`. "
Instance Attribute Summary collapse
-
#interactive_mode ⇒ Object
readonly
Returns the value of attribute interactive_mode.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#open_resources ⇒ Object
readonly
Returns the value of attribute open_resources.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
-
#attempt_command_action(command, *args, &error_handler_block) ⇒ Object
Look up the command name and, if found, run it.
-
#awesome_print_available? ⇒ Boolean
We’d like to use awesome_print if it is available, but not require it.
- #call ⇒ Object
- #cmd_a ⇒ Object
- #cmd_ci ⇒ Object
- #cmd_co(network, password = nil) ⇒ Object
- #cmd_cy ⇒ Object
- #cmd_d ⇒ Object
- #cmd_f(*options) ⇒ Object
- #cmd_h ⇒ Object
- #cmd_i ⇒ Object
- #cmd_l ⇒ Object
-
#cmd_na(*args) ⇒ Object
Performs nameserver functionality.
- #cmd_ne ⇒ Object
- #cmd_of ⇒ Object
- #cmd_on ⇒ Object
- #cmd_pa(network) ⇒ Object
- #cmd_pr ⇒ Object
- #cmd_q ⇒ Object
-
#cmd_ro(*resource_codes) ⇒ Object
Use Mac OS ‘open’ command line utility.
- #cmd_t(*options) ⇒ Object
- #cmd_w ⇒ Object
- #cmd_x ⇒ Object
- #commands ⇒ Object
- #fancy_puts(object) ⇒ Object (also: #fp)
- #fancy_string(object) ⇒ Object
- #find_command_action(command_string) ⇒ Object
-
#initialize(options) ⇒ CommandLineInterface
constructor
A new instance of CommandLineInterface.
-
#method_missing(method_name, *method_args) ⇒ Object
For use by the shell when the user types the DSL commands.
-
#post_process(object) ⇒ Object
If a post-processor has been configured (e.g. YAML or JSON), use it.
- #post_processor ⇒ Object
- #print_help ⇒ Object
- #process_command_line ⇒ Object
- #quit ⇒ Object
-
#run_pry ⇒ Object
Pry will output the content of the method from which it was called.
-
#run_shell ⇒ Object
Runs a pry session in the context of this object.
-
#validate_command_line ⇒ Object
Asserts that a command has been passed on the command line.
- #verbose_mode ⇒ Object
Constructor Details
#initialize(options) ⇒ CommandLineInterface
Returns a new instance of CommandLineInterface.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/wifi-wand/command_line_interface.rb', line 95 def initialize() @options = current_os = OperatingSystems.new.current_os raise Error.new("Could not determine operating system") if current_os.nil? = OpenStruct.new({ verbose: .verbose, wifi_port: .wifi_port }) unless awesome_print_available? HELP_TEXT << "For nicer output, `gem install awesome_print`.\n\n" end @model = current_os.create_model() @interactive_mode = !!(.interactive_mode) run_shell if @interactive_mode end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *method_args) ⇒ Object
For use by the shell when the user types the DSL commands
216 217 218 219 220 221 222 |
# File 'lib/wifi-wand/command_line_interface.rb', line 216 def method_missing(method_name, *method_args) attempt_command_action(method_name.to_s, *method_args) do puts(%Q{"#{method_name}" is not a valid command or option. } \ << 'If you intend for this to be a string literal, ' \ << 'use quotes or %q{}/%Q{}.') end end |
Instance Attribute Details
#interactive_mode ⇒ Object (readonly)
Returns the value of attribute interactive_mode.
10 11 12 |
# File 'lib/wifi-wand/command_line_interface.rb', line 10 def interactive_mode @interactive_mode end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
10 11 12 |
# File 'lib/wifi-wand/command_line_interface.rb', line 10 def model @model end |
#open_resources ⇒ Object (readonly)
Returns the value of attribute open_resources.
10 11 12 |
# File 'lib/wifi-wand/command_line_interface.rb', line 10 def open_resources @open_resources end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
10 11 12 |
# File 'lib/wifi-wand/command_line_interface.rb', line 10 def @options end |
Instance Method Details
#attempt_command_action(command, *args, &error_handler_block) ⇒ Object
Look up the command name and, if found, run it. If not, execute the passed block.
203 204 205 206 207 208 209 210 211 212 |
# File 'lib/wifi-wand/command_line_interface.rb', line 203 def attempt_command_action(command, *args, &error_handler_block) action = find_command_action(command) if action action.(*args) else error_handler_block.call nil end end |
#awesome_print_available? ⇒ Boolean
We’d like to use awesome_print if it is available, but not require it. So, we try to require it, but if that fails, we fall back to using pp (pretty print), which is included in Ruby distributions without the need to install a gem.
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/wifi-wand/command_line_interface.rb', line 128 def awesome_print_available? if @awesome_print_available.nil? # first time here begin require 'awesome_print' @awesome_print_available = true rescue LoadError require 'pp' @awesome_print_available = false end end @awesome_print_available end |
#call ⇒ Object
514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/wifi-wand/command_line_interface.rb', line 514 def call validate_command_line begin # By this time, the Main class has removed the command line options, and all that is left # in ARGV is the commands and their options. process_command_line rescue BadCommandError => error separator_line = "! #{'-' * 75} !\n" puts '' << separator_line << error.to_s << "\n" << separator_line exit(-1) end end |
#cmd_a ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/wifi-wand/command_line_interface.rb', line 250 def cmd_a info = model.available_network_names if interactive_mode info else if post_processor puts post_processor.(info) else puts model.wifi_on? \ ? "Available networks are:\n\n#{fancy_string(info)}" \ : "Wifi is off, cannot see available networks." end end end |
#cmd_ci ⇒ Object
266 267 268 269 270 271 272 273 |
# File 'lib/wifi-wand/command_line_interface.rb', line 266 def cmd_ci connected = model.connected_to_internet? if interactive_mode connected else puts (post_processor ? post_processor.(connected) : "Connected to Internet: #{connected}") end end |
#cmd_co(network, password = nil) ⇒ Object
276 277 278 |
# File 'lib/wifi-wand/command_line_interface.rb', line 276 def cmd_co(network, password = nil) model.connect(network, password) end |
#cmd_cy ⇒ Object
281 282 283 |
# File 'lib/wifi-wand/command_line_interface.rb', line 281 def cmd_cy model.cycle_network end |
#cmd_d ⇒ Object
286 287 288 |
# File 'lib/wifi-wand/command_line_interface.rb', line 286 def cmd_d model.disconnect end |
#cmd_f(*options) ⇒ Object
434 435 436 437 438 439 440 441 |
# File 'lib/wifi-wand/command_line_interface.rb', line 434 def cmd_f(*) removed_networks = model.remove_preferred_networks(*) if interactive_mode removed_networks else puts (post_processor ? post_processor.(removed_networks) : "Removed networks: #{removed_networks.inspect}") end end |
#cmd_h ⇒ Object
291 292 293 |
# File 'lib/wifi-wand/command_line_interface.rb', line 291 def cmd_h print_help end |
#cmd_i ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/wifi-wand/command_line_interface.rb', line 296 def cmd_i info = model.wifi_info if interactive_mode info else if post_processor puts post_processor.(info) else puts fancy_string(info) end end end |
#cmd_l ⇒ Object
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/wifi-wand/command_line_interface.rb', line 310 def cmd_l info = model.available_network_info if interactive_mode info else output = '' unless model.wifi_on? output << "Wifi is off, cannot see available networks." else if post_processor output = post_processor.(info) else output << "\nAccess points listed in descending order of signal strength (RSSI):\n\n" output << fancy_string(info) end end puts output end end |
#cmd_na(*args) ⇒ Object
Performs nameserver functionality.
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/wifi-wand/command_line_interface.rb', line 334 def cmd_na(*args) subcommand = if args.empty? || args.first.to_sym == :get :get elsif args.first.to_sym == :clear :clear else :put end case(subcommand) when :get current_nameservers = model.nameservers_using_networksetup if interactive_mode current_nameservers else if post_processor puts post_processor.(current_nameservers) else current_nameservers_as_string = current_nameservers.empty? ? "[None]" : current_nameservers.join(', ') puts "Nameservers: #{current_nameservers_as_string}" end end when :clear model.set_nameservers(:clear) when :put new_nameservers = args model.set_nameservers(new_nameservers) end end |
#cmd_ne ⇒ Object
365 366 367 368 369 370 371 372 373 |
# File 'lib/wifi-wand/command_line_interface.rb', line 365 def cmd_ne name = model.connected_network_name if interactive_mode name else display_name = name ? name : '[none]' puts (post_processor ? post_processor.(name) : %Q{Network (SSID) name: "#{display_name}"}) end end |
#cmd_of ⇒ Object
376 377 378 |
# File 'lib/wifi-wand/command_line_interface.rb', line 376 def cmd_of model.wifi_off end |
#cmd_on ⇒ Object
381 382 383 |
# File 'lib/wifi-wand/command_line_interface.rb', line 381 def cmd_on model.wifi_on end |
#cmd_pa(network) ⇒ Object
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/wifi-wand/command_line_interface.rb', line 402 def cmd_pa(network) password = model.preferred_network_password(network) if interactive_mode password else if post_processor puts post_processor.(password) else output = %Q{Preferred network "#{model.connected_network_name}" } output << (password ? %Q{stored password is "#{password}".} : "has no stored password.") puts output end end end |
#cmd_pr ⇒ Object
419 420 421 422 423 424 425 426 |
# File 'lib/wifi-wand/command_line_interface.rb', line 419 def cmd_pr networks = model.preferred_networks if interactive_mode networks else puts (post_processor ? post_processor.(networks) : fancy_string(networks)) end end |
#cmd_q ⇒ Object
429 430 431 |
# File 'lib/wifi-wand/command_line_interface.rb', line 429 def cmd_q quit end |
#cmd_ro(*resource_codes) ⇒ Object
Use Mac OS ‘open’ command line utility
387 388 389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/wifi-wand/command_line_interface.rb', line 387 def cmd_ro(*resource_codes) resource_codes.each do |code| resource = OPEN_RESOURCES.find_by_code(code) if resource if code == 'spe' && Dir.exist?('/Applications/Speedtest.app/') model.open_application('Speedtest') else model.open_resource(resource.resource) end end end nil end |
#cmd_t(*options) ⇒ Object
444 445 446 447 448 |
# File 'lib/wifi-wand/command_line_interface.rb', line 444 def cmd_t(*) target_status = [0].to_sym wait_interval_in_secs = ([1] ? Float([1]) : nil) model.till(target_status, wait_interval_in_secs) end |
#cmd_w ⇒ Object
451 452 453 454 455 456 457 458 |
# File 'lib/wifi-wand/command_line_interface.rb', line 451 def cmd_w on = model.wifi_on? if interactive_mode on else puts (post_processor ? post_processor.(on) : "Wifi on: #{on}") end end |
#cmd_x ⇒ Object
461 462 463 |
# File 'lib/wifi-wand/command_line_interface.rb', line 461 def cmd_x quit end |
#commands ⇒ Object
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'lib/wifi-wand/command_line_interface.rb', line 466 def commands @commands_ ||= [ Command.new('a', 'avail_nets', -> (*) { cmd_a }), Command.new('ci', 'ci', -> (*) { cmd_ci }), Command.new('co', 'connect', -> (*) { cmd_co(*) }), Command.new('cy', 'cycle', -> (*) { cmd_cy }), Command.new('d', 'disconnect', -> (*) { cmd_d }), Command.new('f', 'forget', -> (*) { cmd_f(*) }), Command.new('h', 'help', -> (*) { cmd_h }), Command.new('i', 'info', -> (*) { cmd_i }), Command.new('l', 'ls_avail_nets', -> (*) { cmd_l }), Command.new('na', 'nameservers', -> (*) { cmd_na(*) }), Command.new('ne', 'network_name', -> (*) { cmd_ne }), Command.new('of', 'off', -> (*) { cmd_of }), Command.new('on', 'on', -> (*) { cmd_on }), Command.new('ro', 'ropen', -> (*) { cmd_ro(*) }), Command.new('pa', 'password', -> (*) { cmd_pa(*) }), Command.new('pr', 'pref_nets', -> (*) { cmd_pr }), Command.new('q', 'quit', -> (*) { cmd_q }), Command.new('t', 'till', -> (*) { cmd_t(*) }), Command.new('u', 'url', -> (*) { PROJECT_URL }), Command.new('w', 'wifi_on', -> (*) { cmd_w }), Command.new('x', 'xit', -> (*) { cmd_x }) ] end |
#fancy_puts(object) ⇒ Object Also known as: fp
148 149 150 |
# File 'lib/wifi-wand/command_line_interface.rb', line 148 def fancy_puts(object) puts fancy_string(object) end |
#fancy_string(object) ⇒ Object
143 144 145 |
# File 'lib/wifi-wand/command_line_interface.rb', line 143 def fancy_string(object) awesome_print_available? ? object.ai : object.pretty_inspect end |
#find_command_action(command_string) ⇒ Object
493 494 495 496 497 498 499 500 |
# File 'lib/wifi-wand/command_line_interface.rb', line 493 def find_command_action(command_string) result = commands.detect do |cmd| cmd.max_string.start_with?(command_string) \ && \ command_string.length >= cmd.min_string.length # e.g. 'c' by itself should not work end result ? result.action : nil end |
#post_process(object) ⇒ Object
If a post-processor has been configured (e.g. YAML or JSON), use it.
504 505 506 |
# File 'lib/wifi-wand/command_line_interface.rb', line 504 def post_process(object) post_processor ? post_processor.(object) : object end |
#post_processor ⇒ Object
509 510 511 |
# File 'lib/wifi-wand/command_line_interface.rb', line 509 def post_processor .post_processor end |
#print_help ⇒ Object
119 120 121 |
# File 'lib/wifi-wand/command_line_interface.rb', line 119 def print_help puts HELP_TEXT end |
#process_command_line ⇒ Object
Processes the command (ARGV) and any relevant options (ARGV).
CAUTION! In interactive mode, any strings entered (e.g. a network name) MUST be in a form that the Ruby interpreter will recognize as a string, i.e. single or double quotes, %q, %Q, etc. Otherwise it will assume it’s a method name and pass it to method_missing!
231 232 233 234 235 236 237 |
# File 'lib/wifi-wand/command_line_interface.rb', line 231 def process_command_line attempt_command_action(ARGV[0], *ARGV[1..-1]) do print_help raise BadCommandError.new( %Q{! Unrecognized command. Command was "#{ARGV.first.inspect}" and options were #{ARGV[1..-1].inspect}.}) end end |
#quit ⇒ Object
241 242 243 244 245 246 247 |
# File 'lib/wifi-wand/command_line_interface.rb', line 241 def quit if interactive_mode exit(0) else puts "This command can only be run in shell mode." end end |
#run_pry ⇒ Object
Pry will output the content of the method from which it was called. This small method exists solely to reduce the amount of pry’s output that is not needed here.
167 168 169 170 171 172 173 |
# File 'lib/wifi-wand/command_line_interface.rb', line 167 def run_pry binding.pry # the seemingly useless line below is needed to avoid pry's exiting # (see https://github.com/deivid-rodriguez/pry-byebug/issues/45) _a = nil end |
#run_shell ⇒ Object
Runs a pry session in the context of this object. Commands and options specified on the command line can also be specified in the shell.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/wifi-wand/command_line_interface.rb', line 178 def run_shell begin require 'pry' rescue LoadError = "The 'pry' gem and/or one of its prerequisites, required for running the shell, was not found." + " Please `gem install pry` or, if necessary, `sudo gem install pry`." raise Error.new() end print_help # Enable the line below if you have any problems with pry configuration being loaded # that is messing up this runtime use of pry: # Pry.config.should_load_rc = false # Strangely, this is the only thing I have found that successfully suppresses the # code context output, which is not useful here. Anyway, this will differentiate # a pry command from a DSL command, which _is_ useful here. Pry.config.command_prefix = '%' run_pry end |
#validate_command_line ⇒ Object
Asserts that a command has been passed on the command line.
155 156 157 158 159 160 161 |
# File 'lib/wifi-wand/command_line_interface.rb', line 155 def validate_command_line if ARGV.empty? puts "Syntax is: #{$0} [options] command [command_options]" print_help exit(-1) end end |
#verbose_mode ⇒ Object
114 115 116 |
# File 'lib/wifi-wand/command_line_interface.rb', line 114 def verbose_mode .verbose end |