i2cssh 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. data/README.markdown +4 -3
  2. data/VERSION +1 -1
  3. data/bin/i2cssh +54 -100
  4. data/i2cssh.gemspec +1 -1
  5. data/lib/i2cssh.rb +71 -0
  6. metadata +2 -2
@@ -9,13 +9,14 @@ to all sessions.
9
9
  $ gem install i2cssh
10
10
 
11
11
  ## Usage
12
-
13
12
  Usage: i2cssh [options]
14
13
  -d, --debug Start RIPL after creating terminals
15
- -f, --file FILE Cluster file
14
+ -A, --forward-agent Enable SSH agent forwarding
15
+ -f, --file FILE Cluster file (one hostname per line)
16
16
  -F, --fullscreen Fullscreen
17
- -u, --username USERNAME SSH username
17
+ -l, --login LOGIN SSH login name
18
18
  -c, --cluster CLUSTERNAME Name of the cluster specified in ~/.i2csshrc
19
+ -m, --machines a,b,c Comma-separated list of hosts
19
20
  -C, --columns COLUMNS Amount of columns (rows will be calculated)
20
21
  -R, --rows ROWS Amount of rows (columns will be calculated)
21
22
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
data/bin/i2cssh CHANGED
@@ -1,111 +1,65 @@
1
1
  #!/usr/bin/ruby
2
2
  require 'rubygems'
3
- require 'appscript'
4
3
  require 'optparse'
4
+ require 'i2cssh'
5
5
 
6
- options = {}
6
+ i2_options, ssh_options, servers = {}, [], []
7
7
 
8
8
  optparse = OptionParser.new do |opts|
9
- opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
10
- options[:debug] = false
11
- options[:fullscreen] = false
12
- opts.on('-d', '--debug', "Start RIPL after creating terminals") { options[:debug] = true }
13
- opts.on('-A', '--forward-agent', "Enable SSH agent forwarding") { options[:forward] = true }
14
- opts.on('-f', '--file FILE', "Cluster file (one hostname per line)") { |f| options[:file] = f }
15
- opts.on('-F', '--fullscreen', "Fullscreen") { options[:fullscreen] = true }
16
- opts.on('-l', '--login LOGIN', "SSH login name") { |u| options[:login] = u }
17
- opts.on('-c', '--cluster CLUSTERNAME', "Name of the cluster specified in ~/.i2csshrc") { |c| options[:cluster] = c }
18
- opts.on('-m', '--machines a,b,c', Array, "Comma-separated list of hosts") { |h| options[:hosts] = h }
19
- opts.on('-C', '--columns COLUMNS', "Amount of columns (rows will be calculated)") { |c| options[:columns] = c }
20
- opts.on('-R', '--rows ROWS', "Amount of rows (columns will be calculated)") { |r| options[:rows] = r }
21
- # opts.on('-s', '--session SESSIONNAME', "Name of an iTerm2 session") { |s| options[:session_name] = s }
9
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
10
+
11
+ # SSH options
12
+ opts.on '-A', '--forward-agent',
13
+ 'Enable SSH agent forwarding' do
14
+ ssh_options << '-A'
15
+ end
16
+ opts.on '-l', '--login LOGIN',
17
+ 'SSH login name' do |u|
18
+ ssh_options << "-l #{u}"
19
+ end
20
+
21
+ # iTerm2 options
22
+ opts.on '-F', '--fullscreen',
23
+ 'Make the window fullscreen' do
24
+ i2_options[:fullscreen] = true
25
+ end
26
+ opts.on '-C', '--columns COLUMNS', Integer,
27
+ 'Number of columns (rows will be calculated)' do |c|
28
+ i2_options[:columns] = c
29
+ end
30
+ opts.on '-R', '--rows ROWS', Integer,
31
+ 'Number of rows (columns will be calculated)' do |r|
32
+ if i2_options[:columns]
33
+ puts "ERROR: -C and -R can't be used at the same time"
34
+ puts optparse.help
35
+ exit
36
+ else
37
+ i2_options[:rows] = r
38
+ end
39
+ end
40
+
41
+ # Hosts
42
+ opts.on '-f', '--file FILE',
43
+ 'Cluster file (one hostname per line)' do |f|
44
+ servers += File.read(f).split "\n"
45
+ end
46
+ opts.on '-c', '--cluster CLUSTERNAME',
47
+ 'Name of the cluster specified in ~/.i2csshrc' do |c|
48
+ require 'yaml'
49
+ config_hash = YAML.load File.read File.expand_path '~/.i2csshrc'
50
+ servers += config_hash["clusters"][c]
51
+ end
52
+ opts.on '-m', '--machines a,b,c', Array,
53
+ 'Comma-separated list of hosts' do |h|
54
+ servers += h
55
+ end
22
56
  end
23
-
24
57
  optparse.parse!
25
58
 
