]> git.rmz.io Git - dotfiles.git/blobdiff - weechat/python/grep.py
weechat: update wee-slack
[dotfiles.git] / weechat / python / grep.py
index 24ab0c4b7cbf8df9e692dc44781296538463c0e6..19415311fa33e57855456e162f10ac240fea86ba 100644 (file)
@@ -53,6 +53,9 @@
 #     It can be used for force or disable background process, using '0' forces to always grep in
 #     background, while using '' (empty string) will disable it.
 #
+#   * plugins.var.python.grep.timeout_secs:
+#     Timeout (in seconds) for background grepping.
+#
 #   * plugins.var.python.grep.default_tail_head:
 #     Config option for define default number of lines returned when using --head or --tail options.
 #     Can be overriden in the command with --number option.
 #
 #   History:
 #
+#   2018-04-10, Sébastien Helleu <flashcode@flashtux.org>
+#   version 0.8.1: fix infolist_time for WeeChat >= 2.2 (WeeChat returns a long
+#                  integer instead of a string)
+#
+#   2017-09-20, mickael9
+#   version 0.8:
+#   * use weechat 1.5+ api for background processing (old method was unsafe and buggy)
+#   * add timeout_secs setting (was previously hardcoded to 5 mins)
+#
 #   2017-07-23, Sébastien Helleu <flashcode@flashtux.org>
 #   version 0.7.8: fix modulo by zero when nick is empty string
 #
 ###
 
 from os import path
-import sys, getopt, time, os, re, tempfile
+import sys, getopt, time, os, re
+
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
 
 try:
     import weechat
@@ -209,20 +226,21 @@ except ImportError:
 
 SCRIPT_NAME    = "grep"
 SCRIPT_AUTHOR  = "Elián Hanisch <lambdae2@gmail.com>"
-SCRIPT_VERSION = "0.7.8"
+SCRIPT_VERSION = "0.8.1"
 SCRIPT_LICENSE = "GPL3"
 SCRIPT_DESC    = "Search in buffers and logs"
 SCRIPT_COMMAND = "grep"
 
 ### Default Settings ###
 settings = {
-'clear_buffer'      : 'off',
-'log_filter'        : '',
-'go_to_buffer'      : 'on',
-'max_lines'         : '4000',
-'show_summary'      : 'on',
-'size_limit'        : '2048',
-'default_tail_head' : '10',
+    'clear_buffer'      : 'off',
+    'log_filter'        : '',
+    'go_to_buffer'      : 'on',
+    'max_lines'         : '4000',
+    'show_summary'      : 'on',
+    'size_limit'        : '2048',
+    'default_tail_head' : '10',
+    'timeout_secs'      : '300',
 }
 
 ### Class definitions ###
