Permalink
Browse files

New clipboard helper. Linter cleanup stuff

  • Loading branch information...
focusaurus committed Mar 8, 2012
1 parent 532bd67 commit 0801adbe48fb978e0ec77442dbdb6f4c1cf2ab1a
Showing with 64 additions and 12 deletions.
  1. +22 −6 commander.py
  2. +42 −6 helpers.py
View
@@ -17,7 +17,7 @@
logger = logging.getLogger("commander")
handler = logging.handlers.RotatingFileHandler(
- os.path.expanduser("~/.commander.log"), maxBytes=1024**2, backupCount=5)
+ os.path.expanduser("~/.commander.log"), maxBytes=1024 ** 2, backupCount=5)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
#logger.setLevel(logging.DEBUG)
@@ -26,6 +26,8 @@
commands = {}
reloaders = []
+
+
class Reloader(object):
"""Check whether a file has been modified since the last check"""
@@ -55,8 +57,8 @@ def createWidgets(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
- self.QUIT["fg"] = "red"
- self.QUIT["command"] = self.quit
+ self.QUIT["fg"] = "red"
+ self.QUIT["command"] = self.quit
self.QUIT.pack()
@@ -76,8 +78,9 @@ def add(function, name):
(name, id(commands), commands.keys()))
commands[name] = function
-#decorator function to store command functions in commands map
+
def command(*args, **kwargs):
+ """decorator function to store command functions in commands map"""
alias = kwargs.get("alias")
invoked = bool(not args or kwargs)
if invoked:
@@ -93,6 +96,8 @@ def wrapper(function):
return function
########## Helper Methods ##########
+
+
def siteOpener(URLs):
"Generate a closure function to open a list of URLs in the browser"
#Note: If you rename this function, rename it inside loadSites as well
@@ -104,6 +109,7 @@ def opener(*terms):
helpers.browser(URL)
return opener
+
def loadSites(*args):
if (not os.access(SITE_CONF_PATH, os.R_OK)) or \
(not os.path.isfile(SITE_CONF_PATH)):
@@ -133,6 +139,7 @@ def loadSites(*args):
else:
commands[keyword] = siteOpener(URLs)
+
def loadMyCommands(*args):
logger.info("loading mycommands")
try:
@@ -142,11 +149,12 @@ def loadMyCommands(*args):
path = mycommands.__file__
logger.info("Loaded mycommands from: " + path)
if path.endswith("pyc"):
- path = path[0:-1] #Watch the .py file for change, not the .pyc
+ path = path[0:-1] # Watch the .py file for change, not the .pyc
reloaders.append(Reloader(path))
except ImportError, info:
logger.debug("Could not import mycommands module. %s" % info)
+
def fullReload(command=""):
logger.info("Reloading commander.py")
#This makes sure the current command is not dropped, but
@@ -159,13 +167,14 @@ def fullReload(command=""):
else:
os.execvp(sys.argv[0], args)
+
def interpret(value):
if not value:
#Typing CTRL-D at the prompt generates empty string, which means quit
return quit()
for reloader in reloaders:
if reloader.check():
- fullReload(value) #This will exit the process and re-execute
+ fullReload(value) # This will exit the process and re-execute
value = value.strip()
if not value:
#Empty line, reprompt
@@ -194,22 +203,27 @@ def interpret(value):
else:
unknown(command)
+
def unknown(command):
message = "Unknown command: %s" % command
sys.stderr.write(message + "\n")
logger.debug(message)
+
def wrapped():
output = subprocess.Popen(
["ps", "-p", str(os.getppid()), "-o", "command"],
stdout=subprocess.PIPE).communicate()[0]
return output.count("rlwrap") > 0
########## Command Functions ##########
+
+
@command(alias="q")
def quit():
sys.exit(0)
+
@command
def gui():
root = Tk()
@@ -218,12 +232,14 @@ def gui():
app.mainloop()
root.destroy()
+
@command
def site(*terms):
with open(SITE_CONF_PATH, 'a') as outFile:
outFile.write(" ".join(terms) + "\n")
loadSites()
+
def main():
global command
#Expose our decorator and helpers via the helper module
View
@@ -8,53 +8,65 @@
import urllib2
#These helpers are (currently) OS X specific
+
+
def browser(args):
if type(args) not in (types.ListType, types.TupleType):
args = [args]
#TODO this only works on OS X. Add linux support
- #atWork = True
- atWork = False
browser = ["open"]
- if atWork:
- browser.extend(["-a", "firefox"])
run(browser + args)
-def copyText(text):
- popen = subprocess.Popen("pbcopy", stdin=subprocess.PIPE).communicate(text)
+
+def pbcopy(text):
+ subprocess.Popen("pbcopy", stdin=subprocess.PIPE).communicate(text)
+
+
+def pbpaste():
+ return subprocess.Popen("pbpaste", shell=False,
+ stdout=subprocess.PIPE).stdout.read().strip()
+
def expandPath(path):
return os.path.abspath(os.path.expanduser(path))
+
def expandGlob(path):
return glob.glob(expandPath(path))
+
def maestro(scriptId):
"""Run a Keyboard Maestro script by ID (more robust) or name"""
run("""osascript -e 'tell application "Keyboard Maestro Engine" to """ \
"""do script "%s"'\n""" % scriptId)
+
def search(url, terms):
browser(url % quote(terms))
#END of OS X specific stuff
+
def addProtocol(URL):
if not URL.lower().startswith("http://"):
return "http://" + URL
return URL
+
def run(args):
if type(args) in types.StringTypes:
args = shlex.split(args)
logger.debug("run: %s" % args)
subprocess.call(args)
+
def quote(terms):
if type(terms) in types.StringTypes:
terms = [terms.strip()]
else:
terms = [term.strip() for term in terms]
return urllib2.quote(" ".join(terms))
+
def split(function):
"""Create a decorated function that will get passed pre-split arguments.
@@ -67,9 +79,33 @@ def split(function):
the fully-decorated function is stored in the command map."""
logger.debug("Functon %s will get pre-split arguments" % \
function.__name__)
+
def wrapper(args):
logger.debug("Splitting args to %s: %s" % (function.__name__, args))
return function(shlex.split(args))
#maintain the same name so @command works properly
wrapper.__name__ = function.__name__
return wrapper
+
+
+def clipboard(function):
+ """Create a decorated function that default to clipboard.
+
+ This will wrap your command function such that the if the user did not
+ provide any command line arguments, the contents of the OS clipboard will
+ be used instead.
+
+ CAREFUL if combining this decorator with the @command decorator.
+ @command must come FIRST in the source code (so it is executed last), and
+ the fully-decorated function is stored in the command map."""
+ logger.debug("Functon %s will default to clipboard argument" % \
+ function.__name__)
+
+ def wrapper(args):
+ if not args:
+ args = pbpaste()
+ logger.debug("Using clipboard as args to %s: %s" % (function.__name__, args))
+ return function(args)
+ #maintain the same name so @command works properly
+ wrapper.__name__ = function.__name__
+ return wrapper

0 comments on commit 0801adb

Please sign in to comment.