[mcclim-cvs] CVS mcclim/Drei

thenriksen thenriksen at common-lisp.net
Fri Dec 28 10:08:50 UTC 2007


Update of /project/mcclim/cvsroot/mcclim/Drei
In directory clnet:/tmp/cvs-serv2026/Drei

Modified Files:
	drei.lisp packages.lisp syntax.lisp views.lisp 
Added Files:
	modes.lisp 
Log Message:
Added support for "modes" (roughly similar to Emacs' minor-modes) to Drei.


--- /project/mcclim/cvsroot/mcclim/Drei/drei.lisp	2007/12/25 06:46:21	1.23
+++ /project/mcclim/cvsroot/mcclim/Drei/drei.lisp	2007/12/28 10:08:28	1.24
@@ -219,7 +219,7 @@
 ;;;
 ;;; The basic Drei class.
 
-(defclass drei ()
+(defclass drei (modual-mixin)
   ((%view :initform (make-instance 'textual-drei-syntax-view)
           :initarg :view
           :accessor view
@@ -288,6 +288,25 @@
 (defmethod (setf active) (new-val (drei drei))
   (setf (active (view drei)) new-val))
 
+(defmethod available-modes append ((modual drei))
+  (available-modes (view modual)))
+
+(defmethod mode-applicable-p or ((modual drei) mode-name)
+  (mode-applicable-p (view modual) mode-name))
+
+(defmethod mode-enabled-p or ((modual drei) mode-name)
+  (mode-enabled-p (view modual) mode-name))
+
+(defmethod enable-mode ((modual drei) mode-name &rest initargs)
+  (if (mode-applicable-p (view modual) mode-name)
+      (apply #'enable-mode (view modual) mode-name initargs)
+      (call-next-method)))
+
+(defmethod disable-mode ((modual drei) mode-name)
+  (if (mode-applicable-p (view modual) mode-name)
+      (disable-mode (view modual) mode-name)
+      (call-next-method)))
+
 (defun add-view-cursors (drei)
   "Add the cursors desired by the Drei view to the editor-pane of
 the Drei instance."
--- /project/mcclim/cvsroot/mcclim/Drei/packages.lisp	2007/12/27 15:22:54	1.26
+++ /project/mcclim/cvsroot/mcclim/Drei/packages.lisp	2007/12/28 10:08:33	1.27
@@ -138,7 +138,8 @@
 
 (defpackage :drei-syntax
   (:use :clim-lisp :clim :drei-buffer :drei-base :flexichain :esa-utils)
-  (:export #:syntax #:update-parse #:syntaxp #:define-syntax #:*default-syntax* #:cursor-positions
+  (:export #:syntax #:syntax-command-tables #:update-parse #:syntaxp
+           #:define-syntax #:*default-syntax* #:cursor-positions
            #:syntax-command-table #:additional-command-tables #:define-syntax-command-table
            #:eval-option
            #:define-option-for-syntax
@@ -277,7 +278,12 @@
            #:*foreground-color*
            #:*background-color*
            #:*show-mark*
-           #:*use-tabs-for-indentation*))
+           #:*use-tabs-for-indentation*
+
+           #:view-mode #:syntax-mode
+           #:applicable-modes
+           #:define-mode #:define-view-mode #:define-syntax-mode
+           #:define-mode-toggle-commands))
 
 (defpackage :drei-motion
   (:use :clim-lisp :drei-base :drei-buffer :drei-syntax)
--- /project/mcclim/cvsroot/mcclim/Drei/syntax.lisp	2007/12/10 21:25:12	1.8
+++ /project/mcclim/cvsroot/mcclim/Drei/syntax.lisp	2007/12/28 10:08:34	1.9
@@ -22,7 +22,7 @@
 
 (in-package :drei-syntax)
 
-(defclass syntax (name-mixin)
+(defclass syntax (name-mixin modual-mixin)
   ((%buffer :initarg :buffer :reader buffer)
    (%command-table :initarg :command-table
                    :initform (error "A command table has not been provided for this syntax")
@@ -32,6 +32,13 @@
                  :accessor updater-fns))
   (:documentation "The base class for all syntaxes."))
 
+(defgeneric syntax-command-tables (syntax)
+  (:documentation "Returns additional command tables provided by
+`syntax'.")
+  (:method-combination append)
+  (:method append ((syntax syntax))
+           (list (command-table syntax))))
+
 (defun syntaxp (object)
   "Return T if `object' is an instance of a syntax, NIL
   otherwise."
--- /project/mcclim/cvsroot/mcclim/Drei/views.lisp	2007/12/19 17:17:37	1.7
+++ /project/mcclim/cvsroot/mcclim/Drei/views.lisp	2007/12/28 10:08:35	1.8
@@ -403,7 +403,7 @@
 ;;;
 ;;; View classes.
 
-(defclass drei-view (tabify-mixin subscriptable-name-mixin)
+(defclass drei-view (tabify-mixin subscriptable-name-mixin modual-mixin)
   ((%active :accessor active
             :initform t
             :initarg :active
@@ -445,6 +445,12 @@
   (print-unreadable-object (view stream :type t :identity t)
     (format stream "name: ~a ~a" (name view) (subscript view))))
 
+(defmethod available-modes append ((modual drei-view))
+  *global-modes*)
+
+(defmethod mode-applicable-p or ((modual drei-view) mode-name)
+  (mode-applicable-p (syntax modual) mode-name))
+
 (defgeneric synchronize-view (view &key &allow-other-keys)
   (:documentation "Synchronize the view with the object under
 observation - what exactly this entails, and what keyword
@@ -583,6 +589,19 @@
         (buffer-size view) (size (buffer view)))
   (synchronize-view view :force-p t))
 
+(defmethod mode-enabled-p or ((modual drei-syntax-view) mode-name)
+  (mode-enabled-p (syntax modual) mode-name))
+
+(defmethod enable-mode ((modual drei-syntax-view) mode-name &rest initargs)
+  (if (mode-applicable-p (syntax modual) mode-name)
+      (apply #'enable-mode (syntax modual) mode-name initargs)
+      (call-next-method)))
+
+(defmethod disable-mode ((modual drei-syntax-view) mode-name)
+  (if (mode-applicable-p (syntax modual) mode-name)
+      (disable-mode (syntax modual) mode-name)
+      (call-next-method)))
+
 (defmethod observer-notified ((view drei-syntax-view) (buffer drei-buffer)
                               changed-region)
   (with-accessors ((prefix-size prefix-size)
@@ -668,7 +687,7 @@
           (make-instance 'mark-cursor :view view :output-stream output-stream))))
 
 (defmethod view-command-tables append ((view textual-drei-syntax-view))
-  (list (command-table (syntax view))))
+  (syntax-command-tables (syntax view)))
 
 (defmethod use-editor-commands-p ((view textual-drei-syntax-view))
   t)

--- /project/mcclim/cvsroot/mcclim/Drei/modes.lisp	2007/12/28 10:08:50	NONE
+++ /project/mcclim/cvsroot/mcclim/Drei/modes.lisp	2007/12/28 10:08:50	1.1
;;; -*- Mode: Lisp; Package: DREI -*-

;;;  (c) copyright 2007-2008 by
;;;           Troels Henriksen (athas at sigkill.dk)

;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Library General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Library General Public License for more details.
;;;
;;; You should have received a copy of the GNU Library General Public
;;; License along with this library; if not, write to the
;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;;; Boston, MA  02111-1307  USA.
;;;
;;; This file contains the implementation of the infrastructure for
;;; Drei "modes", loosely equivalent to Emacs minor modes. They modify
;;; aspects of the behavior of a view or syntax.

(in-package :drei)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The general mode protocol and macros.

(defvar *global-modes* '()
  "A list of the names of modes globally available to Drei
instances. Do not use this list to retrieve modes, use the
function `available-modes' instead. The modes on this list are
available to all Drei variants.")

(defun applicable-modes (drei)
  "Return a list of the names of all modes applicable for
`drei'."
  (remove-if-not #'(lambda (mode)
                     (mode-applicable-p (view drei) mode))
                 (available-modes drei)))

(defclass view-mode (mode)
  ()
  (:documentation "The superclass for all view modes."))

(defclass syntax-mode (mode)
  ()
  (:documentation "The superclass for all syntax modes."))

(defmacro define-mode (name (&rest superclasses)
                       (&rest slot-specs)
                       &rest options)
  "Define a toggable Drei mode. It is essentially a class, with
the provided `name', `superclasses', `slot-specs' and
`options'. It will automatically be a subclass of `mode'. Apart
from the normal class options, `options' can also have a
`:global' option, which when true signifies that the mode is
globally available to all Drei instances. This option is true by
default. Note that modes created via this macro are not
applicable to anything."
  (let ((global t)
        (actual-options '()))
    (dolist (option options)
      (case (first option)
        (:global (setf global (second option)))
        (t (push option actual-options))))
   `(progn
      (defclass ,name (, at superclasses mode)
        (, at slot-specs)
        , at actual-options)
      (defmethod enabled-modes append ((modual ,name))
        '(,name))
      ,(when global `(push ',name *global-modes*)))))

(defmacro define-view-mode (name (&rest superclasses)
                            (&rest slot-specs)
                            &rest options)
  "Define a mode (as `define-mode') that is applicable to
views. Apart from taking the same options as `define-mode', it
also takes an `:applicable-views' option (nil by default) that is
a list of views the mode should be applicable to. Multiple uses
of this option are cumulative."
  (let ((applicable-views '())
        (actual-options '()))
    (dolist (option options)
      (case (first option)
        (:applicable-views (setf applicable-views
                                 (append applicable-views
                                         (rest option))))
        (t (push option actual-options))))
   `(progn
      (define-mode ,name (, at superclasses view-mode)
        (, at slot-specs)
        , at actual-options)
      ,@(loop for view in applicable-views
           collecting `(defmethod mode-directly-applicable-p or
                           ((view ,view) (mode-name (eql ',name)))
                         t)))))

(defmacro define-syntax-mode (name (&rest superclasses)
                              (&rest slot-specs)
                              &rest options)
  "Define a mode (as `define-mode') that is applicable to
syntaxes. Apart from taking the same options as `define-mode', it
also takes an `:applicable-syntaxes' option (nil by default) that
is a list of syntaxes the mode should be applicable to. Multiple
uses of this option are cumulative."
  (let ((applicable-syntaxes '())
        (actual-options '()))
    (dolist (option options)
      (case (first option)
        (:applicable-syntaxes (setf applicable-syntaxes
                                    (append applicable-syntaxes
                                            (rest option))))
        (t (push option actual-options))))
    `(progn
       (define-mode ,name (, at superclasses syntax-mode)
         (, at slot-specs)
         , at actual-options)
       ,@(loop for syntax in applicable-syntaxes
            collecting `(defmethod mode-directly-applicable-p or
                            ((syntax ,syntax) (mode-name (eql ',name)))
                          t)))))

(defmacro define-mode-toggle-commands (command-name
                                       (mode-name &optional (string-form (capitalize (string mode-name))))
                                       &key (name t) command-table)
  "Define a simple command (named `command-name') for toggling
the mode named by `mode-name' on and off. `String-form' is the
name of the mode that will be put in the docstring, `name' and
`command-table' work as in `define-command'."
  (check-type command-name symbol)
  (check-type mode-name symbol)
  (check-type string-form string)
  `(define-command (,command-name :name ,name :command-table ,command-table)
       ()
     ,(concatenate 'string "Toggle " string-form " mode.")
     (if (mode-enabled-p *drei-instance* ',mode-name)
         (disable-mode *drei-instance* ',mode-name)
         (enable-mode *drei-instance* ',mode-name))))



More information about the Mcclim-cvs mailing list