-
Notifications
You must be signed in to change notification settings - Fork 5
/
WindowSwitch.py
148 lines (123 loc) · 4.64 KB
/
WindowSwitch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os, console, sys, ctypes
from common import expand_env_vars
import PyCmdUtils
from pycmd_public import color
windows_state_path = 'win_stat.txt'
winstate_separator = '^$^'
pycmd_data_dir = None
winstate_full_path = None
def py_GetConsoleWindow():
return ctypes.windll.kernel32.GetConsoleWindow()
def py_IsWindow(hwnd):
return ctypes.windll.user32.IsWindow(hwnd)
def init():
# %APPDATA% is not always defined (e.g. when using runas.exe)
if 'APPDATA' in os.environ.keys():
APPDATA = '%APPDATA%'
else:
APPDATA = '%USERPROFILE%\\Application Data'
global pycmd_data_dir
global winstate_full_path
pycmd_data_dir = expand_env_vars(APPDATA + '\\PyCmd')
winstate_full_path = os.path.join(pycmd_data_dir, windows_state_path)
if not os.path.exists(pycmd_data_dir):
os.mkdir(pycmd_data_dir)
if not os.path.exists(winstate_full_path):
open(winstate_full_path, 'a').close()
def update_window_state(pwd = '', cmd = '', hwnd = None, remove_hwnd_list=[]):
"""Update status for given hwnd"""
if hwnd == None:
hwnd = py_GetConsoleWindow()
pwd = pwd.strip()
cmd = cmd.strip()
remove_hwnd = len(pwd) == 0 and len(cmd) == 0
if not remove_hwnd and len(pwd) == 0:
pwd = os.getcwd()
with open(winstate_full_path, 'r+') as f:
winstate = f.readlines()
f.seek(0)
for line in winstate:
line = line.strip()
stats = line.split(winstate_separator)
if len(stats) != 3:
continue
if int(stats[0]) in remove_hwnd_list:
# remove invalid line
continue
if not line.startswith(str(hwnd)):
f.write(line + '\n')
elif not remove_hwnd:
if len(stats) != 3:
print("Warning: unsupported line for windows switch", line)
if len(cmd) == 0:
cmd = stats[2]
if not remove_hwnd:
new_line = winstate_separator.join([str(hwnd), pwd, cmd]) + '\n'
f.write(new_line)
f.truncate()
def list_and_switch():
winstate_full_path = os.path.join(pycmd_data_dir, windows_state_path)
with open(winstate_full_path, 'r') as f:
winstate = f.readlines()
winstate.reverse()
first_line = True
index = 0
orig_index = -1
index_map = []
remove_hwnd_list = []
columns = console.get_buffer_size()[0] - 3
currHwnd = py_GetConsoleWindow()
for line in winstate:
orig_index += 1
states = line.split(winstate_separator)
if len(states) != 3:
print("Warning: unsupported line for windows switch: ", line)
continue
hwnd = int(states[0])
if hwnd == currHwnd:
continue
if not py_IsWindow(hwnd):
remove_hwnd_list.append(hwnd)
continue
curr_index_char = chr(ord('a') + index)
index += 1
index_map.append(orig_index)
pwd = states[1].strip() + '> '
cmd = states[2].strip()
if len(pwd) > columns:
pwd = pwd[0: column - 5] + '...> '
cmd = ''
else:
left_columns = columns - len(pwd)
if len(cmd) > left_columns:
if left_columns >= 3:
cmd = cmd[0:left_columns - 3] + '...'
if first_line:
sys.stdout.write('\n\n')
first_line = False
if index % 2 == 0:
color_str_cmd = color.Fore.RED + color.Fore.CLEAR_BRIGHT
color_str_pwd = color.Fore.RED + color.Fore.SET_BRIGHT
else:
color_str_cmd = color.Fore.GREEN + color.Fore.CLEAR_BRIGHT
color_str_pwd = color.Fore.GREEN + color.Fore.SET_BRIGHT
sys.stdout.write(color_str_pwd + curr_index_char + ': ' + pwd + color_str_cmd + cmd + '\n')
if index == 0:
return
sys.stdout.write(color.Fore.DEFAULT + '\n')
message = ' Press a-z to switch to target PyCmd, space to ignore: '
sys.stdout.write(message)
rec = console.read_input()
select_id = ord(rec.Char) - ord('a')
#TODO: refresh current line instead of output new line?
# Why 1 '\n' doesn't work? Know why, because cmd prompt is up for 1 line,
# which occupies the message line scrolled by 1 line
#sys.stdout.write('\n\n')
sys.stdout.write('\r' + ' ' * len(message))
if 0 <= select_id < index:
to_line = winstate[index_map[select_id]]
to_line_list = to_line.split(winstate_separator)
to_hwnd = int(to_line_list[0])
PyCmdUtils.SwitchToHwnd(to_hwnd)
update_window_state(to_line_list[1], to_line_list[2], to_hwnd, remove_hwnd_list)
init()