[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master d1cb93b 241/271: Merge branch 'feature/dispatch' into deve

From: Jackson Ray Hamilton
Subject: [elpa] master d1cb93b 241/271: Merge branch 'feature/dispatch' into develop
Date: Thu, 05 Feb 2015 18:31:36 +0000

branch: master
commit d1cb93b81c7fbb2cb5b57d453edb13aac8496d26
Merge: c947690 cae3b72
Author: Jackson Ray Hamilton <address@hidden>
Commit: Jackson Ray Hamilton <address@hidden>

    Merge branch 'feature/dispatch' into develop
 README.md           |   23 ++++++++-
 context-coloring.el |  127 ++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 106 insertions(+), 44 deletions(-)

diff --git a/README.md b/README.md
index 14f4f1a..af1be13 100644
--- a/README.md
+++ b/README.md
@@ -91,8 +91,9 @@ theme used in the screenshot above).
 ## Extending
-To add support for a new language, write a "scopifier" for it, and add an entry
-to `context-coloring-dispatch-plist`. Then the plugin should handle the rest.
+To add support for a new language, write a "scopifier" for it, and define a new
+coloring dispatch strategy with `context-coloring-define-dispatch`. Then the
+plugin should handle the rest.
 A "scopifier" is a CLI program that reads a buffer's contents from stdin and
 writes a JSON array of numbers to stdout. Every three numbers in the array
@@ -123,6 +124,24 @@ If there is an abstract syntax tree generator for your 
language, you can walk
 the syntax tree, find variables and scopes, and build their positions and 
 into an array like the one above.
+For example, a Ruby scopifier might be defined and implemented like this:
+(context-coloring-define-dispatch 'ruby
+  :modes '(ruby-mode)
+  :executable "ruby"
+  :command "/home/username/scopifier")
+#!/usr/bin/env ruby
+def scopifier(code)
+    # Parse code.
+    # Return an array.
+print scopifier ARGF.read
 [linter]: http://jshint.com/about/
 [flycheck]: http://www.flycheck.org/
 [zenburn]: http://github.com/bbatsov/zenburn-emacs
diff --git a/context-coloring.el b/context-coloring.el
index 2cda3fb..759e303 100644
--- a/context-coloring.el
+++ b/context-coloring.el
@@ -318,26 +318,75 @@ Invokes CALLBACK when complete."
 ;;; Dispatch
