Advertisement
BSDG33KCLUB

shell.py (weechat)

May 4th, 2014
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.76 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. # =============================================================================
  3. # shell.py (c) March 2006, 2009 by Kolter <kolter@openics.org>
  4. #
  5. # Licence : GPL v2
  6. # Description : running shell commands in WeeChat
  7. # Syntax : try /help shell to get some help on this script
  8. # Precond : needs weechat >= 0.3.0 to run
  9. #
  10. #
  11. # ### changelog ###
  12. #
  13. # * version 0.8, 2013-07-27, Sebastien Helleu <flashcode@flashtux.org>:
  14. # - don't remove empty lines in output of command
  15. # * version 0.7, 2012-11-26, Sebastien Helleu <flashcode@flashtux.org>:
  16. # - use hashtable for command arguments (for WeeChat >= 0.4.0)
  17. # * version 0.6, 2012-11-21, Sebastien Helleu <flashcode@flashtux.org>:
  18. # - call shell in hook_process (WeeChat >= 0.3.9.2 does not call shell any more)
  19. # * version 0.5, 2011-10-01, Sebastien Helleu <flashcode@flashtux.org>:
  20. # - add shell buffer
  21. # * version 0.4, 2009-05-02, Sebastien Helleu <flashcode@flashtux.org>:
  22. # - sync with last API changes
  23. # * version 0.3, 2009-03-06, Sebastien Helleu <flashcode@flashtux.org>:
  24. # - use of hook_process to run background process
  25. # - add option -t <timeout> to kill process after <timeout> seconds
  26. # - show process running, kill it with -kill
  27. # * version 0.2, 2009-01-31, Sebastien Helleu <flashcode@flashtux.org>:
  28. # - conversion to WeeChat 0.3.0+
  29. # * version 0.1, 2006-03-13, Kolter <kolter@openics.org>:
  30. # - first release
  31. #
  32. # =============================================================================
  33.  
  34. import weechat, os, datetime
  35.  
  36. SCRIPT_NAME = 'shell'
  37. SCRIPT_AUTHOR = 'Kolter'
  38. SCRIPT_VERSION = '0.8'
  39. SCRIPT_LICENSE = 'GPL2'
  40. SCRIPT_DESC = 'Run shell commands in WeeChat'
  41.  
  42. SHELL_CMD = 'shell'
  43. SHELL_PREFIX = '[shell] '
  44.  
  45. cmd_hook_process = ''
  46. cmd_command = ''
  47. cmd_start_time = None
  48. cmd_buffer = ''
  49. cmd_shell_buffer = ''
  50. cmd_stdout = ''
  51. cmd_stderr = ''
  52. cmd_send_to_buffer = ''
  53. cmd_timeout = 0
  54.  
  55. if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
  56. SCRIPT_DESC, '', ''):
  57. weechat.hook_command(
  58. SHELL_CMD,
  59. 'Running shell commands in WeeChat',
  60. '[-o|-n] [-t seconds] <command> || -show || -kill',
  61. ' -o: send output to current buffer (simulate user entry '
  62. 'with command output - dangerous, be careful when using this option)\n'
  63. ' -n: display output in a new empty buffer\n'
  64. '-t seconds: auto-kill process after timeout (seconds) if process '
  65. 'is still running\n'
  66. ' command: shell command or builtin like cd, getenv, setenv, unsetenv\n'
  67. ' -show: show running process\n'
  68. ' -kill: kill running process',
  69. '-o|-n|-t|cd|getenv|setenv|unsetenv|-show||-kill -o|-n|-t|cd|getenv|setenv|unsetenv',
  70. 'shell_cmd', '')
  71.  
  72. def shell_init():
  73. """Initialize some variables."""
  74. global cmd_hook_process, cmd_command, cmd_start_time, cmd_buffer, cmd_stdout, cmd_stderr
  75. cmd_hook_process = ''
  76. cmd_command = ''
  77. cmd_start_time = None
  78. cmd_buffer = ''
  79. cmd_stdout = ''
  80. cmd_stderr = ''
  81.  
  82. def shell_set_title():
  83. """Set title on shell buffer (with working directory)."""
  84. global cmd_shell_buffer
  85. if cmd_shell_buffer:
  86. weechat.buffer_set(cmd_shell_buffer, 'title',
  87. '%s.py %s | "q": close buffer | Working dir: %s' % (SCRIPT_NAME, SCRIPT_VERSION, os.getcwd()))
  88.  
  89. def shell_process_cb(data, command, rc, stdout, stderr):
  90. """Callback for hook_process()."""
  91. global cmd_hook_process, cmd_buffer, cmd_stdout, cmd_stderr, cmd_send_to_buffer
  92. cmd_stdout += stdout
  93. cmd_stderr += stderr
  94. if int(rc) >= 0:
  95. if cmd_stdout:
  96. lines = cmd_stdout.rstrip().split('\n')
  97. if cmd_send_to_buffer == 'current':
  98. for line in lines:
  99. weechat.command(cmd_buffer, '%s' % line)
  100. else:
  101. weechat.prnt(cmd_buffer, '')
  102. if cmd_send_to_buffer != 'new':
  103. weechat.prnt(cmd_buffer, '%sCommand "%s" (rc %d), stdout:'
  104. % (SHELL_PREFIX, data, int(rc)))
  105. for line in lines:
  106. weechat.prnt(cmd_buffer, ' \t%s' % line)
  107. if cmd_stderr:
  108. lines = cmd_stderr.rstrip().split('\n')
  109. if cmd_send_to_buffer == 'current':
  110. for line in lines:
  111. weechat.command(cmd_buffer, '%s' % line)
  112. else:
  113. weechat.prnt(cmd_buffer, '')
  114. if cmd_send_to_buffer != 'new':
  115. weechat.prnt(cmd_buffer, '%s%sCommand "%s" (rc %d), stderr:'
  116. % (weechat.prefix('error'), SHELL_PREFIX, data, int(rc)))
  117. for line in lines:
  118. weechat.prnt(cmd_buffer, '%s%s' % (weechat.prefix('error'), line))
  119. cmd_hook_process = ''
  120. shell_set_title()
  121. return weechat.WEECHAT_RC_OK
  122.  
  123. def shell_show_process(buffer):
  124. """Show running process."""
  125. global cmd_command, cmd_start_time
  126. if cmd_hook_process:
  127. weechat.prnt(buffer, '%sprocess running: "%s" (started on %s)'
  128. % (SHELL_PREFIX, cmd_command, cmd_start_time.ctime()))
  129. else:
  130. weechat.prnt(buffer, '%sno process running' % SHELL_PREFIX)
  131.  
  132. def shell_kill_process(buffer):
  133. """Kill running process."""
  134. global cmd_hook_process, cmd_command
  135. if cmd_hook_process:
  136. weechat.unhook(cmd_hook_process)
  137. weechat.prnt(buffer, '%sprocess killed (command "%s")' % (SHELL_PREFIX, cmd_command))
  138. shell_init()
  139. else:
  140. weechat.prnt(buffer, '%sno process running' % SHELL_PREFIX)
  141.  
  142. def shell_chdir(buffer, directory):
  143. """Change working directory."""
  144. if not directory:
  145. if os.environ.has_key('HOME'):
  146. directory = os.environ['HOME']
  147. try:
  148. os.chdir(directory)
  149. except:
  150. weechat.prnt(buffer, '%san error occured while running command "cd %s"' % (SHELL_PREFIX, directory))
  151. else:
  152. weechat.prnt(buffer, '%schdir to "%s" ok, new path: %s' % (SHELL_PREFIX, directory, os.getcwd()))
  153. shell_set_title()
  154.  
  155. def shell_getenv(buffer, var):
  156. """Get environment variable."""
  157. global cmd_send_to_buffer
  158. var = var.strip()
  159. if not var:
  160. weechat.prnt(buffer, '%swrong syntax, try "getenv VAR"' % (SHELL_PREFIX))
  161. return
  162.  
  163. value = os.getenv(var)
  164. if value == None:
  165. weechat.prnt(buffer, '%s$%s is not set' % (SHELL_PREFIX, var))
  166. else:
  167. if cmd_send_to_buffer == 'current':
  168. weechat.command(buffer, '$%s=%s' % (var, os.getenv(var)))
  169. else:
  170. weechat.prnt(buffer, '%s$%s=%s' % (SHELL_PREFIX, var, os.getenv(var)))
  171.  
  172. def shell_setenv(buffer, expr):
  173. """Set an environment variable."""
  174. global cmd_send_to_buffer
  175. expr = expr.strip()
  176. lexpr = expr.split('=')
  177.  
  178. if (len(lexpr) < 2):
  179. weechat.prnt(buffer, '%swrong syntax, try "setenv VAR=VALUE"' % (SHELL_PREFIX))
  180. return
  181.  
  182. os.environ[lexpr[0].strip()] = '='.join(lexpr[1:])
  183. if cmd_send_to_buffer != 'current':
  184. weechat.prnt(buffer, '%s$%s is now set to "%s"' % (SHELL_PREFIX, lexpr[0], '='.join(lexpr[1:])))
  185.  
  186. def shell_unsetenv(buffer, var):
  187. """Remove environment variable."""
  188. var = var.strip()
  189. if not var:
  190. weechat.prnt(buffer, '%swrong syntax, try "unsetenv VAR"' % (SHELL_PREFIX))
  191. return
  192.  
  193. if os.environ.has_key(var):
  194. del os.environ[var]
  195. weechat.prnt(buffer, '%s$%s is now unset' % (SHELL_PREFIX, var))
  196. else:
  197. weechat.prnt(buffer, '%s$%s is not set' % (SHELL_PREFIX, var))
  198.  
  199. def shell_exec(buffer, command):
  200. """Execute a command."""
  201. global cmd_hook_process, cmd_command, cmd_start_time, cmd_buffer
  202. global cmd_stdout, cmd_stderr, cmd_send_to_buffer, cmd_timeout
  203. if cmd_hook_process:
  204. weechat.prnt(buffer,
  205. '%sanother process is running! (use "/%s -kill" to kill it)'
  206. % (SHELL_PREFIX, SHELL_CMD))
  207. return
  208. if cmd_send_to_buffer == 'new':
  209. weechat.prnt(buffer, '-->\t%s%s$ %s%s'
  210. % (weechat.color('chat_buffer'), os.getcwd(), weechat.color('reset'), command))
  211. weechat.prnt(buffer, '')
  212. args = command.split(' ')
  213. if args[0] == 'cd':
  214. shell_chdir(buffer, ' '.join(args[1:]))
  215. elif args[0] == 'getenv':
  216. shell_getenv (buffer, ' '.join(args[1:]))
  217. elif args[0] == 'setenv':
  218. shell_setenv (buffer, ' '.join(args[1:]))
  219. elif args[0] == 'unsetenv':
  220. shell_unsetenv (buffer, ' '.join(args[1:]))
  221. else:
  222. shell_init()
  223. cmd_command = command
  224. cmd_start_time = datetime.datetime.now()
  225. cmd_buffer = buffer
  226. version = weechat.info_get("version_number", "") or 0
  227. if int(version) >= 0x00040000:
  228. cmd_hook_process = weechat.hook_process_hashtable('sh', { 'arg1': '-c', 'arg2': command },
  229. cmd_timeout * 1000, 'shell_process_cb', command)
  230. else:
  231. cmd_hook_process = weechat.hook_process("sh -c '%s'" % command, cmd_timeout * 1000, 'shell_process_cb', command)
  232.  
  233. def shell_input_buffer(data, buffer, input):
  234. """Input callback on shell buffer."""
  235. global cmd_send_to_buffer
  236. if input in ('q', 'Q'):
  237. weechat.buffer_close(buffer)
  238. return weechat.WEECHAT_RC_OK
  239. cmd_send_to_buffer = 'new'
  240. weechat.prnt(buffer, '')
  241. command = weechat.string_input_for_buffer(input)
  242. shell_exec(buffer, command)
  243. return weechat.WEECHAT_RC_OK
  244.  
  245. def shell_close_buffer(data, buffer):
  246. """Close callback on shell buffer."""
  247. global cmd_shell_buffer
  248. cmd_shell_buffer = ''
  249. return weechat.WEECHAT_RC_OK
  250.  
  251. def shell_new_buffer():
  252. """Create shell buffer."""
  253. global cmd_shell_buffer
  254. cmd_shell_buffer = weechat.buffer_search('python', 'shell')
  255. if not cmd_shell_buffer:
  256. cmd_shell_buffer = weechat.buffer_new('shell', 'shell_input_buffer', '', 'shell_close_buffer', '')
  257. if cmd_shell_buffer:
  258. shell_set_title()
  259. weechat.buffer_set(cmd_shell_buffer, 'localvar_set_no_log', '1')
  260. weechat.buffer_set(cmd_shell_buffer, 'time_for_each_line', '0')
  261. weechat.buffer_set(cmd_shell_buffer, 'input_get_unknown_commands', '1')
  262. weechat.buffer_set(cmd_shell_buffer, 'display', '1')
  263. return cmd_shell_buffer
  264.  
  265. def shell_cmd(data, buffer, args):
  266. """Callback for /shell command."""
  267. global cmd_send_to_buffer, cmd_timeout
  268. largs = args.split(' ')
  269.  
  270. # strip spaces
  271. while '' in largs:
  272. largs.remove('')
  273. while ' ' in largs:
  274. largs.remove(' ')
  275.  
  276. cmdbuf = buffer
  277.  
  278. if len(largs) == 0:
  279. shell_new_buffer()
  280. else:
  281. if largs[0] == '-show':
  282. shell_show_process(cmdbuf)
  283. elif largs[0] == '-kill':
  284. shell_kill_process(cmdbuf)
  285. else:
  286. cmd_send_to_buffer = ''
  287. cmd_timeout = 0
  288. while largs:
  289. if largs[0] == '-o':
  290. cmd_send_to_buffer = 'current'
  291. largs = largs[1:]
  292. continue
  293. if largs[0] == '-n':
  294. cmd_send_to_buffer = 'new'
  295. cmdbuf = shell_new_buffer()
  296. largs = largs[1:]
  297. continue
  298. if largs[0] == '-t' and len(largs) > 2:
  299. cmd_timeout = int(largs[1])
  300. largs = largs[2:]
  301. continue
  302. break
  303. if len(largs) > 0:
  304. shell_exec(cmdbuf, ' '.join(largs))
  305. return weechat.WEECHAT_RC_OK
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement