Created
January 6, 2013 03:51
Revisions
-
HarHar created this gist
Jan 6, 2013 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,375 @@ # -*- coding: utf-8 -*- # ============================================================================= # shell.py (c) March 2006, 2009 by Kolter <[email protected]> # # Licence : GPL v2 # Description : running shell commands in WeeChat # Syntax : try /help shell to get some help on this script # Precond : needs weechat >= 0.3.0 to run # # # ### changelog ### # # * version 0.7, 2012-11-26, Sebastien Helleu <[email protected]>: # - use hashtable for command arguments (for WeeChat >= 0.4.0) # * version 0.6, 2012-11-21, Sebastien Helleu <[email protected]>: # - call shell in hook_process (WeeChat >= 0.3.9.2 does not call shell any more) # * version 0.5, 2011-10-01, Sebastien Helleu <[email protected]>: # - add shell buffer # * version 0.4, 2009-05-02, Sebastien Helleu <[email protected]>: # - sync with last API changes # * version 0.3, 2009-03-06, Sebastien Helleu <[email protected]>: # - use of hook_process to run background process # - add option -t <timeout> to kill process after <timeout> seconds # - show process running, kill it with -kill # * version 0.2, 2009-01-31, Sebastien Helleu <[email protected]>: # - conversion to WeeChat 0.3.0+ # * version 0.1, 2006-03-13, Kolter <[email protected]>: # - first release # # ============================================================================= import weechat, os, datetime SCRIPT_NAME = 'shell' SCRIPT_AUTHOR = 'Kolter' SCRIPT_VERSION = '0.7' SCRIPT_LICENSE = 'GPL2' SCRIPT_DESC = 'Run shell commands in WeeChat' SHELL_CMD = 'shell' SHELL_PREFIX = '[shell] ' cmd_hook_process = '' cmd_command = '' cmd_start_time = None cmd_buffer = '' cmd_shell_buffer = '' cmd_stdout = '' cmd_stderr = '' cmd_send_to_buffer = '' cmd_timeout = 0 if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''): weechat.hook_command( SHELL_CMD, 'Running shell commands in WeeChat', '[-o|-n] [-t seconds] <command> || -show || -kill', ' -o: send output to current buffer (simulate user entry ' 'with command output - dangerous, be careful when using this option)\n' ' -n: display output in a new empty buffer\n' '-t seconds: auto-kill process after timeout (seconds) if process ' 'is still running\n' ' command: shell command or builtin like cd, getenv, setenv, unsetenv\n' ' -show: show running process\n' ' -kill: kill running process', '-o|-n|-t|cd|getenv|setenv|unsetenv|-show||-kill -o|-n|-t|cd|getenv|setenv|unsetenv', 'shell_cmd', '') import webcolors def closest_colour(requested_colour): min_colours = {} for key, name in webcolors.css3_hex_to_names.items(): r_c, g_c, b_c = webcolors.hex_to_rgb(key) rd = (r_c - requested_colour[0]) ** 2 gd = (g_c - requested_colour[1]) ** 2 bd = (b_c - requested_colour[2]) ** 2 min_colours[(rd + gd + bd)] = name return min_colours[min(min_colours.keys())] def get_colour_name(requested_colour): try: closest_name = actual_name = webcolors.rgb_to_name(requested_colour) except ValueError: closest_name = closest_colour(requested_colour) actual_name = None return actual_name, closest_name def shell_init(): """Initialize some variables.""" global cmd_hook_process, cmd_command, cmd_start_time, cmd_buffer, cmd_stdout, cmd_stderr cmd_hook_process = '' cmd_command = '' cmd_start_time = None cmd_buffer = '' cmd_stdout = '' cmd_stderr = '' def shell_set_title(): """Set title on shell buffer (with working directory).""" global cmd_shell_buffer if cmd_shell_buffer: weechat.buffer_set(cmd_shell_buffer, 'title', '%s.py %s | "q": close buffer | Working dir: %s' % (SCRIPT_NAME, SCRIPT_VERSION, os.getcwd())) def shell_process_cb(data, command, rc, stdout, stderr): """Callback for hook_process().""" global cmd_hook_process, cmd_buffer, cmd_stdout, cmd_stderr, cmd_send_to_buffer cmd_stdout += stdout cmd_stderr += stderr if int(rc) >= 0: if cmd_stdout: lines = cmd_stdout out = '' a = False l = 0 r, g, b = '', '', '' for c in lines: if a == False: if c == '\x1b': a = True l = 0 continue out += c else: if c == ';': l += 1; continue if c == 'm': l = 0 a = False if r == '': r = '0' if g == '': g = '0' if b == '': b = '0' t1, t2 = get_colour_name((int(r), int(g), int(b))) if t1 != None: cn = t1 elif t2 != None: cn = t2 else: continue colortable = {'white': '0', 'aqua': '11', 'black': '1', 'blue': '2', 'midnightblue': '2', 'yellow': '8', 'orange': '7', 'purple': '6', 'green': '3', 'lime': '9', 'red': '4', 'brown': '5', 'maroon': '5', 'royal': '12', 'deeppink': '13', 'pink': '13', 'fuchsia': '13'} if cn in colortable: out += chr(3) + colortable[cn] continue elif cn.strip('light') in colortable: out += chr(3) + colortable[cn.strip('light')] continue elif cn.strip('dark') in colortable: out += chr(3) + colortable[cn.strip('dark')] continue elif cn.strip('deep') in colortable: out += chr(3) + colortable[cn.strip('deep')] continue else: out += '{' + cn + '}' continue if l == 1: r += c elif l == 2: g += c elif l == 3: b += c lines = out.split('\n') if cmd_send_to_buffer == 'current': for line in lines: if line: weechat.command(cmd_buffer, '%s' % line) else: if cmd_send_to_buffer != 'new': weechat.prnt(cmd_buffer, '%sCommand "%s" (rc %d), stdout:' % (SHELL_PREFIX, data, int(rc))) for line in lines: if line: weechat.prnt(cmd_buffer, ' \t%s' % line) if cmd_stderr: lines = cmd_stderr.split('\n') if cmd_send_to_buffer == 'current': for line in lines: if line: weechat.command(cmd_buffer, '%s' % line) else: if cmd_send_to_buffer != 'new': weechat.prnt(cmd_buffer, '%s%sCommand "%s" (rc %d), stderr:' % (weechat.prefix('error'), SHELL_PREFIX, data, int(rc))) for line in lines: if line: weechat.prnt(cmd_buffer, '%s%s' % (weechat.prefix('error'), line)) cmd_hook_process = '' shell_set_title() return weechat.WEECHAT_RC_OK def shell_show_process(buffer): """Show running process.""" global cmd_command, cmd_start_time if cmd_hook_process: weechat.prnt(buffer, '%sprocess running: "%s" (started on %s)' % (SHELL_PREFIX, cmd_command, cmd_start_time.ctime())) else: weechat.prnt(buffer, '%sno process running' % SHELL_PREFIX) def shell_kill_process(buffer): """Kill running process.""" global cmd_hook_process, cmd_command if cmd_hook_process: weechat.unhook(cmd_hook_process) weechat.prnt(buffer, '%sprocess killed (command "%s")' % (SHELL_PREFIX, cmd_command)) shell_init() else: weechat.prnt(buffer, '%sno process running' % SHELL_PREFIX) def shell_chdir(buffer, directory): """Change working directory.""" if not directory: if os.environ.has_key('HOME'): directory = os.environ['HOME'] try: os.chdir(directory) except: weechat.prnt(buffer, '%san error occured while running command "cd %s"' % (SHELL_PREFIX, directory)) else: weechat.prnt(buffer, '%schdir to "%s" ok, new path: %s' % (SHELL_PREFIX, directory, os.getcwd())) shell_set_title() def shell_getenv(buffer, var): """Get environment variable.""" global cmd_send_to_buffer var = var.strip() if not var: weechat.prnt(buffer, '%swrong syntax, try "getenv VAR"' % (SHELL_PREFIX)) return value = os.getenv(var) if value == None: weechat.prnt(buffer, '%s$%s is not set' % (SHELL_PREFIX, var)) else: if cmd_send_to_buffer == 'current': weechat.command(buffer, '$%s=%s' % (var, os.getenv(var))) else: weechat.prnt(buffer, '%s$%s=%s' % (SHELL_PREFIX, var, os.getenv(var))) def shell_setenv(buffer, expr): """Set an environment variable.""" global cmd_send_to_buffer expr = expr.strip() lexpr = expr.split('=') if (len(lexpr) < 2): weechat.prnt(buffer, '%swrong syntax, try "setenv VAR=VALUE"' % (SHELL_PREFIX)) return os.environ[lexpr[0].strip()] = '='.join(lexpr[1:]) if cmd_send_to_buffer != 'current': weechat.prnt(buffer, '%s$%s is now set to "%s"' % (SHELL_PREFIX, lexpr[0], '='.join(lexpr[1:]))) def shell_unsetenv(buffer, var): """Remove environment variable.""" var = var.strip() if not var: weechat.prnt(buffer, '%swrong syntax, try "unsetenv VAR"' % (SHELL_PREFIX)) return if os.environ.has_key(var): del os.environ[var] weechat.prnt(buffer, '%s$%s is now unset' % (SHELL_PREFIX, var)) else: weechat.prnt(buffer, '%s$%s is not set' % (SHELL_PREFIX, var)) def shell_exec(buffer, command): """Execute a command.""" global cmd_hook_process, cmd_command, cmd_start_time, cmd_buffer global cmd_stdout, cmd_stderr, cmd_send_to_buffer, cmd_timeout if cmd_hook_process: weechat.prnt(buffer, '%sanother process is running! (use "/%s -kill" to kill it)' % (SHELL_PREFIX, SHELL_CMD)) return if cmd_send_to_buffer == 'new': weechat.prnt(buffer, '-->\t%s%s$ %s%s' % (weechat.color('chat_buffer'), os.getcwd(), weechat.color('reset'), command)) weechat.prnt(buffer, '') args = command.split(' ') if args[0] == 'cd': shell_chdir(buffer, ' '.join(args[1:])) elif args[0] == 'getenv': shell_getenv (buffer, ' '.join(args[1:])) elif args[0] == 'setenv': shell_setenv (buffer, ' '.join(args[1:])) elif args[0] == 'unsetenv': shell_unsetenv (buffer, ' '.join(args[1:])) else: shell_init() cmd_command = command cmd_start_time = datetime.datetime.now() cmd_buffer = buffer version = weechat.info_get("version_number", "") or 0 if int(version) >= 0x00040000: cmd_hook_process = weechat.hook_process_hashtable('sh', { 'arg1': '-c', 'arg2': command }, cmd_timeout * 1000, 'shell_process_cb', command) else: cmd_hook_process = weechat.hook_process("sh -c '%s'" % command, cmd_timeout * 1000, 'shell_process_cb', command) def shell_input_buffer(data, buffer, input): """Input callback on shell buffer.""" global cmd_send_to_buffer if input in ('q', 'Q'): weechat.buffer_close(buffer) return weechat.WEECHAT_RC_OK cmd_send_to_buffer = 'new' weechat.prnt(buffer, '') command = weechat.string_input_for_buffer(input) shell_exec(buffer, command) return weechat.WEECHAT_RC_OK def shell_close_buffer(data, buffer): """Close callback on shell buffer.""" global cmd_shell_buffer cmd_shell_buffer = '' return weechat.WEECHAT_RC_OK def shell_new_buffer(): """Create shell buffer.""" global cmd_shell_buffer cmd_shell_buffer = weechat.buffer_search('python', 'shell') if not cmd_shell_buffer: cmd_shell_buffer = weechat.buffer_new('shell', 'shell_input_buffer', '', 'shell_close_buffer', '') if cmd_shell_buffer: shell_set_title() weechat.buffer_set(cmd_shell_buffer, 'localvar_set_no_log', '1') weechat.buffer_set(cmd_shell_buffer, 'time_for_each_line', '0') weechat.buffer_set(cmd_shell_buffer, 'input_get_unknown_commands', '1') weechat.buffer_set(cmd_shell_buffer, 'display', '1') return cmd_shell_buffer def shell_cmd(data, buffer, args): """Callback for /shell command.""" global cmd_send_to_buffer, cmd_timeout largs = args.split(' ') # strip spaces while '' in largs: largs.remove('') while ' ' in largs: largs.remove(' ') cmdbuf = buffer if len(largs) == 0: shell_new_buffer() else: if largs[0] == '-show': shell_show_process(cmdbuf) elif largs[0] == '-kill': shell_kill_process(cmdbuf) else: cmd_send_to_buffer = '' cmd_timeout = 0 while largs: if largs[0] == '-o': cmd_send_to_buffer = 'current' largs = largs[1:] continue if largs[0] == '-n': cmd_send_to_buffer = 'new' cmdbuf = shell_new_buffer() largs = largs[1:] continue if largs[0] == '-t' and len(largs) > 2: cmd_timeout = int(largs[1]) largs = largs[2:] continue break if len(largs) > 0: shell_exec(cmdbuf, ' '.join(largs)) return weechat.WEECHAT_RC_OK