multiSSH3 5.73__tar.gz → 5.74__tar.gz
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.
Potentially problematic release.
This version of multiSSH3 might be problematic. Click here for more details.
- {multissh3-5.73 → multissh3-5.74}/PKG-INFO +1 -1
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/PKG-INFO +1 -1
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.py +58 -6
- {multissh3-5.73 → multissh3-5.74}/README.md +0 -0
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/SOURCES.txt +0 -0
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/dependency_links.txt +0 -0
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/entry_points.txt +0 -0
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/requires.txt +0 -0
- {multissh3-5.73 → multissh3-5.74}/multiSSH3.egg-info/top_level.txt +0 -0
- {multissh3-5.73 → multissh3-5.74}/setup.cfg +0 -0
- {multissh3-5.73 → multissh3-5.74}/setup.py +0 -0
- {multissh3-5.73 → multissh3-5.74}/test/test.py +0 -0
- {multissh3-5.73 → multissh3-5.74}/test/testCurses.py +0 -0
- {multissh3-5.73 → multissh3-5.74}/test/testCursesOld.py +0 -0
- {multissh3-5.73 → multissh3-5.74}/test/testPerfCompact.py +0 -0
- {multissh3-5.73 → multissh3-5.74}/test/testPerfExpand.py +0 -0
|
@@ -10,6 +10,7 @@ __curses_available = False
|
|
|
10
10
|
__resource_lib_available = False
|
|
11
11
|
try:
|
|
12
12
|
import curses
|
|
13
|
+
import curses.panel
|
|
13
14
|
__curses_available = True
|
|
14
15
|
except ImportError:
|
|
15
16
|
pass
|
|
@@ -54,10 +55,10 @@ except AttributeError:
|
|
|
54
55
|
# If neither is available, use a dummy decorator
|
|
55
56
|
def cache_decorator(func):
|
|
56
57
|
return func
|
|
57
|
-
version = '5.
|
|
58
|
+
version = '5.74'
|
|
58
59
|
VERSION = version
|
|
59
60
|
__version__ = version
|
|
60
|
-
COMMIT_DATE = '2025-
|
|
61
|
+
COMMIT_DATE = '2025-06-03'
|
|
61
62
|
|
|
62
63
|
CONFIG_FILE_CHAIN = ['./multiSSH3.config.json',
|
|
63
64
|
'~/multiSSH3.config.json',
|
|
@@ -1868,6 +1869,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1868
1869
|
_ = config_reason
|
|
1869
1870
|
try:
|
|
1870
1871
|
box_ansi_color = None
|
|
1872
|
+
refresh_all = True
|
|
1871
1873
|
org_dim = stdscr.getmaxyx()
|
|
1872
1874
|
# To do this, first we need to know the size of the terminal
|
|
1873
1875
|
max_y, max_x = org_dim
|
|
@@ -1951,6 +1953,33 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1951
1953
|
#bottom_border.addnstr(0, 0, '-' * (max_x - 1), max_x - 1)
|
|
1952
1954
|
_curses_add_string_to_window(window=bottom_border, y=0, line='-' * (max_x - 1),fill_char='-',box_ansi_color=box_ansi_color)
|
|
1953
1955
|
bottom_border.refresh()
|
|
1956
|
+
help_window_hight = min(14, max_y)
|
|
1957
|
+
help_window_width = min(31, max_x)
|
|
1958
|
+
# Create a centered help window
|
|
1959
|
+
help_window_y = (max_y - help_window_hight) // 2
|
|
1960
|
+
help_window_x = (max_x - help_window_width) // 2
|
|
1961
|
+
help_window = curses.newwin(help_window_hight, help_window_width, help_window_y, help_window_x)
|
|
1962
|
+
help_window.leaveok(True)
|
|
1963
|
+
help_window.scrollok(True)
|
|
1964
|
+
help_window.idlok(True)
|
|
1965
|
+
help_window.box()
|
|
1966
|
+
_curses_add_string_to_window(window=help_window,y=0,line='Help', color_pair_list=[-1,-1,1], centered=True, fill_char='─', lead_str='┌', box_ansi_color=box_ansi_color)
|
|
1967
|
+
_curses_add_string_to_window(window=help_window,y=1,line='? : Toggle Help Menu', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1968
|
+
_curses_add_string_to_window(window=help_window,y=2,line='_ or + : Change window hight', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1969
|
+
_curses_add_string_to_window(window=help_window,y=3,line='{ or } : Change window width', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1970
|
+
_curses_add_string_to_window(window=help_window,y=4,line='< or > : Change host index', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1971
|
+
_curses_add_string_to_window(window=help_window,y=5,line='|(pipe) : Toggle single host', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1972
|
+
_curses_add_string_to_window(window=help_window,y=6,line='Ctrl+D : Exit', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1973
|
+
_curses_add_string_to_window(window=help_window,y=7,line='Ctrl+R : Force refresh', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1974
|
+
_curses_add_string_to_window(window=help_window,y=8,line='↑ or ↓ : Navigate history', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1975
|
+
_curses_add_string_to_window(window=help_window,y=9,line='← or → : Move cursor', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1976
|
+
_curses_add_string_to_window(window=help_window,y=10,line='PgUp/Dn : Scroll history by 5', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1977
|
+
_curses_add_string_to_window(window=help_window,y=11,line='Home/End: Jump cursor', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1978
|
+
_curses_add_string_to_window(window=help_window,y=12,line='Esc : Clear line', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1979
|
+
help_panel = curses.panel.new_panel(help_window)
|
|
1980
|
+
help_panel.hide()
|
|
1981
|
+
help_shown = False
|
|
1982
|
+
curses.panel.update_panels()
|
|
1954
1983
|
indexOffset = 0
|
|
1955
1984
|
while host_stats['running'] > 0 or host_stats['waiting'] > 0:
|
|
1956
1985
|
# Check for keypress
|
|
@@ -1961,7 +1990,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1961
1990
|
# When we encounter a newline, we add a new list to the list of lists. ( a new line of input )
|
|
1962
1991
|
# with open('keylog.txt','a') as f:
|
|
1963
1992
|
# f.write(str(key)+'\n')
|
|
1964
|
-
if key == 410: # 410 is the key code for resize
|
|
1993
|
+
if key == 410 or key == curses.KEY_RESIZE: # 410 is the key code for resize
|
|
1965
1994
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal resize requested')
|
|
1966
1995
|
# if the user pressed ctrl + d and the last line is empty, we will exit by adding 'exit\n' to the last line
|
|
1967
1996
|
elif key == 4 and not __keyPressesIn[-1]:
|
|
@@ -1991,12 +2020,15 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1991
2020
|
# We handle positional keys
|
|
1992
2021
|
# if the key is up arrow, we will move the line to display up
|
|
1993
2022
|
elif key == 259: # 259 is the key code for up arrow
|
|
2023
|
+
# also scroll curserPosition to last if it is currently at the last line and curserPosition is at 0
|
|
1994
2024
|
lineToDisplay = max(lineToDisplay - 1, -len(__keyPressesIn))
|
|
2025
|
+
if lineToDisplay == -2 and not __keyPressesIn[-1]:
|
|
2026
|
+
curserPosition = len(__keyPressesIn[lineToDisplay])
|
|
1995
2027
|
# if the key is down arrow, we will move the line to display down
|
|
1996
2028
|
elif key == 258: # 258 is the key code for down arrow
|
|
1997
2029
|
lineToDisplay = min(lineToDisplay + 1, -1)
|
|
1998
2030
|
# if the key is left arrow, we will move the cursor left
|
|
1999
|
-
elif key == 260: # 260 is the key
|
|
2031
|
+
elif key == 260: # 260 is the key code for left arrow
|
|
2000
2032
|
curserPosition = min(max(curserPosition - 1, 0), len(__keyPressesIn[lineToDisplay]) -1)
|
|
2001
2033
|
# if the key is right arrow, we will move the cursor right
|
|
2002
2034
|
elif key == 261: # 261 is the key code for right arrow
|
|
@@ -2013,6 +2045,23 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2013
2045
|
# if the key is end, we will move the cursor to the end of the line
|
|
2014
2046
|
elif key == 360: # 360 is the key code for end
|
|
2015
2047
|
curserPosition = len(__keyPressesIn[lineToDisplay])
|
|
2048
|
+
elif key == curses.KEY_REFRESH or key == curses.KEY_F5 or key == 18: # 18 is the key code for ctrl + R
|
|
2049
|
+
# if the key is refresh, we will refresh the screen
|
|
2050
|
+
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Refresh requested')
|
|
2051
|
+
elif key == curses.KEY_EXIT or key == 27: # 27 is the key code for ESC
|
|
2052
|
+
# if the key is exit, we will exit the program
|
|
2053
|
+
return
|
|
2054
|
+
elif key == curses.KEY_HELP or key == 63 or key == curses.KEY_F1: # 63 is the key code for ?
|
|
2055
|
+
# if the key is help, we will display the help message
|
|
2056
|
+
if not help_shown:
|
|
2057
|
+
help_panel.show()
|
|
2058
|
+
help_shown = True
|
|
2059
|
+
else:
|
|
2060
|
+
help_panel.hide()
|
|
2061
|
+
help_shown = False
|
|
2062
|
+
refresh_all = True
|
|
2063
|
+
#return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Help closed')
|
|
2064
|
+
curses.panel.update_panels()
|
|
2016
2065
|
# We are left with these are keys that mofidy the current line.
|
|
2017
2066
|
else:
|
|
2018
2067
|
# This means the user have done scrolling and is committing to modify the current line.
|
|
@@ -2058,7 +2107,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2058
2107
|
# displayCurserPosition is needed as the curserPosition can be larger than the length of the encodedLine. This is wanted to keep scrolling through the history less painful
|
|
2059
2108
|
displayCurserPosition = min(curserPosition,len(encodedLine) -1)
|
|
2060
2109
|
stats = f'Send CMD: {encodedLine[:displayCurserPosition]}\x1b[7m{encodedLine[displayCurserPosition]}\x1b[0m{encodedLine[displayCurserPosition + 1:]}'
|
|
2061
|
-
if stats != old_stat :
|
|
2110
|
+
if stats != old_stat or refresh_all:
|
|
2062
2111
|
old_stat = stats
|
|
2063
2112
|
# calculate the real curser position in stats as we centered the stats
|
|
2064
2113
|
# if 'Send CMD: ' in stats:
|
|
@@ -2078,7 +2127,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2078
2127
|
#target_length = max_x - 2 + len('\x1b[33m\x1b[0m\x1b[31m\x1b[0m\x1b[32m\x1b[0m')
|
|
2079
2128
|
#bottom_stats = '└'+ f" Total: {len(hosts)} Running: \x1b[33m{host_stats['running']}\x1b[0m Failed: \x1b[31m{host_stats['failed']}\x1b[0m Finished: \x1b[32m{host_stats['finished']}\x1b[0m Waiting: {host_stats['waiting']} "[:target_length].center(target_length, "─")
|
|
2080
2129
|
bottom_stats = f" Total: {len(hosts)} Running: \x1b[33m{host_stats['running']}\x1b[0m Failed: \x1b[31m{host_stats['failed']}\x1b[0m Finished: \x1b[32m{host_stats['finished']}\x1b[0m Waiting: {host_stats['waiting']} "
|
|
2081
|
-
if bottom_stats != old_bottom_stat:
|
|
2130
|
+
if bottom_stats != old_bottom_stat or refresh_all:
|
|
2082
2131
|
old_bottom_stat = bottom_stats
|
|
2083
2132
|
#bottom_border.clear()
|
|
2084
2133
|
#bottom_border.addnstr(0, 0, bottom_stats, max_x - 1)
|
|
@@ -2087,6 +2136,9 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2087
2136
|
# set the maximum refresh rate to 100 Hz
|
|
2088
2137
|
if time.perf_counter() - last_refresh_time < 0.01:
|
|
2089
2138
|
time.sleep(max(0,0.01 - time.perf_counter() + last_refresh_time))
|
|
2139
|
+
if refresh_all:
|
|
2140
|
+
rearrangedHosts = set(hosts_to_display)
|
|
2141
|
+
refresh_all = False
|
|
2090
2142
|
#stdscr.clear()
|
|
2091
2143
|
for host_window, host in zip(host_windows, hosts_to_display):
|
|
2092
2144
|
# we will only update the window if there is new output or the window is not fully printed
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|