Commits

Mike Hix committed aa11bde

Rewrite checkpoint. Nearly there.

  • Participants
  • Parent commits 00be3ab

Comments (0)

Files changed (11)

+#!/usr/bin/ruby -*- ruby -*-
+
+$LOAD_PATH.unshift 'lib'
+
+begin
+        require 'dock_driver'
+rescue Exception => e
+        $stderr.puts "DockDriver's libraries failed to load: #{e.message}\n\t" +
+                e.backtrace.join( "\n\t" )
+end
 
 require 'rubygems'
 require 'dock_driver'
+require 'trollop'
 
-DockDriver::ShellCommand.run ARGV
+include Signal
+
+extend Loggability
+log_to :dock_driver
+
+opts = Trollop.options do
+    opt :config,
+        "Specify an alternate config file.",
+        :default => DockDriver::USER_CONFIG_FILE.expand_path.to_s
+end
+
+self.log.debug "DockDriver command line options: %p" % [opts]
+
+trap 'INT' do
+    self.log.debug "Recieved SIGINT. Bye."
+    exit 0
+end
+
+trap 'HUP' do
+    self.log.debug "Recieved SIGHUP."
+    DockDriver.reload opts 
+end
+
+DockDriver.run opts

data/example.dock_driver.yml

+---
+dock_driver:
+    command: 'dzen2'
+    template: ''
+dock:
+    items:
+        - name: gronald
+          command: foo --bar baz
+          frequency: 1.5
+        - name: aphrodite
+          command: feeblebeeble -vqnf 42
+          scan: 'Gort: (\d+)'
+          frequency: 3
+logging:
+    __default__: warn (color)
+    dock_driver: debug (color)

lib/dock_driver.rb

 require 'rubygems'
 require 'loggability'
 
-# A namespace for the project.
+require 'dock_driver/constants'    
+require 'dock_driver/mixins'
+
+require 'dock_driver/i3'
+require 'dock_driver/dock'
+require 'dock_driver/dock_item'
+require 'dock_driver/workspace_pager'
+
+# A namespace for the project & singleton for driving the dock.
 module DockDriver
 
-    require 'dock_driver/mixins'
-    require 'dock_driver/constants'
-    require 'dock_driver/i3'
-    require 'dock_driver/dock'
-    require 'dock_driver/dock_item'
-    require 'dock_driver/workspace_pager'
-    require 'dock_driver/shell_command'
-
-    include Constants
+    include Constants,
+        Configurability
     extend Loggability
 
+    config_key :dock_driver
     log_as :dock_driver
 
-    class UserInput < DockItem
+    # The loaded config
+    @config = {}
 
-        extend Loggability
-        log_to :dock_driver
+    # The dock instance for the app.
+    @dock = Dock.new
 
-        def run
-            return if self.running
-            @running = true
+    class << self
+        attr_accessor :config
+        attr_accessor :config_loaded_at
+        attr_accessor :log_file
+        attr_accessor :dock
+    end
 
-            self.log.debug "%s is running." % self.name
-            loop do
-                self.var = gets
-                self.fire
+    ### Configurability API
+    def self::load_config( config_file )
+        self.config = Configurability::Config.load config_file, CONFIG_DEFAULTS
+        self.log.info "Installing config (%p)" % [self.config]
+        self.config.install
+        self.config_loaded_at = Time.now
+        return self.config
+    end
+
+    # Watch the config; initate a reload if it has been touched.
+    def self::run( opts )
+        loop do
+            if self.config_loaded_at.nil? or 
+               self.config_loaded_at < File.mtime( opts[:config] )
+               self.log.debug "The config has been touched."
+               self.reload( opts )
             end
+            sleep 1
         end
+    end
 
+    # Reload the config
+    def self::reload( opts )
+        self.log.debug "Reloading."
+        self.load_config( opts[:config] )
+        self.dock.run
     end
 
 end

lib/dock_driver/constants.rb

-module DockDriver::Constants
 
-    VERSION = '0.2.0'
-    REVISION = %$Revision$
+require 'pathname'
 
+module DockDriver
+    module Constants
+        VERSION = '0.2.0'
+        REVISION = %$Revision$
+        USER_CONFIG_FILE = Pathname( '~/.dock_driver.yml' )
+        CONFIG_DEFAULTS = {}
+    end
+    self.extend Constants
 end

lib/dock_driver/dock.rb

-class DockDriver::Dock
 
-        @@render_lock = Mutex.new
+require 'thread'
+
+module DockDriver
+
+    class Dock
 
         extend Loggability
         log_to :dock_driver
 
-        include Observer
+        include Configurability
 
-        attr_accessor :items
+        config_key :dock
+
+        ### Configurability
+
+        @items = []
+        class << self; attr_accessor :items; end
+
+        CONFIG_DEFAULTS = {
+            :items => []
+        }
+
+        def self::configure( section )
+            if section
+                @items = section[:items] || CONFIG_DEFAULTS[:items]
+            end
+        end
+
         attr_reader :running
+        attr_accessor :threads
+        attr_accessor :render_lock
 
         def initialize
-            @items = []
+            @threads = {}
+            @render_lock = Mutex.new
+            # TODO - start the dock process
         end
 
