Commits

Nikolaj Sjujskij committed 2bd16dd

Refactor `inotify_watcher` script mercilessly

  • Participants
  • Parent commits 5a57188

Comments (0)

Files changed (1)

File inotify_watcher.py

 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-''' Inotify watcher '''
+'''
+Inotify watcher
+***************
+
+Quite simple script to watch file events via Linux kernel ``inotify`` subsystem
+and take user-defined actions upon them.
+
+ © 2010-2012 Nikolaj Sjujskij
+Distributed under the terms of the GNU General Public License v3
+'''
 
 from optparse import OptionParser, OptionGroup
-import inotifyx, logging, os, subprocess, sys
-from time import sleep
 
+import inotifyx
 from pygments import highlight
-from pygments.lexers import guess_lexer, guess_lexer_for_filename, CppLexer
+from pygments.lexers import guess_lexer, guess_lexer_for_filename
 from pygments.formatters import TerminalFormatter
 
-LOG_FILE = '/tmp/inotify_viewer.log'
+implemented_actions = {}
 
-def inotify_watch(wfile, debug=False, log=LOG_FILE):
+def register_action(name=None, catalogue=implemented_actions):
+    ''' Registration decorator, maintaining dictionary of implemented actions'''
+    name = name or f.__name__
+    def register_closure(f):
+        catalogue[name] = f
+        def tmp(*args, **kwargs):
+            return f(*args, **kwargs)
+        return tmp
+    return register_closure
 
-    if debug:
-        logging.basicConfig(filename=log, level=logging.DEBUG)
+@register_action('hlite')
+def highlight_watched(filename):
+    ''' File contents highlighter '''
+    with open(filename, 'r') as file_to_read:
+        content = file_to_read.read()
+    content = highlight(content,
+                        guess_lexer_for_filename(filename, ""),
+                        TerminalFormatter(bg='dark'))
+    print(content)
 
-    # Initting inotifyx
+@register_action('rsthtml')
+def view_rst_as_html(filename):
+    ''' Function converting reStructuredText to HTML for display in browser '''
+    pass
+
+def ino_watch(file_to_watch, action, action_args=[], action_kwargs={}):
+    ''' ``inotify``-based watcher, applying function on modification events '''
     watcher = inotifyx.init()
-
-    inotifyx.add_watch(watcher, wfile, inotifyx.IN_MODIFY)
-
-    try:
-        logging.debug('Starting infinite loop…\n')
-        while True:
-            logging.debug('Starting iteration…\n')
-
-            # it's possible to get output text somehow differently... some day
-            with open(wfile, 'r') as file_to_read:
-                string = file_to_read.read()
-
-            # probably it'd be optional
-            string = highlight(string,
-                               guess_lexer_for_filename(wfile, ""),
-                               TerminalFormatter(bg='dark'))
-
-            # all right, may be even output should be optional!
-            logging.debug('Spawning less…\n')
-            less = subprocess.Popen(['less', '-'],
-                                    stdin=subprocess.PIPE)
-            logging.debug('less spawned, piping data…\n')
-            less.stdin.write(string)
-            less.stdin = sys.stdin
-
-            logging.debug('Data piped, waiting for inotification…\n')
-            inotifyx.get_events(watcher)
-            logging.debug('Inotified, killing less\n')
-            less.terminate()
-            logging.debug('_______________________\n')
-
-
-    except KeyboardInterrupt:
-        logging.debug('Interruption caught, closing everything\n')
-        less.terminate()
-        os.close(watcher)
-
+    inotifyx.add_watch(watcher, file_to_watch, inotifyx.IN_MODIFY)
+    while True:
+        action(*action_args, **action_kwargs)
+        inotifyx.get_events(watcher)
 
 def main():
-    ''' Main function. Parses arguments and passes them ... '''
-
+    ''' Mainloop function handling arguments and control flow '''
     usage = '''Usage: %prog [options] file_to_watch'''
     opt_parser = OptionParser(usage=usage)
+    opt_parser.add_option("-a", "--action", dest="action",
+                      help="action to be undertaken",
+                      metavar="ACTION", default='hlite')
+    (options, args) = opt_parser.parse_args()
+    if len(args) > 1:
+        print("How should I know what to watch from this list?\n"
+              "Watching only first one, '%s'" % args[0])
+        sleep(7)
+    file_to_watch = args[0]
+    action = implemented_actions.get(options.action)
+    if not action:
+        import sys
+        sys.stderr.write("Unknown action: '%s'\n" % options.action)
+        sys.exit(1)
+    try:
+        ino_watch(file_to_watch, action, [file_to_watch])
+    except KeyboardInterrupt:
+        print('\nCaught keyboard interrupt, exiting')
 
-    log_group = OptionGroup(opt_parser, "Debugging options")
-    log_group.add_option("-d", "--debug", action="store_false", default=True,
-                      help="log debug messages (see '--log')", dest="debug")
-    log_group.add_option("-l", "--log", dest="log",
-                      help="log debug ouput to LOG_FILE file (see '--debug')",
-                      metavar="LOG_FILE", default=LOG_FILE)
+if __name__ == "__main__":
+    main()
 
-#    watch_group = OptionGroup(opt_parser, "General options")
-#    watch_group.add_option("--watch-file", dest="watch_file",
-#                        metavar='FILE', help="file to watch")
-
-    opt_parser.add_option_group(log_group)
-#    opt_parser.add_option_group(watch_group)
-
-    (options, args) = opt_parser.parse_args()
-
-    if options.log and not options.debug:
-        opt_parser.error("there's no sense in specifying logfile without debug mode (see --help)")
-    if options.debug and not options.log:
-        print "Log file for debug mode not specified, using default", LOG_FILE
-        sleep(7)
-
-    if len(args) > 1:
-        print "How should I know what to watch from this list?"
-        print "Watching only first one, '{first}'".format(first=args[0])
-        sleep(7)
-
-    inotify_watch(wfile=args[0], debug=options.debug, log=options.log)
-
-
-if __name__=="__main__":
-    # If run directly
-    main()