Created
September 2, 2011 18:03
-
-
Save kepler/1189327 to your computer and use it in GitHub Desktop.
SSHplus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
# | |
# SSHplus | |
# A remote connect utlity, sshmenu compatible clone, and application starter. | |
# | |
# (C) 2011 Anil Gulecha | |
# Based on sshlist, incorporating changes by Benjamin Heil's simplestarter | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
# Instructions | |
# | |
# 1. Copy file sshplus.py (this file) to /usr/local/bin | |
# 2. Edit file .sshplus in your home directory to add menu entries, each | |
# line in the format NAME|COMMAND|ARGS | |
# 3. Launch sshplus.py | |
# 4. Or better yet, add it to gnome startup programs list so it's run on login. | |
import gobject | |
import gtk | |
import appindicator | |
import os | |
import pynotify | |
import sys | |
import shlex | |
_VERSION = "1.0" | |
_SETTINGS_FILE = os.getenv("HOME") + "/.sshplus" | |
_SSHMENU_FILE = os.getenv("HOME") + "/.sshmenu" | |
_ABOUT_TXT = """A simple application starter as appindicator. | |
To add items to the menu, edit the file <i>.sshplus</i> in your home directory. Each entry must be on a new line in this format: | |
<tt>NAME|COMMAND|ARGS</tt> | |
If the item is clicked in the menu, COMMAND with arguments ARGS will be executed. ARGS can be empty. To insert a separator, add a line which only contains "sep". Lines starting with "#" will be ignored. You can set an unclickable label with the prefix "label:". Items from sshmenu configuration will be automatically added (except nested items). To insert a nested menu, use the prefix "folder:menu name". Subsequent items will be inserted in this menu, until a line containing an empty folder name is found: "folder:". After that, subsequent items get inserted in the parent menu. That means that more than one level of nested menus can be created. | |
Example file: | |
<tt><small> | |
Show top|gnome-terminal|-x top | |
sep | |
# this is a comment | |
label:SSH connections | |
# create a folder named "Home" | |
folder:Home | |
SSH Ex|gnome-terminal|-x ssh [email protected] | |
# to mark the end of items inside "Home", specify and empty folder: | |
folder: | |
# this item appears in the main menu | |
SSH Ex|gnome-terminal|-x ssh [email protected] | |
label:RDP connections | |
RDP Ex|rdesktop|-T "RDP-Server" -r sound:local 1.2.3.4 | |
</small></tt> | |
Copyright 2011 Anil Gulecha | |
Incorporating changes from simplestarter, Benjamin Heil, http://www.bheil.net | |
Released under GPL3, http://www.gnu.org/licenses/gpl-3.0.html""" | |
def menuitem_response(w, item): | |
if item == '_about': | |
show_help_dlg(_ABOUT_TXT) | |
elif item == '_refresh': | |
newmenu = build_menu() | |
ind.set_menu(newmenu) | |
pynotify.Notification("SSHplus refreshed", "Menu list was refreshed from %s" % _SETTINGS_FILE).show() | |
elif item == '_quit': | |
sys.exit(0) | |
elif item == 'folder': | |
pass | |
else: | |
print item | |
os.spawnvp(os.P_NOWAIT, item['cmd'], [item['cmd']] + item['args']) | |
os.wait3(os.WNOHANG) | |
def show_help_dlg(msg, error=False): | |
if error: | |
dlg_icon = gtk.MESSAGE_ERROR | |
else: | |
dlg_icon = gtk.MESSAGE_INFO | |
md = gtk.MessageDialog(None, 0, dlg_icon, gtk.BUTTONS_OK) | |
try: | |
md.set_markup("<b>SSHplus %s</b>" % _VERSION) | |
md.format_secondary_markup(msg) | |
md.run() | |
finally: | |
md.destroy() | |
def add_separator(menu): | |
separator = gtk.SeparatorMenuItem() | |
separator.show() | |
menu.append(separator) | |
def add_menu_item(menu, caption, item=None): | |
menu_item = gtk.MenuItem(caption) | |
if item: | |
menu_item.connect("activate", menuitem_response, item) | |
else: | |
menu_item.set_sensitive(False) | |
menu_item.show() | |
menu.append(menu_item) | |
return menu_item | |
def get_sshmenuconfig(): | |
if not os.path.exists(_SSHMENU_FILE): | |
return None | |
hostlist=open(os.getenv("HOME")+"/.sshmenu","r").read() | |
smenutitle=[] | |
smenuparams=[] | |
try: | |
for line in hostlist.split("\n"): | |
if line[2:7] == "title": | |
smenutitle.append(line.split(":")[1]) | |
if line[2:11] == "sshparams": | |
smenuparams.append(line.split(":")[1]) | |
if len(smenutitle) == len(smenuparams): | |
if len(smenutitle) != 0: | |
return (smenutitle,smenuparams) | |
else: | |
if len(smenuparams) != 0: | |
return (smenuparams,smenuparams) | |
return None | |
except: | |
return None | |
def get_sshplusconfig(): | |
if not os.path.exists(_SETTINGS_FILE): | |
return [] | |
app_list = [] | |
f = open(_SETTINGS_FILE, "r") | |
try: | |
for line in f.readlines(): | |
line = line.rstrip() | |
if not line or line.startswith('#'): | |
continue | |
elif line == "sep": | |
app_list.append('sep') | |
elif line.startswith('label:'): | |
app_list.append({ | |
'name': 'LABEL', | |
'cmd': line[6:], | |
'args': '' | |
}) | |
elif line.startswith('folder:'): | |
app_list.append({ | |
'name': 'FOLDER', | |
'cmd': line[7:], | |
'args': '' | |
}) | |
else: | |
try: | |
name, cmd, args = line.split('|', 2) | |
app_list.append({ | |
'name': name, | |
'cmd': cmd, | |
'args': [n.replace("\n", "") for n in shlex.split(args)], | |
}) | |
except ValueError: | |
print "The following line has errors and will be ignored:\n%s" % line | |
finally: | |
f.close() | |
return app_list | |
def build_menu(): | |
if not os.path.exists(_SETTINGS_FILE) and not os.path.exists(_SSHMENU_FILE) : | |
show_help_dlg("<b>ERROR: No .sshmenu or .sshplus file found in home directory</b>\n\n%s" % \ | |
_ABOUT_TXT, error=True) | |
sys.exit(1) | |
app_list = get_sshplusconfig() | |
#Add sshmenu config items if any | |
sshmenuitems = get_sshmenuconfig() | |
if sshmenuitems != None: | |
app_list.append("sep") | |
app_list.append({ | |
'name': 'LABEL', | |
'cmd': "SSHmenu", | |
'args': '' | |
}) | |
titles=sshmenuitems[0] | |
sshparams=sshmenuitems[1] | |
for i in range(len(titles)): | |
app_list.append({ | |
'name': titles[i], | |
'cmd': "gnome-terminal", | |
'args': [n.replace("\n", "") for n in shlex.split("-x ssh " + sshparams[i])], | |
}) | |
menu = gtk.Menu() | |
menus = [menu] | |
for app in app_list: | |
if app == "sep": | |
add_separator(menus[-1]) | |
elif app['name'] == "FOLDER" and not app['cmd']: | |
if len(menus) > 1: | |
menus.pop() | |
elif app['name'] == "FOLDER": | |
menu_item = add_menu_item(menus[-1], app['cmd'], 'folder') | |
menus.append(gtk.Menu()) | |
menu_item.set_submenu(menus[-1]) | |
elif app['name'] == "LABEL": | |
add_menu_item(menus[-1], app['cmd'], None) | |
else: | |
add_menu_item(menus[-1], app['name'], app) | |
add_separator(menu) | |
add_menu_item(menu, 'Refresh', '_refresh') | |
add_menu_item(menu, 'About', '_about') | |
add_separator(menu) | |
add_menu_item(menu, 'Quit', '_quit') | |
return menu | |
if __name__ == "__main__": | |
ind = appindicator.Indicator("sshplus", "stock_connect", | |
appindicator.CATEGORY_APPLICATION_STATUS) | |
#ind.set_label("Launch") | |
ind.set_status(appindicator.STATUS_ACTIVE) | |
appmenu = build_menu() | |
ind.set_menu(appmenu) | |
gtk.main() |
Doesn't currently support importing nested menus from sshmenu configuration.
Can you please update it for Ubuntu 11.10?
It doesn't show an icon in the notification area and it core dumps on refresh.
Thanks for youe effort.
It's working for me on Ubuntu 11.10 but using Gnome Shell, not Unity (so it's not the same notification area). Have you tried the lastest version from Anil's github repository (github.com/anilgulecha/misc)?
Yes, the latest version from Anil is working,
Thanks.
Link update: https://github.com/anilgulecha/misc
works on ubuntu 16.04
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Copy of SSHplus from Anil Gulecha, modified to support some very basic menu nesting.