-        def add_item( p )
-            self.items << p
-            p.add_observer self
-        end
-
+        # Be a good listener. 
         def observe
-            @@render_lock.synchronize do
-                # TODO - output to a process
+            self.render_lock.synchronize do
+                # TODO - output to the dock process
                 puts self.to_s
             end
         end
 
         # TODO can the run/running code be factored out to a module?
         def run
-            return if self.running
-            @running = true
 
-            self.items.inject( [] ) do |threads,poll|
-                threads << Thread.new { poll.run }.run
-                threads
-            end.map( &:join )
+            # If already running, kill and clear out the threads and restart
+            # the dock process
+            if self.running
+                self.log.debug "Restarting the dock."
+                self.threads.values.map( &:kill )
+                self.threads.clear
+                # TODO restart the dock process
+            else
+                self.log.debug "Starting the dock."
+                @running = true
+            end
+
+            self.log.debug "Building items."
+            self.class.items.map do |item_opts|
+                item = DockItem.new( item_opts )
+                item.add_observer self
+                threads[item] = Thread.new { item.run }
+            end
+
+            self.log.debug "Starting threads."
+            self.threads.values.map( &:run )
+
+            self.log.debug "Thread count: %d" % [Thread.list.count]
         end
 
         def to_s
             # TODO - templating engine
             # TODO - cache the template to avoid rendering unnecessarily
-            return items.map( &:to_s ).join( ' ' )
+            return self.threads.keys.map( &:to_s ).join( ' ' )
         end
 
+    end
+
 end

lib/dock_driver/dock_item.rb

-class DockDriver::DockItem
+module DockDriver
+    class DockItem
 
-    extend Loggability
-    log_to :dock_driver
+        extend Loggability
+        log_to :dock_driver
 
-    include Subject
+        include Subject
 
-    attr_accessor :name
-    attr_accessor :var
-    attr_accessor :listeners
-    attr_reader :running
+        attr_accessor :name
+        attr_accessor :frequency
+        attr_accessor :var
 
-    def initialize( name )
-        @name = name
-        @var = 0
+        def initialize( opts = {} )
+            self.log.debug "DockItem constructor options: %p" % [opts]
+            @name = opts['name']
+            @frequency = opts['frequency'] || 1000
+            @var = 0
+        end
+
+        # TODO can the run/running code be factored out to a module?
+        def run
+            self.log.debug "%s is running." % self.name
+            loop do
+                sleep self.frequency
+                self.var += 1
+                self.notify_observers
+            end
+        end
+
+        def to_s
+            # TODO - templating engine
+            # TODO - cache the template to avoid rendering unnecessarily
+            return "%s: %s" % [self.name, self.var]
+        end
+
     end
-
-    # TODO can the run/running code be factored out to a module?
-    def run
-        return if self.running
-        @running = true
-
-        self.log.debug "%s is running." % self.name
-        loop do
-            sleep 1.0 + rand
-            self.var += 1
-            self.notify_observers
-        end
-    end
-
-    def to_s
-        # TODO - templating engine
-        # TODO - cache the template to avoid rendering unnecessarily
-        return "%s: %s" % [self.name, self.var]
-    end
-
 end

lib/dock_driver/i3.rb

+module DockDriver
+    class I3
+    end
+end

lib/dock_driver/mixins.rb

-module DockDriver::Observer
-    def observe
-        raise '%s.observe must be defined.' % self.class.name
+module DockDriver
+
+    # The Listened to.
+    module Subject
+
+        extend Loggability
+        log_to :dock_driver
+
+        def observers
+            return @observers ||= []
+        end
+
+        def add_observer( obj )
+            observers ||= []
+            if obj.respond_to? :observe
+                self.observers << obj
+            else
+                raise "Object must respond to :observe: %p" % [obj]
+            end
+        end
+
+        def notify_observers
+            return unless self.observers
+            self.observers.each do |observer|
+                observer.observe
+            end
+        end
+
     end
-end
-
-module DockDriver::Subject
-
-    extend Loggability
-    log_to :dock_driver
-
-    def observers
-        return @observers ||= []
-    end
-
-    def add_observer( obj )
-        observers ||= []
-        if obj.respond_to? :observe
-            self.observers << obj
-        else
-            raise "Object must respond to :observe: %p" % [obj]
-        end
-    end
-
-    def notify_observers
-        return unless self.observers
-        self.observers.each do |observer|
-            observer.observe
-        end
-    end
-
+    
 end

lib/dock_driver/shell_command.rb

-class DockDriver::ShellCommand
-
-    extend Loggability
-    log_to :dock_driver
-
-    def self::run( args = {} )
-        self.log.debug 'Running.'
-        dock = Dock.new
-
-        self.log.debug 'Adding items.'
-        name = 'a'
-        3.times do
-            dock.add_item DockItem.new name.dup
-            name.next!
-        end
-
-        dock.add_item UserInput.new "User Input"
-
-        self.log.debug 'Running the dock.'
-        dock.run
-    end
-
-end

lib/dock_driver/workspace_pager.rb

-class DockDriver::WorkspacePager
+module DockDriver
+    class DockDriver::WorkspacePager < DockDriver::DockItem
+    end
 end