-(defvar context-coloring-javascript-scopifier
-  `(:type shell-command
-          :executable "node"
-          :command ,(expand-file-name
-                     "./languages/javascript/binaries/scopifier"
-                     context-coloring-path))
-  "JavaScript scopifier via Node.js.")
-(defvar context-coloring-js2-colorizer
-  `(:type elisp
-          :colorizer context-coloring-js2-colorize)
-  "JavaScript colorizer via `js2-mode'.")
-(defcustom context-coloring-dispatch-plist
-  `(js-mode ,context-coloring-javascript-scopifier
-            js2-mode ,context-coloring-js2-colorizer
-            js3-mode ,context-coloring-javascript-scopifier)
-  "Property list mapping major modes to scopification and
-colorization programs."
-  :group 'context-coloring)
+(defvar context-coloring-dispatch-hash-table (make-hash-table :test 'eq)
+  "Mapping of dispatch strategy names to their corresponding
+  property lists, which contain details about the strategies.")
+(defvar context-coloring-mode-hash-table (make-hash-table :test 'eq)
+  "Mapping of major mode names to dispatch property lists.")
+(defun context-coloring-select-dispatch (mode dispatch)
+  "Use DISPATCH for MODE."
+  (puthash
+   mode
+   (gethash
+    dispatch
+    context-coloring-dispatch-hash-table)
+   context-coloring-mode-hash-table))
+(defun context-coloring-define-dispatch (symbol &rest properties)
+  "Define a new dispatch named SYMBOL with PROPERTIES.
+A \"dispatch\" is a property list describing a strategy for
+coloring a buffer. There are three possible strategies: Parse and
+color in a single function (`:colorizer'), parse in a function
+that returns scope data (`:scopifier'), or parse with a shell
+command that returns scope data (`:command'). In the latter two
+cases, the scope data will be used to automatically color the
+PROPERTIES must include `:modes' and one of `:colorizer',
+`:scopifier' or `:command'.
+`:modes' - List of major modes this dispatch is valid for.
+`:colorizer' - Symbol referring to a function that parses and
+colors the buffer.
+`:scopifier' - Symbol referring to a function that parses the
+buffer a returns a flat vector of start, end and level data.
+`:executable' - Optional name of an executable required by
+`:command' - Shell command to execute with the current buffer
+sent via stdin, and with a flat JSON array of start, end and
+level data returned via stdout."
+  (let ((modes (plist-get properties :modes))
+        (colorizer (plist-get properties :colorizer))
+        (scopifier (plist-get properties :scopifier))
+        (command (plist-get properties :command)))
+    (when (null modes)
+      (error "No mode defined for dispatch"))
+    (when (not (or colorizer
+                   scopifier
+                   command))
+      (error "No colorizer, scopifier or command defined for dispatch"))
+    (puthash symbol properties context-coloring-dispatch-hash-table)
+    (dolist (mode modes)
+      (when (null (gethash mode context-coloring-mode-hash-table))
+        (puthash mode properties context-coloring-mode-hash-table)))))
+(context-coloring-define-dispatch 'javascript-node
+  :modes '(js-mode js3-mode)
+  :executable "node"
+  :command (expand-file-name
+            "./languages/javascript/binaries/scopifier"
+            context-coloring-path))
+(context-coloring-define-dispatch 'javascript-js2
+  :modes '(js2-mode)
+  :colorizer 'context-coloring-js2-colorize)
 (defun context-coloring-dispatch (&optional callback)
   "Determines the optimal track for scopification / colorization
@@ -345,31 +394,25 @@ of the current buffer, then executes it.
 Invokes CALLBACK when complete. It is invoked synchronously for
 elisp tracks, and asynchronously for shell command tracks."
-  (let ((dispatch (plist-get context-coloring-dispatch-plist major-mode)))
+  (let ((dispatch (gethash major-mode context-coloring-mode-hash-table)))
     (if (null dispatch)
         (message "%s" "Context coloring is not available for this major mode"))
-    (let ((type (plist-get dispatch :type)))
+    (let (colorizer
+          scopifier
+          command
+          executable)
-       ((eq type 'elisp)
-        (let ((colorizer (plist-get dispatch :colorizer))
-              (scopifier (plist-get dispatch :scopifier)))
-          (cond
-           (colorizer
-            (funcall colorizer)
-            (if callback (funcall callback)))
-           (scopifier
-            (context-coloring-apply-tokens (funcall scopifier))
-            (if callback (funcall callback)))
-           (t
-            (error "No `:colorizer' nor `:scopifier' specified for dispatch of 
`:type' elisp")))))
-       ((eq type 'shell-command)
-        (let ((executable (plist-get dispatch :executable))
-              (command (plist-get dispatch :command)))
-          (if (null command)
-              (error "No `:command' specified for dispatch of `:type' 
-          (if (and (not (null executable))
-                   (null (executable-find executable)))
-              (message "Executable \"%s\" not found" executable))
+       ((setq colorizer (plist-get dispatch :colorizer))
+        (funcall colorizer)
+        (if callback (funcall callback)))
+       ((setq scopifier (plist-get dispatch :scopifier))
+        (context-coloring-apply-tokens (funcall scopifier))
+        (if callback (funcall callback)))
+       ((setq command (plist-get dispatch :command))
+        (setq executable (plist-get dispatch :executable))
+        (if (and (not (null executable))
+                 (null (executable-find executable)))
+            (message "Executable \"%s\" not found" executable)
           (context-coloring-scopify-shell-command command callback)))))))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]