26
- unless options[:file] || options[:cluster] || options[:hosts] then
27
- puts optparse.help
28
- exit
29
- end
30
-
31
- if [ options[:file], options[:cluster], options[:hosts] ].compact.length > 1 then
32
- puts "ERROR: neither -f, -c or -h can be combined"
33
- puts optparse.help
34
- exit
35
- end
36
-
37
- if options[:columns] && options[:rows] then
38
- puts "ERROR: -C and -R can't be used at the same time"
39
- puts optparse.help
40
- exit
41
- end
42
-
43
- ssh_prefix = "ssh " +
44
- (options[:forward] ? "-A " : "") +
45
- (options[:login] ? "-l #{options[:login]} " : "")
46
-
47
- rows = options[:rows].to_i if options[:rows]
48
- columns = options[:columns].to_i if options[:columns]
49
-
50
-
51
- if options[:file] then
52
- servers = File.read(options[:file]).split("\n")
53
- elsif options[:cluster] then
54
- require 'yaml'
55
- config_hash = YAML.load(File.read(File.expand_path("~/.i2csshrc")))
56
- servers = config_hash["clusters"][options[:cluster]]
57
- elsif options[:hosts] then
58
- servers = options[:hosts]
59
- end
60
-
61
- count = servers.size
62
- if rows then
63
- columns = (count / rows.to_f).ceil
64
- elsif columns then
65
- rows = (count / columns.to_f).ceil
66
- else
67
- rows = Math.sqrt(count).ceil
68
- columns = (count / rows.to_f).ceil
59
+ if servers.empty?
60
+ puts "ERROR: no servers given"
61
+ puts optparse.help
62
+ exit
69
63
  end
70
64
 
71
- iterm = Appscript.app.by_name('iTerm')
72
- finder = Appscript.app.by_name('Finder')
73
- sys_events = Appscript.app.by_name('System Events')
74
- term = iterm.make(:new => :terminal)
75
-
76
- session = term.sessions.after.make(:new => :session)
77
- session.exec(:command => "/bin/bash -l")
78
-
79
- if options[:fullscreen] then
80
- window_bounds = finder.desktop.window.bounds
81
- window = iterm.windows.get.sort_by{|x| x.id_.get}.last
82
- window.bounds.set(window_bounds.get)
83
- end
84
-
85
- (columns - 1).times do
86
- sys_events.keystroke("d", :using => :command_down)
87
- end
88
- (rows - 1).times do
89
- (columns - 1).times do
90
- sys_events.key_code(123, :using => [:command_down, :option_down])
91
- end
92
- (columns).times do |x|
93
- sys_events.keystroke("D", :using => :command_down)
94
- sys_events.key_code(124, :using => [:command_down, :option_down]) unless (columns - 1) == x
95
- end
96
- end
97
-
98
- (rows * columns).times do |i|
99
- if servers && servers[i] then
100
- term.sessions[i+1].write(:text => "history -d $(($HISTCMD-1)) && #{ssh_prefix}#{servers[i]}")
101
- else
102
- term.sessions[i+1].foreground_color.set("red")
103
- term.sessions[i+1].write(:text => "history -d $(($HISTCMD-1)) && stty -isig -icanon -echo && echo -e '#{"\n"*100}UNUSED' && cat > /dev/null")
104
- end
105
- end
106
- if options[:debug] then
107
- require 'ripl'
108
- Ripl.start :binding => binding
109
- end
110
-
111
-
65
+ I2Cssh.new servers, ssh_options, i2_options
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{i2cssh}
8
- s.version = "1.1.0"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wouter de Bie"]
@@ -0,0 +1,71 @@
1
+ require 'appscript'
2
+
3
+ class I2Cssh
4
+ def initialize servers, ssh_options, i2_options
5
+ @ssh_prefix = "ssh " + ssh_options.join(' ')
6
+ @ssh_options = ssh_options
7
+ @i2_options = i2_options
8
+ @servers = servers
9
+
10
+ raise Exception.new 'No servers given' if servers.empty?
11
+
12
+ @sys_events = Appscript.app.by_name('System Events')
13
+ @iterm = Appscript.app.by_name('iTerm')
14
+ @term = @iterm.make(:new => :terminal)
15
+ session = @term.sessions.after.make :new => :session
16
+ session.exec :command => "/bin/bash -l"
17
+
18
+ compute_geometry
19
+ split_session
20
+ maximize if i2_options[:fullscreen]
21
+ start_ssh
22
+ end
23
+
24
+ private
25
+ def maximize
26
+ fullscreen_bounds = Appscript.app.by_name('Finder').desktop.window.bounds
27
+ window = @iterm.windows.get.sort_by{|x| x.id_.get}.last
28
+ window.bounds.set fullscreen_bounds.get
29
+ end
30
+
31
+ def compute_geometry
32
+ count = @servers.size
33
+ if @i2_options[:rows] then
34
+ @columns = (count / @i2_options[:rows].to_f).ceil
35
+ elsif @i2_options[:rows] then
36
+ @rows = (count / @i2_options[:columns].to_f).ceil
37
+ else
38
+ @columns = Math.sqrt(count).ceil
39
+ @rows = (count / @columns.to_f).ceil
40
+ end
41
+ puts @rows
42
+ puts @columns
43
+ end
44
+
45
+ def split_session
46
+ 2.upto @columns do
47
+ @sys_events.keystroke "d", :using => :command_down
48
+ end
49
+ 2.upto @rows do
50
+ 1.upto @columns do
51
+ @sys_events.key_code 123, :using => [:command_down, :option_down]
52
+ end
53
+ @columns.times do |x|
54
+ @sys_events.keystroke "D", :using => :command_down
55
+ @sys_events.key_code 124, :using => [:command_down, :option_down] unless @columns - 1 == x
56
+ end
57
+ end
58
+ end
59
+
60
+ def start_ssh
61
+ 1.upto(@rows*@columns) do |i|
62
+ server = @servers[i-1]
63
+ if server then
64
+ @term.sessions[i].write :text => "unset HISTFILE && #{@ssh_prefix} #{server}"
65
+ else
66
+ @term.sessions[i].foreground_color.set "red"
67
+ @term.sessions[i].write :text => "unset HISTFILE && stty -isig -icanon -echo && echo -e '#{"\n"*100}UNUSED' && cat > /dev/null"
68
+ end
69
+ end
70
+ end
71
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 1.1.0
9
+ version: 1.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Wouter de Bie