sshyguy 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 225a14fa2b004e45d52ec9a6df5161aa253e4cbb
4
- data.tar.gz: 718902b6750ca29d5baa3cd6a7dff6aa33f409c4
3
+ metadata.gz: 74b1b6c81566ac6efd9220f7f77662983249fa51
4
+ data.tar.gz: 24e64e5e2c08f3c994a91f35908b80513012517b
5
5
  SHA512:
6
- metadata.gz: 8647ebf42c79867364153e95b16515d3c63e59fbfe69e4aff54cbfd27058a344f30e16999e1493bf534fcc7f8be5e81376e3b31a13cf35e46cc5c88b5bc724f8
7
- data.tar.gz: 496c9c253d03759d27208f04974c743b5dc3478f4f3d2553e7e6207d825b7971654fc505ec50c20bb68cdbd3e6c5240001feabcbfb08d6c768ef527d301a7e20
6
+ metadata.gz: 42dee875e4f064323a63f0a7ad69db576705bceeb9d0fe22799015ac1fb22ac520297296f56dff12082b33ad57b4f5a0dabee497f76a4ce0472e375b3a1e6b7e
7
+ data.tar.gz: 54ba820da01574736f22d65b05605c403d0794f8771e2ff1909b0fbffce2af97ebfb945d0807e6dda2e0757778096ac4951670f4bbfc9e7b531376a5ebef053e
data/.gitignore CHANGED
@@ -6,3 +6,16 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ .bundle/
10
+ log/*.log
11
+ pkg/
12
+ test/dummy/db/*.sqlite3
13
+ test/dummy/db/*.sqlite3-journal
14
+ test/dummy/log/*.log
15
+ test/dummy/node_modules/
16
+ test/dummy/yarn-error.log
17
+ test/dummy/storage/
18
+ test/dummy/tmp/
19
+ *.gem
20
+ .ruby-version
21
+
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in sshyguy.gemspec
4
6
  gemspec
data/README.md CHANGED
@@ -23,9 +23,15 @@ Edit your config file add servers.
23
23
  "user": "deploy",
24
24
  "label": "Production",
25
25
  "shortcut": "production",
26
+ "command": "",
27
+ "options": ""
26
28
  }
27
29
  ```
28
30
 
31
+ ### Notes
32
+
33
+ If `command` is present (not blank/empty/nil), it will be used to spawn the SSH connection. Otherwise, it will be built with `ssh $user@$hostname -p $port $options`.
34
+
29
35
  ## Usage
30
36
 
31
37
  Feeling lazy?
data/Rakefile CHANGED
@@ -1,2 +1,4 @@
1
- require "bundler/gem_tasks"
2
- task :default => :spec
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "sshyguy"
4
+ require 'bundler/setup'
5
+ require 'sshyguy'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "sshyguy"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/bin/sshyguy CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'sshyguy'
4
5
 
5
6
  begin
6
7
  SshyGuy::CLI.run
7
8
  rescue Interrupt => e
8
- puts ""
9
- puts ""
10
- puts "Goodbye."
9
+ puts ''
10
+ puts ''
11
+ puts 'Goodbye.'
11
12
  end
@@ -1,14 +1,15 @@
1
1
  {
2
+ "version": 1,
2
3
  "config": {
3
4
  "debug": false,
4
- "include_shortcut": true,
5
5
  "cycle": true,
6
6
  "filter": true,
7
- "editor": "subl",
8
- "folders": true,
7
+ "editor": "vi",
9
8
  "ssh_defaults": {
10
9
  "user": "root",
11
- "port": 22
10
+ "port": 22,
11
+ "options": "",
12
+ "hostname": ""
12
13
  }
13
14
  },
14
15
  "servers": [
data/lib/sshyguy.rb CHANGED
@@ -1,7 +1,11 @@
1
- require "sshyguy/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'sshyguy/version'
2
4
  require 'tty-prompt'
3
5
  require 'optionparser'
4
6
  require 'json'
7
+ require 'sshyguy/params'
8
+ require 'sshyguy/servers'
5
9
  require 'sshyguy/config'
6
10
  require 'sshyguy/prompt'
7
11
  require 'sshyguy/core_ext'
@@ -11,23 +15,9 @@ require 'sshyguy/command'
11
15
  require 'sshyguy/cli'
12
16
 
13
17
  module SshyGuy
14
- def self.params
15
- @params ||= {}
16
- end
17
- def self.params=(val)
18
- @params = val
19
- end
20
- def self.reload_params!
21
- self.params = {}
22
- end
23
-
24
- def self.servers=(val)
25
- @servers = val
26
- end
27
-
28
- def self.servers
29
- @servers ||= []
30
- end
18
+ extend SshyGuy::Servers
19
+ extend SshyGuy::Params
20
+ class Error < StandardError; end
31
21
 
32
22
  def self.configuration
33
23
  @configuration ||= Config.new
@@ -36,31 +26,54 @@ module SshyGuy
36
26
  def self.config
37
27
  configuration
38
28
  end
39
- class Error < StandardError; end
40
29
 
41
30
  def self.log(str)
42
31
  if SshyGuy.config.debug?
43
32
  puts str
33
+ puts caller(0)
44
34
  end
45
35
  end
46
36
 
47
37
  def self.config_file
48
- File.expand_path("~/.sshyguy.json")
38
+ File.expand_path('~/.sshyguy.json')
49
39
  end
50
40
 
51
41
  def self.load_config!
52
- unless File.exist?(self.config_file)
53
- puts "No config file found at #{self.config_file}"
54
- puts "Install this with sshyguy --install"
42
+ SshyGuy.log("Checking if config_file exists at #{config_file}")
43
+ unless File.exist?(config_file)
44
+ SshyGuy.log('config_file not found')
45
+ puts "No config file found at #{config_file}"
46
+ puts 'Install this with sshyguy --install'
47
+ SshyGuy.log('Exiting program')
55
48
  exit
56
49
  end
57
50
  begin
58
- json = JSON.parse(File.read(self.config_file))
59
- json['config'].each do |k,v|
51
+ SshyGuy.log('Parsing config_file')
52
+ file = File.read(config_file)
53
+ SshyGuy.log('File read')
54
+ SshyGuy.log('File contents:')
55
+ SshyGuy.log(file)
56
+ SshyGuy.log('Parsing file')
57
+ json = JSON.parse(file)
58
+ if json['version'].to_i < SshyGuy::CONFIG_VERSION
59
+ puts 'Warning: Configuration out of date.'
60
+ end
61
+ SshyGuy.log('Parsed')
62
+ SshyGuy.log('Parsed contents')
63
+ SshyGuy.log(json)
64
+ SshyGuy.log('Loading config defaults')
65
+ json['config'].each do |k, v|
66
+ SshyGuy.log("Setting default '#{k}' to '#{v}'")
60
67
  configuration.send("#{k}=", v)
61
68
  end
62
- Server.build(json['servers'].reject { |server| !server['command'].present? && !server['hostname'].present? })
63
- rescue => e
69
+ json['servers'].each do |server|
70
+ if server['command'].present? || server['hostname'].present?
71
+ Server.new(server)
72
+ else
73
+ log("Skipping server #{server.inspect}")
74
+ end
75
+ end
76
+ rescue JSON::ParserError => e
64
77
  puts e
65
78
  puts "Unable to parse config file. Ensure it's valid JSON."
66
79
  exit
data/lib/sshyguy/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sshyguy/screen'
2
4
  require 'sshyguy/screens/help_screen'
3
5
  require 'sshyguy/screens/main_screen'
@@ -9,20 +11,19 @@ module SshyGuy
9
11
  def self.run
10
12
  options = {}
11
13
  OptionParser.new do |opts|
12
- opts.banner = "Usage: sshy [options]"
13
-
14
- opts.on("-v", "--verbose", "Run verbosely") do |v|
15
- options[:verbose] = v
16
- end
17
- opts.on("-h", "--help", "Help") do |v|
14
+ opts.banner = 'Usage: sshyguy [options]'
15
+ opts.on('-h', '--help', 'Help') do |_v|
18
16
  options[:help] = true
19
17
  end
20
- opts.on("-s", "--shortcut SHORTCUT", "Shortcut") do |v|
18
+ opts.on('-s', '--shortcut SHORTCUT', 'Shortcut') do |v|
21
19
  options[:shortcut] = v
22
20
  end
23
- opts.on('--install') do |v|
21
+ opts.on('--install') do |_v|
24
22
  options[:install] = true
25
23
  end
24
+ opts.on('-d', '--debug', 'Debug') do |_v|
25
+ SshyGuy.config.debug = true
26
+ end
26
27
  end.parse!
27
28
  new(options).run
28
29
  end
@@ -35,9 +36,10 @@ module SshyGuy
35
36
  def run
36
37
  if options[:install]
37
38
  puts "Writing to #{SshyGuy.config_file}"
38
- File.open(SshyGuy.config_file, "w+") { |f| f.puts(File.read("lib/data/example.json")) }
39
+ File.open(SshyGuy.config_file, 'w+') { |f| f.puts(File.read('lib/data/example.json')) }
39
40
  exit
40
41
  end
42
+ SshyGuy.log('Loading config')
41
43
  SshyGuy.load_config!
42
44
  if options[:help]
43
45
  Screens::HelpScreen.show(options)
@@ -46,4 +48,4 @@ module SshyGuy
46
48
  end
47
49
  end
48
50
  end
49
- end
51
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Command
3
5
  attr_reader :to_command
@@ -6,29 +8,23 @@ module SshyGuy
6
8
  end
7
9
 
8
10
  def to_command
11
+ SshyGuy.log('Building command')
12
+ SshyGuy.log(@config['command'])
9
13
  if @config['command'].present?
10
14
  @config['command']
11
15
  else
12
- parts = ["ssh"]
13
- if @config['options'].present?
14
- parts << @config['options']
15
- end
16
+ parts = ['ssh']
17
+ parts << @config['options'] if @config['options'].present?
16
18
  parts << "#{user}@#{hostname}"
17
19
  parts << "-p #{port}"
18
- parts.join(" ")
20
+ parts.join(' ')
19
21
  end
20
22
  end
21
23
 
22
- def hostname
23
- @config['hostname'] || SshyGuy.config.ssh_defaults['hostname']
24
- end
25
-
26
- def user
27
- @config['user'].presence || SshyGuy.config.ssh_defaults['user']
28
- end
29
-
30
- def port
31
- @config['port'].presence || SshyGuy.config.ssh_defaults['port']
24
+ %i[hostname user port options].each do |option|
25
+ define_method(option) do
26
+ @config[option.to_s].presence || SshyGuy.config.ssh_defaults[option.to_s]
27
+ end
32
28
  end
33
29
  end
34
- end
30
+ end
@@ -1,14 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Config
3
5
  attr_accessor :ssh_defaults, :debug, :include_shortcut, :cycle, :filter, :servers, :editor, :folders
4
6
  def cycle?
5
7
  cycle
6
8
  end
9
+
7
10
  def filter?
8
11
  filter
9
12
  end
13
+
10
14
  def debug?
11
15
  debug
12
16
  end
13
17
  end
14
- end
18
+ end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class NilClass
2
4
  def presence
3
5
  false
4
6
  end
7
+
5
8
  def present?
6
9
  false
7
10
  end
@@ -11,6 +14,7 @@ class String
11
14
  def presence
12
15
  present? ? self : false
13
16
  end
17
+
14
18
  def present?
15
19
  !empty?
16
20
  end
@@ -20,15 +24,18 @@ class FalseClass
20
24
  def presence
21
25
  false
22
26
  end
27
+
23
28
  def present?
24
29
  false
25
30
  end
26
31
  end
32
+
27
33
  class TrueClass
28
34
  def presence
29
35
  true
30
36
  end
37
+
31
38
  def present?
32
39
  true
33
40
  end
34
- end
41
+ end
data/lib/sshyguy/menu.rb CHANGED
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Menu
3
- def initialize
4
- end
5
+ def initialize; end
5
6
 
6
7
  def items
7
8
  @items ||= Server.all
8
9
  end
9
10
  end
10
- end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshyGuy
4
+ module Params
5
+ def self.params
6
+ @params ||= {}
7
+ end
8
+
9
+ def self.params=(val)
10
+ @params = val
11
+ end
12
+
13
+ def self.reload_params!
14
+ self.params = {}
15
+ end
16
+ end
17
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Prompt < TTY::Prompt
3
5
  def select(question, *args, &block)
4
6
  super(question, *args, cycle: SshyGuy.config.cycle?, filter: SshyGuy.config.filter?, &block)
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Screen
3
5
  def self.show(options)
@@ -21,11 +23,11 @@ module SshyGuy
21
23
  end
22
24
 
23
25
  def current_folder?
24
- current_folder.present? && current_folder != "__ALL"
26
+ current_folder.present? && current_folder != '__ALL'
25
27
  end
26
28
 
27
29
  def params
28
30
  SshyGuy.params
29
31
  end
30
32
  end
31
- end
33
+ end
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  module Screens
3
5
  class FolderScreen < Screen
4
6
  def show
5
- selected = prompt.select("Select a folder") do |select|
7
+ selected = prompt.select('Select a folder') do |select|
6
8
  Server.folders.each do |folder|
7
9
  select.choice(folder)
8
10
  end
9
- select.choice("All servers", "__ALL")
11
+ select.choice('All servers', '__ALL')
10
12
  end
11
13
  SshyGuy.params[:folder] = selected
12
14
  MainScreen.show(options)
13
15
  end
14
16
  end
15
17
  end
16
- end
18
+ end
@@ -1,23 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  module Screens
3
5
  class HelpScreen < Screen
4
6
  def show
5
- selection = prompt.select("How can I help?") do |select|
7
+ SshyGuy.log('HelpScreen initialized')
8
+ selection = prompt.select('How can I help?') do |select|
6
9
  select.enum '.'
7
- select.choice("Edit config file", :edit)
8
- select.choice("Jk", :close)
9
- select.choice("Exit", :exit)
10
+ select.choice('Edit config file', :edit)
11
+ select.choice('Jk', :close)
12
+ select.choice('Exit', :exit)
10
13
  end
11
14
  case selection
12
15
  when :edit
16
+ SshyGuy.log('Selected :edit')
13
17
  system("#{SshyGuy.config.editor} #{SshyGuy.config_file}")
14
18
  exit
15
19
  when :exit
16
- puts "Bye."
20
+ SshyGuy.log('Selected :exit')
21
+ puts 'Bye.'
22
+ SshyGuy.log('Exiting program')
17
23
  exit
18
24
  when :close
25
+ SshyGuy.log('Selected :close')
26
+ SshyGuy.log('Closing window')
27
+
19
28
  end
20
29
  end
21
30
  end
22
31
  end
23
- end
32
+ end
@@ -1,32 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  module Screens
3
5
  class MainScreen < Screen
4
6
  def show
5
- if options[:shortcut]
6
- server = SshyGuy::Server.all.detect { |server| server.shortcut == options[:shortcut] }
7
- if server
8
- server.spawn
9
- else
10
- puts "No shortcut server found for '#{options[:shortcut]}'"
11
- exit
12
- end
13
- end
14
- label = "Select a server."
7
+ SshyGuy.log('MainScreen initialized')
8
+ ShortcutScreen.show(options) if options[:shortcut]
9
+ SshyGuy.log('Building server menu')
10
+ label = 'Select a server.'
15
11
  servers = SshyGuy::Server.all
16
- server = prompt.select(label, cycle: SshyGuy.config.cycle?, filter: SshyGuy.config.filter?) do |select|
12
+ server = prompt.select(label) do |select|
17
13
  select.enum '.'
18
14
  servers.each do |item|
19
15
  select.choice(item.to_label, item)
20
16
  end
21
- select.choice("Exit folder", :close_folder) if current_folder?
17
+ select.choice('Exit folder', :close_folder) if current_folder?
22
18
  end
19
+ SshyGuy.log("Selected #{server.inspect}")
23
20
  if server == :close_folder
24
- SshyGuy.params[:folder] = '__ALL'
25
21
  MainScreen.show(options)
26
22
  else
23
+ SshyGuy.log("Spawning server #{server.inspect}")
27
24
  server.spawn
28
25
  end
29
26
  end
30
27
  end
31
28
  end
32
- end
29
+ end
@@ -1,16 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  module Screens
3
5
  class ShortcutScreen < Screen
4
6
  def show
5
- menu = Menu.new
6
- shortcut = menu.items.detect { |item| item.shortcut == args[:shortcut] }
7
- unless shortcut
8
- puts "No shortcut found for '#{args[:shortcut]}'"
7
+ unless find_shortcut
8
+ puts "No shortcut found for '#{options[:shortcut]}'"
9
9
  exit
10
10
  end
11
- shortcut.spawn
12
- exit
11
+ find_shortcut.spawn
12
+ end
13
+
14
+ private
15
+
16
+ def find_shortcut
17
+ @find_shortcut ||= Server.all.detect { |item| item.shortcut == options[:shortcut] }
13
18
  end
14
19
  end
15
20
  end
16
- end
21
+ end
@@ -1,21 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
4
  class Server
3
5
  def self.all
4
6
  @all ||= []
5
7
  end
6
8
 
7
- def self.build(servers)
8
- servers.each do |server|
9
- self.all << Server.new(server)
10
- end
11
- end
12
-
13
- def self.folders
14
- @folders ||= self.all.map(&:folder).uniq
15
- end
16
-
17
9
  def initialize(config)
18
10
  @config = config
11
+ self.class.all << self
19
12
  end
20
13
 
21
14
  def to_label
@@ -33,7 +26,7 @@ module SshyGuy
33
26
  end
34
27
 
35
28
  def folder
36
- @config['folder'].presence || "Default"
29
+ @config['folder'].presence || 'Default'
37
30
  end
38
31
 
39
32
  def shortcut
@@ -41,7 +34,7 @@ module SshyGuy
41
34
  end
42
35
 
43
36
  def group
44
- @config['group'].presence || "Default"
37
+ @config['group'].presence || 'Default'
45
38
  end
46
39
  end
47
- end
40
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshyGuy
4
+ module Servers
5
+ def self.servers=(val)
6
+ @servers = val
7
+ end
8
+
9
+ def self.servers
10
+ @servers ||= []
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SshyGuy
2
- VERSION = '0.1.5'
3
- end
4
+ VERSION = '0.1.6'
5
+ CONFIG_VERSION = 1
6
+ end
data/sshyguy.gemspec CHANGED
@@ -1,31 +1,32 @@
1
- lib = File.expand_path("lib", __dir__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
 
4
- require "sshyguy/version"
6
+ require 'sshyguy/version'
5
7
 
6
8
  Gem::Specification.new do |spec|
7
- spec.name = "sshyguy"
9
+ spec.name = 'sshyguy'
8
10
  spec.version = SshyGuy::VERSION
9
- spec.authors = ["Josh Brody"]
10
- spec.email = ["josh@josh.mn"]
11
+ spec.authors = ['Josh Brody']
12
+ spec.email = ['josh@josh.mn']
11
13
 
12
- spec.summary = "A lazy SSH manager."
14
+ spec.summary = 'A lazy SSH manager.'
13
15
  spec.description = spec.summary
14
- spec.homepage = "https://github.com/joshmn/sshyguy"
15
-
16
+ spec.homepage = 'https://github.com/joshmn/sshyguy'
16
17
 
17
- spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata['homepage_uri'] = spec.homepage
18
19
 
19
20
  # Specify which files should be added to the gem when it is released.
20
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
24
  end
24
- spec.bindir = "bin"
25
- spec.executables = ["sshyguy"]
26
- spec.require_paths = ["lib"]
25
+ spec.bindir = 'bin'
26
+ spec.executables = ['sshyguy']
27
+ spec.require_paths = ['lib']
27
28
 
28
- spec.add_development_dependency "bundler", "~> 2.0"
29
- spec.add_development_dependency "rake", "~> 10.0"
30
- spec.add_dependency "tty-prompt"
29
+ spec.add_development_dependency 'bundler', '~> 2.0'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_dependency 'tty-prompt'
31
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshyguy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Brody
@@ -75,6 +75,7 @@ files:
75
75
  - lib/sshyguy/config.rb
76
76
  - lib/sshyguy/core_ext.rb
77
77
  - lib/sshyguy/menu.rb
78
+ - lib/sshyguy/params.rb
78
79
  - lib/sshyguy/prompt.rb
79
80
  - lib/sshyguy/screen.rb
80
81
  - lib/sshyguy/screens/folder_screen.rb
@@ -82,6 +83,7 @@ files:
82
83
  - lib/sshyguy/screens/main_screen.rb
83
84
  - lib/sshyguy/screens/shortcut_screen.rb
84
85
  - lib/sshyguy/server.rb
86
+ - lib/sshyguy/servers.rb
85
87
  - lib/sshyguy/version.rb
86
88
  - sshyguy.gemspec
87
89
  homepage: https://github.com/joshmn/sshyguy