2017-11-19 22:34:25 +00:00
|
|
|
#!/usr/bin/env python3
|
2017-07-15 15:11:06 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
from __future__ import division
|
2017-11-19 22:34:25 +00:00
|
|
|
from __future__ import print_function
|
|
|
|
try:
|
|
|
|
import configparser
|
|
|
|
except ImportError:
|
|
|
|
import ConfigParser as configparser # Python 2.x import
|
|
|
|
|
2017-07-15 15:11:06 +00:00
|
|
|
from os import path
|
|
|
|
from sys import argv
|
2017-07-25 13:39:02 +00:00
|
|
|
from math import ceil
|
2017-07-16 10:12:20 +00:00
|
|
|
from getpass import getpass
|
2017-07-19 11:25:42 +00:00
|
|
|
from optparse import OptionParser
|
2017-07-15 15:11:06 +00:00
|
|
|
import subprocess
|
|
|
|
import base64
|
2017-07-25 14:21:54 +00:00
|
|
|
import time
|
2017-11-19 22:34:25 +00:00
|
|
|
import curses
|
|
|
|
from curses import textpad, panel
|
2017-07-15 15:11:06 +00:00
|
|
|
|
2017-07-16 10:12:20 +00:00
|
|
|
# https://github.com/zlaxy/sshch
|
2018-04-08 09:12:04 +00:00
|
|
|
version = "0.994"
|
2017-07-16 10:12:20 +00:00
|
|
|
# path to conf file, default: ~/.config/sshch.conf
|
2017-07-15 15:11:06 +00:00
|
|
|
conf_file = path.expanduser("~") + '/.config/sshch.conf'
|
2018-04-04 21:31:37 +00:00
|
|
|
# expand groups by default
|
|
|
|
expand_default = False
|
2017-07-15 15:11:06 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
def AddNewAlias(alias):
|
2018-04-08 09:12:04 +00:00
|
|
|
alias = alias.split()[0].strip()
|
2017-07-18 17:18:16 +00:00
|
|
|
if not conf.has_section(alias):
|
|
|
|
conf.add_section(alias)
|
|
|
|
conf.write(open(conf_file, "w"))
|
2017-07-19 11:25:42 +00:00
|
|
|
return True
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2018-04-08 09:12:04 +00:00
|
|
|
return "error: '" + alias + "' alias or group already exists"
|
2017-07-18 17:18:16 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
def SetAliasString(alias, string):
|
|
|
|
conf.set(alias, "exec_string", string)
|
|
|
|
conf.write(open(conf_file, "w"))
|
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2018-04-04 21:31:37 +00:00
|
|
|
def SetGroupString(alias, string):
|
|
|
|
conf.set(alias, "group", string)
|
|
|
|
conf.write(open(conf_file, "w"))
|
|
|
|
|
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
def SetPassword(alias, string):
|
|
|
|
string = base64.b64encode(base64.b16encode(
|
|
|
|
base64.b32encode(string)))
|
|
|
|
conf.set(alias, "password", string)
|
|
|
|
conf.write(open(conf_file, "w"))
|
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
def RemoveAliases(aliases):
|
|
|
|
for alias in aliases:
|
|
|
|
conf.remove_section(alias)
|
|
|
|
conf.write(open(conf_file, "w"))
|
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
def ConnectAlias(alias, command=False):
|
|
|
|
exec_string = ""
|
|
|
|
if conf.has_option(alias, "password"):
|
|
|
|
password = base64.b32decode(base64.b16decode(
|
2018-04-04 21:31:37 +00:00
|
|
|
base64.b64decode(conf.get(alias, "password"))))
|
2017-09-05 12:16:23 +00:00
|
|
|
exec_string = 'sshpass -p "' + password + '" '
|
2017-09-13 09:03:00 +00:00
|
|
|
if conf.has_option(alias, "exec_string"):
|
|
|
|
exec_string = exec_string + conf.get(alias, "exec_string")
|
2017-07-18 17:18:16 +00:00
|
|
|
if command:
|
|
|
|
exec_string = exec_string + " " + command
|
2017-07-25 14:21:54 +00:00
|
|
|
subprocess.Popen(exec_string, shell=True).communicate()[0]
|
|
|
|
|
2017-07-25 14:39:18 +00:00
|
|
|
|
2017-07-25 14:21:54 +00:00
|
|
|
def HoldConnection(alias):
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
connectaliases = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
if alias in groups:
|
|
|
|
print("Can't hold connection with group.")
|
|
|
|
else:
|
|
|
|
print("Connecting to " + alias + ". Press CTRL+C to cancel.")
|
|
|
|
time.sleep(1)
|
|
|
|
while True:
|
|
|
|
ConnectAlias(alias)
|
|
|
|
time.sleep(5)
|
2017-07-18 17:18:16 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CMDAdd(alias):
|
|
|
|
result = AddNewAlias(alias)
|
2018-04-08 09:12:04 +00:00
|
|
|
if result == True:
|
2017-07-25 13:39:02 +00:00
|
|
|
prompt_add = ("".join(["Enter connection string for new alias ",
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
2017-07-19 11:25:42 +00:00
|
|
|
string = ""
|
|
|
|
while string == "":
|
2017-11-19 22:34:25 +00:00
|
|
|
string = input(prompt_add)
|
2017-07-19 11:25:42 +00:00
|
|
|
SetAliasString(alias, string)
|
|
|
|
else:
|
2017-11-19 22:34:25 +00:00
|
|
|
print(result)
|
2017-07-19 11:25:42 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2018-04-04 21:31:37 +00:00
|
|
|
def CMDGroup(group):
|
|
|
|
result = AddNewAlias(group)
|
2018-04-08 09:12:04 +00:00
|
|
|
if result == True:
|
2018-04-04 21:31:37 +00:00
|
|
|
prompt_add = ("".join(["Enter aliases for new group ",
|
|
|
|
"(example: alias1 alias2):\n"]))
|
2017-07-19 11:25:42 +00:00
|
|
|
string = ""
|
|
|
|
while string == "":
|
2018-04-04 21:31:37 +00:00
|
|
|
string = input(prompt_add)
|
|
|
|
SetGroupString(group, string)
|
2017-07-19 11:25:42 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
print(result)
|
2017-07-19 11:25:42 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2018-04-04 21:31:37 +00:00
|
|
|
def CMDEdit(alias):
|
2017-07-19 11:25:42 +00:00
|
|
|
if conf.has_section(alias):
|
2018-04-04 21:31:37 +00:00
|
|
|
if conf.has_option(alias, "string"):
|
|
|
|
prompt_edit = ("".join(["Enter connection string for existing alias ",
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
|
|
|
string = ""
|
|
|
|
while string == "":
|
|
|
|
string = input(prompt_edit)
|
|
|
|
SetAliasString(alias, string)
|
|
|
|
elif conf.has_option(alias, "group"):
|
|
|
|
prompt_edit = ("".join(["Enter aliases for existing group ",
|
|
|
|
"(example: alias1 alias2):\n"]))
|
|
|
|
string = ""
|
|
|
|
while string == "":
|
|
|
|
string = input(prompt_edit)
|
|
|
|
SetGroupString(alias, string)
|
|
|
|
else:
|
|
|
|
print("error: '" + alias + "' is not correct alias or group")
|
2017-07-19 11:25:42 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
print("error: '" + alias + "' alias or group does not exists")
|
|
|
|
|
|
|
|
|
|
|
|
def CMDPassword(alias):
|
|
|
|
groups = []
|
|
|
|
connectaliases = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
if alias in groups:
|
|
|
|
print("Can't set password for group.")
|
|
|
|
else:
|
|
|
|
if conf.has_section(alias):
|
|
|
|
prompt_pass = ("[UNSAFE] Enter password for sshpass: ")
|
|
|
|
string = ""
|
|
|
|
string = getpass(prompt_pass)
|
|
|
|
if not string == "":
|
|
|
|
SetPassword(alias, string)
|
|
|
|
else:
|
|
|
|
print("error: '" + alias + "' alias does not exists")
|
2017-07-19 11:25:42 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CMDRemove(alias):
|
|
|
|
if conf.has_section(alias):
|
2018-04-04 21:31:37 +00:00
|
|
|
prompt_remove = ("Type 'yes' if you sure to remove '" + alias + "' alias or group: ")
|
2017-11-19 22:34:25 +00:00
|
|
|
string = input(prompt_remove)
|
2017-07-19 11:25:42 +00:00
|
|
|
if string == "yes":
|
|
|
|
RemoveAliases([alias])
|
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
print("'" + alias + "' alias or group does not deleted.")
|
2017-07-19 11:25:42 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
print("error: '" + alias + "' alias or group does not exists.")
|
2017-07-18 17:18:16 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CMDConnect(aliases, command=False):
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
connectaliases = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
2017-07-16 10:12:20 +00:00
|
|
|
for alias in aliases:
|
2018-04-04 21:31:37 +00:00
|
|
|
if alias in groups:
|
|
|
|
group_aliases = conf.get(alias, "group").split()
|
|
|
|
for ga in group_aliases:
|
|
|
|
if not ga in connectaliases:
|
|
|
|
connectaliases.append(ga)
|
|
|
|
else:
|
|
|
|
if not alias in connectaliases:
|
|
|
|
connectaliases.append(alias)
|
|
|
|
for alias in connectaliases:
|
2017-07-16 10:12:20 +00:00
|
|
|
if conf.has_section(alias):
|
2017-11-19 22:34:25 +00:00
|
|
|
print("Connecting to " + alias + "...")
|
2017-07-19 11:25:42 +00:00
|
|
|
ConnectAlias(alias, command)
|
2017-11-19 22:34:25 +00:00
|
|
|
print("... " + alias + " session finished.")
|
2017-07-16 10:12:20 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
print("error: '" + alias + "' alias does not exists")
|
2017-07-16 10:12:20 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CMDList(option, opt, value, parser):
|
2017-11-21 20:24:24 +00:00
|
|
|
print(' '.join(str(p) for p in conf.sections()))
|
2017-07-16 10:12:20 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2018-04-04 21:31:37 +00:00
|
|
|
def GetTreeList(strings=True, expandlist=True):
|
|
|
|
aliases = []
|
|
|
|
groups = []
|
|
|
|
resultalias = []
|
|
|
|
resultstring = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
elif conf.has_option(a, "exec_string"):
|
|
|
|
aliases.append(a)
|
|
|
|
for g in groups:
|
|
|
|
resultalias.append(g)
|
|
|
|
resultstring.append(">> "+g)
|
|
|
|
group_aliases = conf.get(g, "group").split()
|
|
|
|
for ga in group_aliases:
|
|
|
|
if expandlist == False:
|
|
|
|
pass
|
|
|
|
elif expandlist == True or g in expandlist:
|
|
|
|
if conf.has_option(ga, "exec_string"):
|
|
|
|
resultalias.append(ga+" "+g)
|
|
|
|
result = "".join([" ", str(ga), " (", (conf.get(ga, "exec_string") if
|
|
|
|
conf.has_option(ga, "exec_string") else ""), ")",
|
|
|
|
(" [password]" if conf.has_option(ga, "password") else "")])
|
|
|
|
resultstring.append(result)
|
|
|
|
try:
|
|
|
|
aliases.remove(ga)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
for a in aliases:
|
|
|
|
resultalias.append(a)
|
|
|
|
result = "".join([str(a), " (", (conf.get(a, "exec_string") if
|
|
|
|
conf.has_option(a, "exec_string") else ""), ")",
|
|
|
|
(" [password]" if conf.has_option(a, "password") else "")])
|
|
|
|
resultstring.append(result)
|
|
|
|
if strings:
|
|
|
|
return resultstring;
|
|
|
|
else:
|
|
|
|
return resultalias;
|
|
|
|
|
2017-07-24 14:50:08 +00:00
|
|
|
def CMDFullList(option, opt, value, parser):
|
2018-04-04 21:31:37 +00:00
|
|
|
for p in GetTreeList():
|
|
|
|
print (p)
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-24 14:50:08 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CursesConnect(screen, aliases, command=False):
|
|
|
|
curses.endwin()
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
connectaliases = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
2017-07-19 11:25:42 +00:00
|
|
|
for alias in aliases:
|
2018-04-04 21:31:37 +00:00
|
|
|
if alias in groups:
|
|
|
|
group_aliases = conf.get(alias, "group").split()
|
|
|
|
for ga in group_aliases:
|
|
|
|
if not ga in connectaliases:
|
|
|
|
connectaliases.append(ga)
|
|
|
|
else:
|
|
|
|
if not alias in connectaliases:
|
|
|
|
connectaliases.append(alias)
|
|
|
|
for alias in connectaliases:
|
2017-11-19 22:34:25 +00:00
|
|
|
print("Connecting to " + alias + "...")
|
2017-07-19 11:25:42 +00:00
|
|
|
ConnectAlias(alias, command)
|
2017-11-19 22:34:25 +00:00
|
|
|
print("... " + alias + " session finished.")
|
|
|
|
print("Press 'enter' to continue.")
|
2017-07-19 11:25:42 +00:00
|
|
|
screen.getch()
|
2017-07-16 10:12:20 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-24 14:50:08 +00:00
|
|
|
def CursesExit(error=False):
|
2017-07-19 11:25:42 +00:00
|
|
|
curses.endwin()
|
2017-07-25 13:39:02 +00:00
|
|
|
if error:
|
2017-11-19 22:34:25 +00:00
|
|
|
print(error)
|
2017-07-19 11:25:42 +00:00
|
|
|
exit()
|
2017-07-16 10:12:20 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CursesTextpadConfirm(value):
|
2017-07-18 17:18:16 +00:00
|
|
|
if value == 10:
|
|
|
|
value = 7
|
|
|
|
return value
|
2017-07-19 11:25:42 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CursesTextpad(screen, h, w, y, x, title="", value="",
|
|
|
|
text_colorpair=0, deco_colorpair=0):
|
|
|
|
new_window = curses.newwin(h + 3, w + 2, y - 1, x - 1)
|
2017-07-25 13:39:02 +00:00
|
|
|
title_window = new_window.subwin(1, w, y, x)
|
|
|
|
title_window.addnstr(0, 0, title, w, text_colorpair)
|
2017-07-19 11:25:42 +00:00
|
|
|
title_window.refresh()
|
|
|
|
sub_window = new_window.subwin(h, w, y + 1, x)
|
|
|
|
textbox_field = textpad.Textbox(sub_window, insert_mode=True)
|
|
|
|
new_window.attron(deco_colorpair)
|
|
|
|
new_window.box()
|
|
|
|
new_window.attroff(deco_colorpair)
|
|
|
|
new_window.refresh()
|
2017-07-25 13:39:02 +00:00
|
|
|
sub_window.addnstr(0, 0, value, h * w, text_colorpair)
|
2017-07-19 11:25:42 +00:00
|
|
|
sub_window.attron(text_colorpair)
|
|
|
|
return textbox_field
|
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CursesPanel(screen, h, w, y, x, text,
|
|
|
|
text_colorpair=0, deco_colorpair=0, confirm=0):
|
2017-07-18 17:18:16 +00:00
|
|
|
new_window = curses.newwin(h, w, y, x)
|
|
|
|
new_window.erase()
|
|
|
|
new_window.attron(deco_colorpair)
|
|
|
|
new_window.box()
|
|
|
|
new_window.attroff(deco_colorpair)
|
2017-07-25 13:39:02 +00:00
|
|
|
sub_window = new_window.subwin(h - 2, w - 2, y + 1, x + 1)
|
2017-07-24 14:50:08 +00:00
|
|
|
sub_window.insstr(0, 0, text)
|
2017-07-25 14:21:54 +00:00
|
|
|
panel = curses.panel.new_panel(new_window)
|
2017-07-18 17:18:16 +00:00
|
|
|
curses.panel.update_panels()
|
|
|
|
screen.refresh()
|
|
|
|
if confirm == "password":
|
|
|
|
hidden_password = ""
|
|
|
|
keych = ""
|
|
|
|
position = 2
|
2017-07-19 11:25:42 +00:00
|
|
|
while True:
|
2017-07-18 17:18:16 +00:00
|
|
|
keych = screen.getch()
|
|
|
|
if keych == ord("\n"):
|
|
|
|
break
|
|
|
|
if keych == 27:
|
|
|
|
hidden_password = ""
|
|
|
|
break
|
|
|
|
if keych == curses.KEY_BACKSPACE:
|
|
|
|
if position > 2:
|
2017-07-24 14:50:08 +00:00
|
|
|
if position == len(hidden_password) + 2:
|
|
|
|
sub_window.addstr(1, position - 1, " ",
|
|
|
|
text_colorpair)
|
|
|
|
sub_window.refresh()
|
|
|
|
position = position - 1
|
2017-07-18 17:18:16 +00:00
|
|
|
hidden_password = hidden_password[0:-1]
|
2017-07-24 14:50:08 +00:00
|
|
|
if keych > 31 and keych < 127:
|
2017-07-18 17:18:16 +00:00
|
|
|
hidden_password += curses.keyname(keych)
|
|
|
|
sub_window.addstr(1, position, "*", text_colorpair)
|
2017-07-24 14:50:08 +00:00
|
|
|
if position < w - 4:
|
|
|
|
position += 1
|
2017-07-18 17:18:16 +00:00
|
|
|
sub_window.refresh()
|
|
|
|
return hidden_password
|
|
|
|
elif confirm == "remove":
|
|
|
|
keych = screen.getch()
|
|
|
|
if keych == ord("y") or keych == ord("Y"):
|
|
|
|
return "confirm"
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
screen.getch()
|
2017-07-16 10:12:20 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CMDOptions():
|
|
|
|
class FormatedParser(OptionParser):
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def format_epilog(self, formatter):
|
|
|
|
return self.epilog
|
|
|
|
usage = "usage: %prog [options] [aliases]"
|
|
|
|
progname = path.basename(__file__)
|
2017-07-25 13:39:02 +00:00
|
|
|
epilog = ("".join(["Examples:\n ",
|
|
|
|
progname, " existingalias\n ",
|
|
|
|
progname, " -a newremoteserver\n ",
|
|
|
|
progname, " --edit=newremoteserver -p newremoteserver\n ",
|
|
|
|
progname, ' -c "ls -l" newremoteserver\n ',
|
|
|
|
progname, " -c reboot existingalias newremoteserver\n",
|
|
|
|
"Examples of connection string:\n ",
|
|
|
|
"ssh user@somehost.com\n ",
|
|
|
|
"ssh gates@8.8.8.8 -p 667\n ",
|
|
|
|
"ssh root@somehost.com -t tmux a\n",
|
|
|
|
"Also, you can edit config file manually: ", conf_file, "\n"]))
|
2017-07-19 11:25:42 +00:00
|
|
|
opts = FormatedParser(usage=usage, version="%prog " + version,
|
|
|
|
epilog=epilog)
|
2017-07-25 13:39:02 +00:00
|
|
|
opts.add_option('-l', '--list', action="callback",
|
|
|
|
callback=CMDList, help="show list of all existing aliases")
|
|
|
|
opts.add_option('-f', '--fulllist', action="callback",
|
|
|
|
callback=CMDFullList, help=("show list of all existing " +
|
|
|
|
"aliases with connection strings"))
|
2017-07-19 11:25:42 +00:00
|
|
|
opts.add_option('-a', '--add', action="store", type="string",
|
2017-07-25 13:39:02 +00:00
|
|
|
dest="add", metavar="alias", default=False,
|
|
|
|
help="add new alias for connection string")
|
2018-04-04 21:31:37 +00:00
|
|
|
opts.add_option('-g', '--group', action="store", type="string",
|
|
|
|
dest="group", metavar="group", default=False,
|
|
|
|
help="add new group for aliases")
|
2017-07-19 11:25:42 +00:00
|
|
|
opts.add_option('-c', '--command', action="store", type="string",
|
2017-07-25 13:39:02 +00:00
|
|
|
dest="command", metavar="command", default=False,
|
2018-04-04 21:31:37 +00:00
|
|
|
help="execute command for executing aliases or group")
|
2017-07-25 14:21:54 +00:00
|
|
|
opts.add_option('-k', '--keep', action="store", type="string",
|
|
|
|
dest="keep", metavar="alias", default=False,
|
|
|
|
help="hold connection with specified alias")
|
2017-07-19 11:25:42 +00:00
|
|
|
opts.add_option('-e', '--edit', action="store", type="string",
|
2017-07-25 13:39:02 +00:00
|
|
|
dest='edit', metavar="alias", default=False,
|
2018-04-04 21:31:37 +00:00
|
|
|
help="edit existing alias or group")
|
2017-07-19 11:25:42 +00:00
|
|
|
opts.add_option('-p', '--password', action="store", type="string",
|
2017-07-25 13:39:02 +00:00
|
|
|
dest='password', metavar="alias", default=False,
|
|
|
|
help="set and store password for sshpass [UNSAFE]")
|
2017-07-19 11:25:42 +00:00
|
|
|
opts.add_option('-r', '--remove', action="store", type="string",
|
2017-07-25 13:39:02 +00:00
|
|
|
dest='remove', metavar="alias", default=False,
|
2018-04-04 21:31:37 +00:00
|
|
|
help="remove existing alias or group")
|
2017-07-19 11:25:42 +00:00
|
|
|
options, alias = opts.parse_args()
|
2017-07-25 13:39:02 +00:00
|
|
|
if options.add:
|
|
|
|
CMDAdd(options.add)
|
2018-04-04 21:31:37 +00:00
|
|
|
if options.group:
|
|
|
|
CMDGroup(options.group)
|
2017-07-25 13:39:02 +00:00
|
|
|
if options.edit:
|
|
|
|
CMDEdit(options.edit)
|
|
|
|
if options.password:
|
|
|
|
CMDPassword(options.password)
|
|
|
|
if options.remove:
|
|
|
|
CMDRemove(options.remove)
|
2017-07-25 14:21:54 +00:00
|
|
|
if options.keep:
|
|
|
|
HoldConnection(options.keep)
|
2017-07-25 13:39:02 +00:00
|
|
|
if alias:
|
|
|
|
CMDConnect(alias, options.command)
|
2017-07-18 17:18:16 +00:00
|
|
|
|
|
|
|
# curses template from: https://stackoverflow.com/a/30828805/6224462
|
2017-07-25 13:39:02 +00:00
|
|
|
|
|
|
|
|
2017-07-19 11:25:42 +00:00
|
|
|
def CursesMain():
|
2017-07-25 13:39:02 +00:00
|
|
|
help_screen = ("".join([" Press:\n",
|
|
|
|
" 'z'/'x' or arrows - navigation\n",
|
|
|
|
" 'a'/'F2' - add new alias\n",
|
2018-04-04 21:31:37 +00:00
|
|
|
" 'g'/'F5' - add new group\n",
|
|
|
|
" 'e'/'F4' - edit existing alias/group\n",
|
2017-07-25 13:39:02 +00:00
|
|
|
" 'p'/'F6' - set alias's password for sshpass [UNSAFE]\n",
|
|
|
|
" 'space'/'insert' - select\n",
|
|
|
|
" 'r'/'F8' - remove selected alias/aliases\n",
|
|
|
|
" 'c'/'F3' - execute specific command with selected alias/aliases\n",
|
2017-07-25 14:21:54 +00:00
|
|
|
" 'k'/'F7' - hold connection with selected alias\n",
|
2018-04-04 21:31:37 +00:00
|
|
|
" 'enter'/'F9' - connect to selected alias/aliases,\n",
|
|
|
|
" expand/collapse group\n",
|
2017-07-25 13:39:02 +00:00
|
|
|
" 'q'/'F10' - quit\n",
|
|
|
|
" Run program with '--help' option to view command line help.\n",
|
|
|
|
" Also, you can edit config file manually:\n",
|
|
|
|
" ", conf_file]))
|
2018-04-04 21:31:37 +00:00
|
|
|
if expand_default == True:
|
|
|
|
groups = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
expanded = groups
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
|
|
|
elif expand_default == False:
|
|
|
|
groups = []
|
|
|
|
expanded = groups
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
2017-07-18 17:18:16 +00:00
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings = [" " for i in range(0, row_num + 1)]
|
|
|
|
screen = curses.initscr()
|
|
|
|
curses.noecho()
|
|
|
|
curses.cbreak()
|
|
|
|
curses.start_color()
|
|
|
|
screen.keypad(1)
|
|
|
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN)
|
|
|
|
highlight_text = curses.color_pair(1)
|
|
|
|
normal_text = curses.A_NORMAL
|
|
|
|
height, width = screen.getmaxyx()
|
|
|
|
screen.border(0)
|
|
|
|
curses.curs_set(0)
|
|
|
|
max_row = height - 5
|
2017-07-24 14:50:08 +00:00
|
|
|
screen.addnstr(1, 2, "sshch " + version + ", press 'h' for help",
|
|
|
|
width - 4)
|
2017-07-18 17:18:16 +00:00
|
|
|
box = curses.newwin(max_row + 2, width - 2, 2, 1)
|
|
|
|
box.box()
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
position = 1
|
|
|
|
page = 1
|
|
|
|
for i in range(1, max_row + 1):
|
|
|
|
if row_num == 0:
|
2017-07-25 13:39:02 +00:00
|
|
|
box.addnstr(1, 1, "There aren't any aliases yet. Press 'a' to add new one.",
|
|
|
|
width - 6, highlight_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
exec_string = ["[", selected_strings[i], "] ", stringsfull[i - 1]]
|
2017-07-18 17:18:16 +00:00
|
|
|
if (i == position):
|
2017-07-25 13:39:02 +00:00
|
|
|
box.addnstr(i, 2, "".join(exec_string), width - 6, highlight_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2017-07-25 13:39:02 +00:00
|
|
|
box.addnstr(i, 2, "".join(exec_string), width - 6, normal_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
if i == row_num:
|
|
|
|
break
|
|
|
|
screen.refresh()
|
|
|
|
box.refresh()
|
|
|
|
key_pressed = screen.getch()
|
2017-07-19 11:25:42 +00:00
|
|
|
while True:
|
2017-07-18 17:18:16 +00:00
|
|
|
if key_pressed == ord('q') or key_pressed == ord(
|
2017-07-25 13:39:02 +00:00
|
|
|
'Q') or key_pressed == (
|
|
|
|
27) or key_pressed == curses.KEY_F10:
|
2017-07-19 11:25:42 +00:00
|
|
|
CursesExit()
|
2017-07-18 17:18:16 +00:00
|
|
|
if key_pressed == ord('h') or key_pressed == ord(
|
2017-07-25 13:39:02 +00:00
|
|
|
'H') or key_pressed == curses.KEY_F1:
|
2017-07-19 11:25:42 +00:00
|
|
|
CursesPanel(screen, height - 4, width - 6, 2, 3,
|
|
|
|
help_screen, normal_text, highlight_text)
|
|
|
|
if key_pressed == ord('a') or key_pressed == ord(
|
2017-07-25 13:39:02 +00:00
|
|
|
'A') or key_pressed == curses.KEY_F2:
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(1)
|
2017-07-19 11:25:42 +00:00
|
|
|
new_alias_textpad = CursesTextpad(screen, 1, width - 8,
|
2017-07-25 13:39:02 +00:00
|
|
|
(height // 2) - 1, 4, "Enter new alias:", "",
|
|
|
|
normal_text, highlight_text)
|
2017-07-19 11:25:42 +00:00
|
|
|
add_alias = new_alias_textpad.edit(CursesTextpadConfirm)
|
|
|
|
if not add_alias.rstrip() == "":
|
|
|
|
add_result = AddNewAlias(add_alias.rstrip())
|
2018-04-08 09:12:04 +00:00
|
|
|
if add_result == True:
|
2017-07-19 11:25:42 +00:00
|
|
|
add_string = ""
|
|
|
|
while add_string.rstrip() == "":
|
|
|
|
string_textpad = CursesTextpad(screen, 3,
|
2017-07-25 13:39:02 +00:00
|
|
|
width - 8, (height // 2) - 1, 4,
|
|
|
|
"Enter full execution string:",
|
|
|
|
"ssh ", normal_text, highlight_text)
|
2017-07-19 11:25:42 +00:00
|
|
|
add_string = string_textpad.edit(
|
|
|
|
CursesTextpadConfirm)
|
|
|
|
SetAliasString(add_alias.rstrip(),
|
2017-07-25 13:39:02 +00:00
|
|
|
add_string.replace("\n", "").rstrip())
|
2018-04-04 21:31:37 +00:00
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
2017-07-18 17:18:16 +00:00
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings.append(" ")
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
box.refresh()
|
2018-04-08 09:12:04 +00:00
|
|
|
else:
|
|
|
|
curses.curs_set(0)
|
|
|
|
CursesPanel(screen, 3,
|
|
|
|
width - 6, (height // 2) - 1, 3, add_result,
|
|
|
|
normal_text, highlight_text)
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(0)
|
2018-04-04 21:31:37 +00:00
|
|
|
if key_pressed == ord('g') or key_pressed == ord(
|
|
|
|
'G') or key_pressed == curses.KEY_F5:
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(1)
|
2018-04-04 21:31:37 +00:00
|
|
|
new_group_textpad = CursesTextpad(screen, 1, width - 8,
|
|
|
|
(height // 2) - 1, 4, "Enter name for new group:", "",
|
|
|
|
normal_text, highlight_text)
|
|
|
|
add_group = new_group_textpad.edit(CursesTextpadConfirm)
|
|
|
|
if not add_group.rstrip() == "":
|
|
|
|
add_result = AddNewAlias(add_group.rstrip())
|
2018-04-08 09:12:04 +00:00
|
|
|
if add_result == True:
|
2018-04-04 21:31:37 +00:00
|
|
|
add_string = ""
|
|
|
|
while add_string.rstrip() == "":
|
|
|
|
string_textpad = CursesTextpad(screen, 3,
|
|
|
|
width - 8, (height // 2) - 1, 4,
|
|
|
|
"Enter aliases for new group (example: alias1 alias2):",
|
|
|
|
"", normal_text, highlight_text)
|
|
|
|
add_string = string_textpad.edit(
|
|
|
|
CursesTextpadConfirm)
|
|
|
|
SetGroupString(add_group.rstrip(),
|
|
|
|
add_string.replace("\n", "").rstrip())
|
|
|
|
expanded.append(add_group.rstrip())
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings = [" " for i in range(0, row_num + 1)]
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
box.refresh()
|
2018-04-08 09:12:04 +00:00
|
|
|
else:
|
|
|
|
curses.curs_set(0)
|
|
|
|
CursesPanel(screen, 3,
|
|
|
|
width - 6, (height // 2) - 1, 3, add_result,
|
|
|
|
normal_text, highlight_text)
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(0)
|
2017-07-19 11:25:42 +00:00
|
|
|
if (key_pressed == ord('e') or key_pressed == ord(
|
|
|
|
'E') or key_pressed == curses.KEY_F4) and row_num != 0:
|
|
|
|
edit_string = ""
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(1)
|
2018-04-04 21:31:37 +00:00
|
|
|
if strings[position - 1] in groups:
|
|
|
|
while edit_string.rstrip() == "":
|
|
|
|
string_textpad = CursesTextpad(screen, 3, width - 8,
|
|
|
|
(height // 2) - 1, 4, "Enter new aliases:",
|
|
|
|
(conf.get(strings[position - 1],
|
|
|
|
"group") if conf.has_option(strings[position - 1],
|
|
|
|
"group") else ""),
|
|
|
|
normal_text, highlight_text)
|
|
|
|
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
|
|
|
SetGroupString(strings[position - 1],
|
|
|
|
edit_string.replace("\n", "").rstrip())
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings.append(" ")
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
box.refresh()
|
|
|
|
else:
|
|
|
|
while edit_string.rstrip() == "":
|
|
|
|
string_textpad = CursesTextpad(screen, 3, width - 8,
|
|
|
|
(height // 2) - 1, 4, "Enter new execution string:",
|
|
|
|
(conf.get(strings[position - 1].split()[0].strip(),
|
|
|
|
"exec_string") if conf.has_option(strings[position - 1].split()[0].strip(),
|
|
|
|
"exec_string") else ""),
|
|
|
|
normal_text, highlight_text)
|
|
|
|
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
|
|
|
SetAliasString(strings[position - 1].split()[0].strip(),
|
|
|
|
edit_string.replace("\n", "").rstrip())
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(0)
|
2017-07-19 11:25:42 +00:00
|
|
|
if (key_pressed == ord('p') or key_pressed == ord(
|
|
|
|
'P') or key_pressed == curses.KEY_F6) and row_num != 0:
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
if not strings[position - 1].split()[0].strip() in groups:
|
|
|
|
set_password = ""
|
|
|
|
set_password = CursesPanel(screen, 4, width - 6,
|
|
|
|
(height // 2) - 1, 3,
|
|
|
|
" Enter user password for sshpass and press 'enter':\n>",
|
|
|
|
normal_text, highlight_text, "password")
|
|
|
|
if not set_password == "":
|
|
|
|
SetPassword(strings[position - 1].split()[0].strip(), set_password)
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
2017-07-19 11:25:42 +00:00
|
|
|
if (key_pressed == ord('r') or key_pressed == ord(
|
|
|
|
'R') or key_pressed == curses.KEY_F8 or key_pressed == (
|
|
|
|
curses.KEY_DC)) and row_num != 0:
|
2017-07-18 17:18:16 +00:00
|
|
|
selected = []
|
|
|
|
for i in range(1, row_num + 1):
|
|
|
|
if selected_strings[i] == "*":
|
|
|
|
selected.append(strings[i - 1])
|
|
|
|
if len(selected) > 0:
|
2017-07-25 13:39:02 +00:00
|
|
|
remove_confirm = (
|
|
|
|
"".join(["Are you sure to remove ",
|
|
|
|
str(len(selected)), " selected aliases? (y/N)"]))
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2017-07-25 13:39:02 +00:00
|
|
|
remove_confirm = ("".join(["Are you sure to remove '",
|
2018-04-04 21:31:37 +00:00
|
|
|
strings[position - 1].split()[0].strip(), "' alias? (y/N)"]))
|
|
|
|
selected.append(strings[position - 1].split()[0].strip())
|
2017-07-19 11:25:42 +00:00
|
|
|
remove_result = CursesPanel(screen, 4, width - 6,
|
2017-07-25 13:39:02 +00:00
|
|
|
(height // 2) - 1, 3, remove_confirm, normal_text,
|
|
|
|
highlight_text, "remove")
|
2017-07-19 11:25:42 +00:00
|
|
|
if remove_result == "confirm":
|
2017-07-25 13:39:02 +00:00
|
|
|
RemoveAliases(selected)
|
2018-04-04 21:31:37 +00:00
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
2017-07-18 17:18:16 +00:00
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings = [" " for i in range(0, row_num + 1)]
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
position = 1
|
|
|
|
page = 1
|
|
|
|
box.refresh()
|
2017-07-19 11:25:42 +00:00
|
|
|
if (key_pressed == ord('c') or key_pressed == ord(
|
|
|
|
'C') or key_pressed == curses.KEY_F3) and row_num != 0:
|
2017-07-18 17:18:16 +00:00
|
|
|
selected = []
|
|
|
|
for i in range(1, row_num + 1):
|
|
|
|
if selected_strings[i] == "*":
|
|
|
|
selected.append(strings[i - 1])
|
|
|
|
if not len(selected) > 0:
|
2018-04-04 21:31:37 +00:00
|
|
|
selected.append(strings[position - 1].split()[0].strip())
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(1)
|
2017-07-19 11:25:42 +00:00
|
|
|
command_textpad = CursesTextpad(screen, 3, width - 8,
|
2017-07-25 13:39:02 +00:00
|
|
|
(height // 2) - 1, 4,
|
|
|
|
"".join([
|
|
|
|
"Enter specific command to execute with selected ",
|
|
|
|
"alias/aliases:"]
|
|
|
|
), "", normal_text, highlight_text)
|
2017-07-19 11:25:42 +00:00
|
|
|
command_string = command_textpad.edit(CursesTextpadConfirm)
|
2017-07-24 14:50:08 +00:00
|
|
|
CursesConnect(screen, selected,
|
2017-07-25 13:39:02 +00:00
|
|
|
command_string.replace("\n", "").rstrip())
|
2018-04-08 08:31:20 +00:00
|
|
|
curses.curs_set(0)
|
2017-07-25 14:21:54 +00:00
|
|
|
if (key_pressed == ord('k') or key_pressed == ord('K') or
|
|
|
|
key_pressed == (curses.KEY_F7)) and row_num != 0:
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
if not strings[position - 1] in groups:
|
|
|
|
curses.endwin()
|
|
|
|
HoldConnection(strings[position - 1].split()[0].strip())
|
2017-07-19 11:25:42 +00:00
|
|
|
if (key_pressed == ord("\n") or key_pressed == (
|
|
|
|
curses.KEY_F9)) and row_num != 0:
|
2018-04-04 21:31:37 +00:00
|
|
|
groups = []
|
|
|
|
for a in conf.sections():
|
|
|
|
if conf.has_option(a, "group"):
|
|
|
|
groups.append(a)
|
|
|
|
if strings[position - 1] in groups:
|
|
|
|
if strings[position - 1] in expanded:
|
|
|
|
expanded.remove(strings[position - 1])
|
|
|
|
else:
|
|
|
|
expanded.append(strings[position - 1])
|
|
|
|
strings = GetTreeList(False, expanded)
|
|
|
|
stringsfull = GetTreeList(True, expanded)
|
|
|
|
row_num = len(strings)
|
|
|
|
selected_strings.append(" ")
|
|
|
|
pages = int(ceil(row_num / max_row))
|
|
|
|
box.refresh()
|
|
|
|
else:
|
|
|
|
selected = []
|
|
|
|
for i in range(1, row_num + 1):
|
|
|
|
if selected_strings[i] == "*":
|
|
|
|
selected.append(strings[i - 1])
|
|
|
|
if not len(selected) > 0:
|
|
|
|
selected.append(strings[position - 1].split()[0].strip())
|
|
|
|
CursesConnect(screen, selected)
|
2017-07-24 14:50:08 +00:00
|
|
|
if (key_pressed == 32 or key_pressed == (
|
|
|
|
curses.KEY_IC)) and row_num != 0:
|
2017-07-19 11:25:42 +00:00
|
|
|
if selected_strings[position] == ' ':
|
|
|
|
selected_strings[position] = '*'
|
2017-07-25 13:39:02 +00:00
|
|
|
else:
|
|
|
|
selected_strings[position] = ' '
|
2017-07-19 11:25:42 +00:00
|
|
|
if page == 1:
|
|
|
|
if position < i:
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
if pages > 1:
|
|
|
|
page = page + 1
|
|
|
|
position = 1 + (max_row * (page - 1))
|
|
|
|
elif page == pages:
|
|
|
|
if position < row_num:
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
if position < max_row + (max_row * (page - 1)):
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
page = page + 1
|
|
|
|
position = 1 + (max_row * (page - 1))
|
2017-07-18 17:18:16 +00:00
|
|
|
if key_pressed == curses.KEY_DOWN or key_pressed == ord(
|
2017-07-25 13:39:02 +00:00
|
|
|
'x') or key_pressed == ord('X'):
|
2017-07-18 17:18:16 +00:00
|
|
|
if page == 1:
|
|
|
|
if position < i:
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
if pages > 1:
|
|
|
|
page = page + 1
|
|
|
|
position = 1 + (max_row * (page - 1))
|
|
|
|
elif page == pages:
|
|
|
|
if position < row_num:
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
if position < max_row + (max_row * (page - 1)):
|
|
|
|
position = position + 1
|
|
|
|
else:
|
|
|
|
page = page + 1
|
|
|
|
position = 1 + (max_row * (page - 1))
|
|
|
|
if key_pressed == curses.KEY_UP or key_pressed == ord(
|
2017-07-25 13:39:02 +00:00
|
|
|
'z') or key_pressed == ord('Z'):
|
2017-07-18 17:18:16 +00:00
|
|
|
if page == 1:
|
|
|
|
if position > 1:
|
|
|
|
position = position - 1
|
|
|
|
else:
|
|
|
|
if position > (1 + (max_row * (page - 1))):
|
|
|
|
position = position - 1
|
|
|
|
else:
|
|
|
|
page = page - 1
|
|
|
|
position = max_row + (max_row * (page - 1))
|
2017-07-25 13:39:02 +00:00
|
|
|
if key_pressed == curses.KEY_LEFT or (key_pressed ==
|
|
|
|
curses.KEY_PPAGE):
|
2017-07-18 17:18:16 +00:00
|
|
|
if page > 1:
|
|
|
|
page = page - 1
|
|
|
|
position = 1 + (max_row * (page - 1))
|
|
|
|
if key_pressed == curses.KEY_RIGHT or (key_pressed ==
|
2017-07-25 13:39:02 +00:00
|
|
|
curses.KEY_NPAGE):
|
2017-07-18 17:18:16 +00:00
|
|
|
if page < pages:
|
|
|
|
page = page + 1
|
|
|
|
position = (1 + (max_row * (page - 1)))
|
|
|
|
box.erase()
|
|
|
|
screen.border(0)
|
|
|
|
box.border(0)
|
|
|
|
for i in range(1 + (max_row * (page - 1)), max_row + 1 +
|
|
|
|
(max_row * (page - 1))):
|
|
|
|
if row_num == 0:
|
2017-07-25 13:39:02 +00:00
|
|
|
box.addnstr(1, 1, "There aren't any aliases yet. Press 'a' to add new one.",
|
|
|
|
width - 6, highlight_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2018-04-04 21:31:37 +00:00
|
|
|
exec_string = ["[", selected_strings[i], "] ", stringsfull[i - 1]]
|
2017-07-25 13:39:02 +00:00
|
|
|
if (i + (max_row * (page - 1)) == (position + (max_row * (page - 1)))):
|
|
|
|
box.addnstr(i - (max_row * (page - 1)), 2, "".join(
|
|
|
|
exec_string), width - 6, highlight_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2017-07-25 13:39:02 +00:00
|
|
|
box.addnstr(i - (max_row * (page - 1)), 2, "".join(
|
|
|
|
exec_string), width - 6, normal_text)
|
2017-07-18 17:18:16 +00:00
|
|
|
if i == row_num:
|
|
|
|
break
|
|
|
|
screen.refresh()
|
|
|
|
box.refresh()
|
2017-07-25 13:39:02 +00:00
|
|
|
key_pressed = screen.getch()
|
2017-07-19 11:25:42 +00:00
|
|
|
CursesExit()
|
2017-07-18 17:18:16 +00:00
|
|
|
|
2017-07-25 13:39:02 +00:00
|
|
|
|
2017-07-18 17:18:16 +00:00
|
|
|
if __name__ == "__main__":
|
2017-11-19 22:34:25 +00:00
|
|
|
try:
|
|
|
|
input = raw_input # Fix for Python 2.x
|
|
|
|
except NameError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
conf = configparser.RawConfigParser()
|
2017-07-18 17:18:16 +00:00
|
|
|
if not path.exists(conf_file):
|
|
|
|
open(conf_file, 'w')
|
|
|
|
conf.read(conf_file)
|
|
|
|
if len(argv) > 1:
|
2017-07-24 14:50:08 +00:00
|
|
|
try:
|
|
|
|
CMDOptions()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
exit()
|
2017-11-19 22:34:25 +00:00
|
|
|
except configparser.Error:
|
|
|
|
print("Error: can't parse your config file, please check it manually or make new one")
|
2017-07-24 14:50:08 +00:00
|
|
|
exit()
|
2017-07-18 17:18:16 +00:00
|
|
|
else:
|
2017-07-24 14:50:08 +00:00
|
|
|
try:
|
|
|
|
CursesMain()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
CursesExit()
|
2017-11-19 22:34:25 +00:00
|
|
|
except configparser.NoOptionError:
|
2017-07-25 13:39:02 +00:00
|
|
|
CursesExit("".join(["Error: can't parse your config file, please ",
|
|
|
|
"check it manually or make new one"]))
|
2017-07-24 14:50:08 +00:00
|
|
|
except curses.error:
|
2017-07-25 13:39:02 +00:00
|
|
|
CursesExit("".join(["Error: can't show some curses element, maybe ",
|
|
|
|
"your terminal is too small"]))
|