Bash aliases/functions



I've added functionality to the Shell Commands plugin to include Bash aliases and functions, both optional and off by default in the plugin's preferences. It seems to work...

A patch on the current git master is attached.
diff --git a/kupfer/plugin/commands.py b/kupfer/plugin/commands.py
index c6bde6d..1368038 100644
--- a/kupfer/plugin/commands.py
+++ b/kupfer/plugin/commands.py
@@ -12,6 +12,8 @@ __version__ = ""
 __author__ = "Ulrik Sverdrup <ulrik sverdrup gmail com>"
 
 import os
+import re
+from subprocess import call, check_output
 
 import gobject
 
@@ -21,6 +23,46 @@ from kupfer.obj.fileactions import Execute
 from kupfer import utils, icons
 from kupfer import kupferstring
 from kupfer import pretty
+from kupfer import plugin_support
+
+__kupfer_settings__ = plugin_support.PluginSettings(
+	{
+		"key" : "aliases",
+		"label": _("Include Bash aliases"),
+		"type": bool,
+		"value": False
+	}, {
+		"key" : "functions",
+		"label": _("Include Bash functions"),
+		"type": bool,
+		"value": False
+	}
+)
+
+# commands to load aliases/functions and make them usable
+bash_cmds = ('shopt -s expand_aliases', 'source /etc/bash.bashrc',
+             'source {0}/.bashrc'.format(os.path.expanduser('~')))
+bash_cmds = ';'.join(bash_cmds) + '\n'
+
+# regex to split aliases in 'alias' output by
+aliases_regex = re.compile(r"(?<!\\)'\nalias ")
+
+def get_bash_aliases ():
+    """Get alias names."""
+    aliases = check_output(('bash', '-c', bash_cmds + 'alias'))
+    aliases = re.split(aliases_regex, aliases)
+    # clean up first and last entries
+    aliases[0] = aliases[0][6:]
+    aliases[-1] = aliases[-1][:aliases[-1].rfind('\'')]
+    # return names
+    return [alias[:alias.find('=')] for alias in aliases]
+
+def get_bash_functions ():
+    """Get function names."""
+    cmds = bash_cmds + 'declare -F'
+    fns = check_output(('bash', '-c', cmds)).strip().split('\n')
+    # name is the last word in each line
+    return [fn.split()[-1] for fn in fns]
 
 def finish_command(ctx, acommand, stdout, stderr, post_result=True):
 	"""Show async error if @acommand returns error output & error status.
@@ -181,6 +223,17 @@ class Command (TextLeaf):
 	def get_icon_name(self):
 		return "exec"
 
+class BashCommand (Command):
+	def __init__ (self, exepath, name):
+		TextLeaf.__init__(self, exepath, name)
+
+	def get_description (self):
+		return unicode(self)
+
+	def get_gicon (self):
+		# not a file, so move on to get_icon_name
+		pass
+
 class CommandTextSource (TextSource):
 	"""Yield path and command text items """
 	def __init__(self):
@@ -202,6 +255,14 @@ class CommandTextSource (TextSource):
 		## absolute paths come out here since
 		## os.path.join with two abspaths returns the latter
 		firstword = firstwords[0]
+		# bash aliases/functions: should supercede real commands (you might
+		# have, say, alias ls='ls --color=auto')
+		if (__kupfer_settings__["aliases"] and \
+			firstword in get_bash_aliases()) or \
+		   (__kupfer_settings__["functions"] and \
+		    firstword in get_bash_functions()):
+			cmds = bash_cmds + u" ".join(firstwords)
+			yield BashCommand(u'bash -c "%s"' % cmds, text)
 		# iterate over $PATH directories
 		PATH = os.environ.get("PATH", os.defpath)
 		for execdir in PATH.split(os.pathsep):
@@ -211,5 +272,6 @@ class CommandTextSource (TextSource):
 			if os.access(exepath, os.R_OK|os.X_OK) and os.path.isfile(exepath):
 				yield Command(exepath, text)
 				break
+
 	def get_description(self):
 		return _("Run command-line programs")


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]