@@ -830,6 +848,10 @@ def grep_buffer(buffer, head, tail, after_context, before_context, count, regexp
                 prefix = string_remove_color(infolist_string(infolist, 'prefix'), '')
                 message = string_remove_color(infolist_string(infolist, 'message'), '')
                 date = infolist_time(infolist, 'date')
+                # since WeeChat 2.2, infolist_time returns a long integer
+                # instead of a string
+                if not isinstance(date, str):
+                    date = time.strftime('%F %T', time.localtime(int(date)))
                 return '%s\t%s\t%s' %(date, prefix, message)
         return function
     get_line = make_get_line_funcion()
@@ -943,104 +965,85 @@ def show_matching_lines():
         elif size_limit == '':
             background = False
 
+        regexp = make_regexp(pattern, matchcase)
+
+        global grep_options, log_pairs
+        grep_options = (head, tail, after_context, before_context,
+                        count, regexp, hilight, exact, invert)
+
+        log_pairs = [(strip_home(log), log) for log in search_in_files]
+
         if not background:
             # run grep normally
-            regexp = make_regexp(pattern, matchcase)
-            for log in search_in_files:
-                log_name = strip_home(log)
-                matched_lines[log_name] = grep_file(log, head, tail, after_context, before_context,
-                        count, regexp, hilight, exact, invert)
+            for log_name, log in log_pairs:
+                matched_lines[log_name] = grep_file(log, *grep_options)
             buffer_update()
         else:
-            # we hook a process so grepping runs in background.
-            #debug('on background')
-            global hook_file_grep, script_path, bytecode
-            timeout = 1000*60*5 # 5 min
-
-            quotify = lambda s: '"%s"' %s
-            files_string = ', '.join(map(quotify, search_in_files))
-
-            global tmpFile
-            # we keep the file descriptor as a global var so it isn't deleted until next grep
-            tmpFile = tempfile.NamedTemporaryFile(prefix=SCRIPT_NAME,
-                    dir=weechat.info_get('weechat_dir', ''))
-            cmd = grep_process_cmd %dict(logs=files_string, head=head, pattern=pattern, tail=tail,
-                    hilight=hilight, after_context=after_context, before_context=before_context,
-                    exact=exact, matchcase=matchcase, home_dir=home_dir, script_path=script_path,
-                    count=count, invert=invert, bytecode=bytecode, filename=tmpFile.name,
-                    python=weechat.info_get('python2_bin', '') or 'python')
-
-            #debug(cmd)
-            hook_file_grep = weechat.hook_process(cmd, timeout, 'grep_file_callback', tmpFile.name)
-            global pattern_tmpl
+            global hook_file_grep, grep_stdout, grep_stderr, pattern_tmpl
+            grep_stdout = grep_stderr = ''
+            hook_file_grep = weechat.hook_process(
+                'func:grep_process',
+                get_config_int('timeout_secs') * 1000,
+                'grep_process_cb',
+                ''
+            )
             if hook_file_grep:
-                buffer_create("Searching for '%s' in %s worth of data..." %(pattern_tmpl,
-                    human_readable_size(size)))
+                buffer_create("Searching for '%s' in %s worth of data..." % (
+                    pattern_tmpl,
+                    human_readable_size(size)
+                ))
     else:
         buffer_update()
 
-# defined here for commodity
-grep_process_cmd = """%(python)s -%(bytecode)sc '
-import sys, cPickle, os
-sys.path.append("%(script_path)s") # add WeeChat script dir so we can import grep
-from grep import make_regexp, grep_file, strip_home
-logs = (%(logs)s, )
-try:
-    regexp = make_regexp("%(pattern)s", %(matchcase)s)
-    d = {}
-    for log in logs:
-        log_name = strip_home(log, "%(home_dir)s")
-        lines = grep_file(log, %(head)s, %(tail)s, %(after_context)s, %(before_context)s,
-        %(count)s, regexp, "%(hilight)s", %(exact)s, %(invert)s)
-        d[log_name] = lines
-    fd = open("%(filename)s", "wb")
-    cPickle.dump(d, fd, -1)
-    fd.close()
-except Exception, e:
-    print >> sys.stderr, e'
-"""
+
+def grep_process(*args):
+    result = {}
+    try:
+        global grep_options, log_pairs
+        for log_name, log in log_pairs:
+            result[log_name] = grep_file(log, *grep_options)
+    except Exception, e:
+        result = e
+
+    return pickle.dumps(result)
 
 grep_stdout = grep_stderr = ''
-def grep_file_callback(filename, command, rc, stdout, stderr):
-    global hook_file_grep, grep_stderr,  grep_stdout
-    global matched_lines
-    #debug("rc: %s\nstderr: %s\nstdout: %s" %(rc, repr(stderr), repr(stdout)))
-    if stdout:
-        grep_stdout += stdout
-    if stderr:
-        grep_stderr += stderr
-    if int(rc) >= 0:
-  
-        def set_buffer_error():
-            grep_buffer = buffer_create()
-            title = weechat.buffer_get_string(grep_buffer, 'title')
-            title = title + ' %serror' %color_title
-            weechat.buffer_set(grep_buffer, 'title', title)
+
+def grep_process_cb(data, command, return_code, out, err):
+    global grep_stdout, grep_stderr, matched_lines, hook_file_grep
+
+    grep_stdout += out
+    grep_stderr += err
+
+    def set_buffer_error(message):
+        error(message)
+        grep_buffer = buffer_create()
+        title = weechat.buffer_get_string(grep_buffer, 'title')
+        title = title + ' %serror' % color_title
+        weechat.buffer_set(grep_buffer, 'title', title)
+
+    if return_code == weechat.WEECHAT_HOOK_PROCESS_ERROR:
+        set_buffer_error("Background grep timed out")
+        hook_file_grep = None
+        return WEECHAT_RC_OK
+
+    elif return_code >= 0:
+        hook_file_grep = None
+        if grep_stderr:
+            set_buffer_error(grep_stderr)
+            return WEECHAT_RC_OK
 
         try:
-            if grep_stderr:
-                error(grep_stderr)
-                set_buffer_error()
-            #elif grep_stdout:
-                #debug(grep_stdout)
-            elif path.exists(filename):
-                import cPickle
-                try:
-                    #debug(file)
-                    fd = open(filename, 'rb')
-                    d = cPickle.load(fd)
-                    matched_lines.update(d)
-                    fd.close()
-                except Exception, e:
-                    error(e)
-                    set_buffer_error()
-                else:
-                    buffer_update()
-            global tmpFile
-            tmpFile = None
-        finally:
-            grep_stdout = grep_stderr = ''
-            hook_file_grep = None
+            data = pickle.loads(grep_stdout)
+            if isinstance(data, Exception):
+                raise data
+            matched_lines.update(data)
+        except Exception, e:
+            set_buffer_error(repr(e))
+            return WEECHAT_RC_OK
+        else:
+            buffer_update()
+
     return WEECHAT_RC_OK
 
 def get_grep_file_status():
@@ -1415,18 +1418,18 @@ def cmd_grep_parsing(args):
             tail = n
 
 def cmd_grep_stop(buffer, args):
-    global hook_file_grep, pattern, matched_lines, tmpFile
+    global hook_file_grep, pattern, matched_lines
     if hook_file_grep:
         if args == 'stop':
             weechat.unhook(hook_file_grep)
             hook_file_grep = None
-            s = 'Search for \'%s\' stopped.' %pattern
+
+            s = 'Search for \'%s\' stopped.' % pattern
             say(s, buffer)
             grep_buffer = weechat.buffer_search('python', SCRIPT_NAME)
             if grep_buffer:
                 weechat.buffer_set(grep_buffer, 'title', s)
-            del matched_lines
-            tmpFile = None
+            matched_lines = {}
         else:
             say(get_grep_file_status(), buffer)
         raise Exception