Ubuntu's usage of dash for sh broke :upload, use bash instead
[gsh.git] / gsh / dispatchers.py
blob15da0a70c7997eab5e5ae5042734882f31f4efbf
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006, 2007, 2008 Guillaume Chazarain <guichaz@gmail.com>
19 import asyncore
20 import fcntl
21 import struct
22 import termios
24 from gsh import remote_dispatcher
25 from gsh import display_names
26 from gsh.terminal_size import terminal_size
28 def all_instances():
29 """Iterator over all the remote_dispatcher instances"""
30 return sorted([i for i in asyncore.socket_map.itervalues() if
31 isinstance(i, remote_dispatcher.remote_dispatcher)],
32 key=lambda i: i.display_name)
34 def count_awaited_processes():
35 """Return a tuple with the number of awaited processes and the total
36 number"""
37 awaited = 0
38 total = 0
39 for i in all_instances():
40 if i.enabled:
41 total += 1
42 if i.state is not remote_dispatcher.STATE_IDLE:
43 awaited += 1
44 return awaited, total
46 def all_terminated():
47 """For each remote shell determine if its terminated"""
48 instances_found = False
49 for i in all_instances():
50 instances_found = True
51 if i.state not in (remote_dispatcher.STATE_TERMINATED,
52 remote_dispatcher.STATE_DEAD):
53 return False
54 return instances_found
56 def update_terminal_size():
57 """Propagate the terminal size to the remote shells accounting for the
58 place taken by the longest name"""
59 w, h = terminal_size()
60 w = max(w - display_names.max_display_name_length - 2, min(w, 10))
61 # python bug http://python.org/sf/1112949 on amd64
62 # from ajaxterm.py
63 bug = struct.unpack('i', struct.pack('I', termios.TIOCSWINSZ))[0]
64 packed_size = struct.pack('HHHH', h, w, 0, 0)
65 term_size = w, h
66 for i in all_instances():
67 if i.enabled and i.term_size != term_size:
68 i.term_size = term_size
69 fcntl.ioctl(i.fd, bug, packed_size)
71 def format_info(info_list):
72 """Turn a 2-dimension list of strings into a 1-dimension list of strings
73 with correct spacing"""
74 max_lengths = []
75 if info_list:
76 nr_columns = len(info_list[0])
77 else:
78 nr_columns = 0
79 for i in xrange(nr_columns):
80 max_lengths.append(max([len(str(info[i])) for info in info_list]))
81 for info_id in xrange(len(info_list)):
82 info = info_list[info_id]
83 for str_id in xrange(len(info) - 1):
84 # Don't justify the last column (i.e. the last printed line)
85 # as it can get much longer in some shells than in others
86 orig_str = str(info[str_id])
87 indent = max_lengths[str_id] - len(orig_str)
88 info[str_id] = orig_str + indent * ' '
89 info_list[info_id] = ' '.join(info) + '\n'