Changeset - dedff6f56350
[Not reviewed]
0 4 0
Sergey Pashinin - 12 years ago 2014-02-26 00:10:50
sergey@pashinin.com
Use cl-flet instead of dflet
4 files changed with 19 insertions and 19 deletions:
0 comments (0 inline, 0 general)
src/workgroups-functions.el
Show inline comments
 
@@ -224,97 +224,97 @@ in either case."
 
in either case."
 
  (or (wg-buffer-uid buffer) (wg-add-buffer-to-buf-list buffer)))
 

	
 
(defun wg-bufobj-uid-or-add (bufobj)
 
  "If BUFOBJ is a wg-buf, return its uid.
 
If BUFOBJ is a buffer or a buffer name, see `wg-buffer-uid-or-add'."
 
  (cl-etypecase bufobj
 
    (wg-buf (wg-buf-uid bufobj)) ;; possibly also add to `wg-buf-list'
 
    (buffer (wg-buffer-uid-or-add bufobj))
 
    (string (wg-bufobj-uid-or-add (wg-get-buffer bufobj)))))
 

	
 

	
 

	
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;
 
;; Notes on buffer and window properties:
 
;;
 
;; fringes, margins and scroll-bars are properly properties of buffers, but
 
;; their settings can be forced ephemerally in a window with the set-window-foo
 
;; functions.
 
;;
 
;; window-point is a property of a buffer/window pair, but won't set properly
 
;; unless the buffer is current -- i.e. (set-window-buffer some-window
 
;; some-buffer) (set-window-point some-window 0)) won't set some-buffer's point
 
;; in some-window unless some-buffer is also current.
 
;;
 
;; window-start and window-hscroll are properties of buffer/window pairs.
 
;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 

	
 

	
 
(defun wg-window-to-win (window)
 
  "Return the serialization (a wg-win) of Emacs window WINDOW."
 
  (let ((selected (eq window (selected-window))))
 
    (with-selected-window window
 
      (wg-make-win
 
       :edges              (window-edges window)
 
       :point              (wg-window-point window)
 
       :start              (window-start window)
 
       :hscroll            (window-hscroll window)
 
       :selected           selected
 
       :minibuffer-scroll  (eq window minibuffer-scroll-window)
 
       :dedicated          (window-dedicated-p window)
 
       :buf-uid            (wg-buffer-uid-or-add (window-buffer window))))))
 

	
 
(defun wg-window-tree-to-wtree (window-tree)
 
  "Return the serialization (a wg-wtree) of Emacs window tree WINDOW-TREE."
 
  (wg-barf-on-active-minibuffer)
 
  (dflet
 
  (cl-flet
 
      ((inner (w) (if (windowp w) (wg-window-to-win w)
 
                    (wg-dbind (dir edges . wins) w
 
                      (wg-make-wtree
 
                       :dir    dir
 
                       :edges  edges
 
                       :wlist  (mapcar #'inner wins))))))
 
    (let ((w (car window-tree)))
 
      (when (and (windowp w) (window-minibuffer-p w))
 
        (error "Workgroups can't operate on minibuffer-only frames."))
 
      (inner w))))
 

	
 
(defun wg-frame-to-wconfig (&optional frame)
 
  "Return the serialization (a wg-wconfig) of Emacs frame FRAME.
 
FRAME nil defaults to `selected-frame'."
 
  (let* ((frame (or frame (selected-frame)))
 
         (fullscrn (frame-parameter frame 'fullscreen)))
 
    (wg-make-wconfig
 
     :left                  (frame-parameter frame 'left)
 
     :top                   (frame-parameter frame 'top)
 
     :width                 (frame-parameter frame 'width)
 
     :height                (frame-parameter frame 'height)
 
     :parameters            `((fullscreen . ,fullscrn))
 
     :vertical-scroll-bars  (frame-parameter frame 'vertical-scroll-bars)
 
     :scroll-bar-width      (frame-parameter frame 'scroll-bar-width)
 
     :wtree                 (wg-window-tree-to-wtree (window-tree frame))
 
     )))
 

	
 
(defun wg-current-wconfig ()
 
  "Return the current wconfig.
 
If `wg-current-wconfig' is non-nil, return it.  Otherwise return
 
`wg-frame-to-wconfig'."
 
  (or (frame-parameter nil 'wg-current-wconfig)
 
      (wg-frame-to-wconfig)))
 

	
 
(defmacro wg-with-current-wconfig (frame wconfig &rest body)
 
  "Eval BODY with WCONFIG current in FRAME.
 
FRAME nil defaults to `selected-frame'."
 
  (declare (indent 2))
 
  (wg-with-gensyms (frame-sym old-value)
 
    `(let* ((,frame-sym (or ,frame (selected-frame)))
 
            (,old-value (frame-parameter ,frame-sym 'wg-current-wconfig)))
 
       (unwind-protect
 
           (progn
 
             (set-frame-parameter ,frame-sym 'wg-current-wconfig ,wconfig)
 
             ,@body)
 
         (when (frame-live-p ,frame-sym)
 
           (set-frame-parameter ,frame-sym 'wg-current-wconfig ,old-value))))))
 

	
 
@@ -386,222 +386,222 @@ BUFFER or `wg-default-buffer' is visible in the only window."
 
        (list left top
 
              (+ left (wg-step-to (- r1 l1) (- r2 l2) hstep))
 
              (+ top  (wg-step-to (- b1 t1) (- b2 t2) vstep)))))))
 

	
 
(defun wg-w-edge-operation (w edges op)
 
  "Return a copy of W with its edges mapped against EDGES through OP."
 
  (wg-set-edges w (cl-mapcar op (wg-w-edges w) edges)))
 

	
 
(defun wg-first-win (w)
 
  "Return the first actual window in W."
 
  (if (wg-win-p w) w
 
    (wg-first-win (car (wg-wtree-wlist w)))))
 

	
 
(defun wg-last-win (w)
 
  "Return the last actual window in W."
 
  (if (wg-win-p w) w
 
    (wg-last-win (wg-last1 (wg-wtree-wlist w)))))
 

	
 
(defun wg-minify-win (w)
 
  "Set W's edges to the smallest allowable."
 
  (let* ((edges (wg-w-edges w))
 
         (left (car edges))
 
         (top (cadr edges)))
 
    (wg-set-edges w (list left top
 
                          (+ left wg-actual-min-width)
 
                          (+ top  wg-actual-min-height)))))
 

	
 
(defun wg-minified-copy-of-last-win (w)
 
  "Minify a copy of the last actual window in W."
 
  (wg-minify-win (wg-copy-win (wg-last-win w))))
 

	
 
(defun wg-w-size (w &optional height)
 
  "Return the width or height of W, calculated from its edge list."
 
  (wg-with-edges w (l1 t1 r1 b1)
 
    (if height (- b1 t1) (- r1 l1))))
 

	
 
(defun wg-adjust-w-size (w width-fn height-fn &optional new-left new-top)
 
  "Adjust W's width and height with WIDTH-FN and HEIGHT-FN."
 
  (wg-with-edges w (left top right bottom)
 
    (let ((left (or new-left left)) (top (or new-top top)))
 
      (wg-set-edges (wg-copy-w w)
 
                    (list left
 
                          top
 
                          (+ left (funcall width-fn  (- right  left)))
 
                          (+ top  (funcall height-fn (- bottom top))))))))
 

	
 
(defun wg-scale-w-size (w width-scale height-scale)
 
  "Scale W's size by WIDTH-SCALE and HEIGHT-SCALE."
 
  (dflet
 
  (cl-flet
 
      ((wscale (width)  (truncate (* width  width-scale)))
 
       (hscale (height) (truncate (* height height-scale))))
 
    (wg-adjust-w-size w #'wscale #'hscale)))
 

	
 
(defun wg-equal-wtrees (w1 w2)
 
  "Return t when W1 and W2 have equal structure."
 
  (cond ((and (wg-win-p w1) (wg-win-p w2))
 
         (equal (wg-w-edges w1) (wg-w-edges w2)))
 
        ((and (wg-wtree-p w1) (wg-wtree-p w2))
 
         (and (eq (wg-wtree-dir w1) (wg-wtree-dir w2))
 
              (equal (wg-wtree-edges w1) (wg-wtree-edges w2))
 
              (cl-every #'wg-equal-wtrees
 
                     (wg-wtree-wlist w1)
 
                     (wg-wtree-wlist w2))))))
 

	
 
(defun wg-normalize-wtree (wtree)
 
  "Clean up and return a new wtree from WTREE.
 
Recalculate the edge lists of all subwins, and remove subwins
 
outside of WTREE's bounds.  If there's only one element in the
 
new wlist, return it instead of a new wtree."
 
  (if (wg-win-p wtree) wtree
 
    (wg-with-slots wtree ((dir wg-wtree-dir)
 
                          (wlist wg-wtree-wlist))
 
      (wg-with-bounds wtree dir (ls1 hs1 lb1 hb1)
 
        (let* ((min-size (wg-min-size dir))
 
               (max (- hb1 1 min-size))
 
               (lastw (wg-last1 wlist)))
 
          ;;(wg--with-temporary-redefinitions
 
          (dflet
 
          (cl-flet
 
              ((mapwl
 
                (wl)
 
                (wg-dbind (sw . rest) wl
 
                  (cons (wg-normalize-wtree
 
                         (wg-set-bounds
 
                          sw dir ls1 hs1 lb1
 
                          (setq lb1 (if (eq sw lastw) hb1
 
                                      (let ((hb2 (+ lb1 (wg-w-size sw dir))))
 
                                        (if (>= hb2 max) hb1 hb2))))))
 
                        (when (< lb1 max) (mapwl rest))))))
 
            (let ((new (mapwl wlist)))
 
              (if (not (cdr new)) (car new)
 
                (setf (wg-wtree-wlist wtree) new)
 
                wtree))))))))
 

	
 
(defun wg-scale-wtree (wtree wscale hscale)
 
  "Return a copy of WTREE with its dimensions scaled by WSCALE and HSCALE.
 
All WTREE's subwins are scaled as well."
 
  (let ((scaled (wg-scale-w-size wtree wscale hscale)))
 
    (if (wg-win-p wtree) scaled
 
      (wg-asetf (wg-wtree-wlist scaled)
 
                (wg-docar (sw it) (wg-scale-wtree sw wscale hscale)))
 
      scaled)))
 

	
 
(defun wg-scale-wconfigs-wtree (wconfig new-width new-height)
 
  "Scale WCONFIG's wtree with NEW-WIDTH and NEW-HEIGHT.
 
Return a copy WCONFIG's wtree scaled with `wg-scale-wtree' by the
 
ratio or NEW-WIDTH to WCONFIG's width, and NEW-HEIGHT to
 
WCONFIG's height."
 
  (wg-normalize-wtree
 
   (wg-scale-wtree
 
    (wg-wconfig-wtree wconfig)
 
    (/ (float new-width)  (wg-wconfig-width wconfig))
 
    (/ (float new-height) (wg-wconfig-height wconfig)))))
 
;; (wg-wconfig-width (wg-current-wconfig))
 

	
 
(defun wg-resize-frame-scale-wtree (wconfig)
 
  "Set FRAME's size to WCONFIG's, returning a possibly scaled wtree.
 
If the frame size was set correctly, return WCONFIG's wtree
 
unchanged.  If it wasn't, return a copy of WCONFIG's wtree scaled
 
with `wg-scale-wconfigs-wtree' to fit the frame as it exists."
 
  (let ((frame (selected-frame)))
 
    (wg-with-slots wconfig ((wcwidth wg-wconfig-width)
 
                            (wcheight wg-wconfig-height))
 
      (when window-system (set-frame-size frame wcwidth wcheight))
 
      (let ((fwidth  (frame-parameter frame 'width))
 
            (fheight (frame-parameter frame 'height)))
 
        (if (and (= wcwidth fwidth) (= wcheight fheight))
 
            (wg-wconfig-wtree wconfig)
 
          (wg-scale-wconfigs-wtree wconfig fwidth fheight))))))
 

	
 
(defun wg-reverse-wlist (w &optional dir)
 
  "Reverse W's wlist and those of all its sub-wtrees in direction DIR.
 
If DIR is nil, reverse WTREE horizontally.
 
If DIR is 'both, reverse WTREE both horizontally and vertically.
 
Otherwise, reverse WTREE vertically."
 
  (dflet
 
  (cl-flet
 
      ((inner (w) (if (wg-win-p w) w
 
                    (wg-with-slots w ((d1 wg-wtree-dir))
 
                      (wg-make-wtree
 
                       :dir d1
 
                       :edges (wg-wtree-edges w)
 
                       :wlist (let ((wl2 (mapcar #'inner (wg-wtree-wlist w))))
 
                                (if (or (eq dir 'both) (eq dir d1))
 
                                    (nreverse wl2)
 
                                  wl2)))))))
 
    (wg-normalize-wtree (inner w))))
 

	
 
(defun wg-wtree-move-window (wtree offset)
 
  "Offset `selected-window' OFFSET places in WTREE."
 
  (dflet
 
  (cl-flet
 
      ((inner (w) (if (wg-win-p w) w
 
                    (wg-with-slots w ((wlist wg-wtree-wlist))
 
                      (wg-make-wtree
 
                       :dir (wg-wtree-dir w)
 
                       :edges (wg-wtree-edges w)
 
                       :wlist (wg-aif (cl-find t wlist :key 'wg-win-selected)
 
                                  (wg-cyclic-offset-elt it wlist offset)
 
                                (mapcar #'inner wlist)))))))
 
    (wg-normalize-wtree (inner wtree))))
 

	
 
(defun wg-reverse-wconfig (wconfig &optional dir)
 
  "Reverse WCONFIG's wtree's wlist in direction DIR."
 
  (wg-asetf (wg-wconfig-wtree wconfig) (wg-reverse-wlist it dir))
 
  wconfig)
 

	
 
(defun wg-wconfig-move-window (wconfig offset)
 
  "Offset `selected-window' OFFSET places in WCONFIG."
 
  (wg-asetf (wg-wconfig-wtree wconfig) (wg-wtree-move-window it offset))
 
  wconfig)
 

	
 
(defun wg-flatten-wtree (wtree &optional key)
 
  "Return a new list by flattening WTREE.
 
KEY non returns returns a list of WTREE's wins.
 
KEY non-nil returns a list of the results of calling KEY on each win."
 
  (dflet
 
  (cl-flet
 
      ((inner (w) (if (wg-win-p w) (list (if key (funcall key w) w))
 
                    (cl-mapcan 'inner (wg-wtree-wlist w)))))
 
    (inner wtree)))
 

	
 
(defun wg-win-list (wtree)
 
  "Construct and return a list of all wg-wins in WTREE."
 
  (wg-flatten-wtree wtree))
 

	
 

	
 
(require 'workgroups-specialbufs)
 
(require 'workgroups-restore)
 

	
 

	
 
;;; workgroup utils
 

	
 
(defun wg-flag-workgroup-modified (workgroup)
 
  "Set WORKGROUP's and the current session's modified flags."
 
  (when wg-flag-modified
 
    (setf (wg-workgroup-modified workgroup) t)
 
    (setf (wg-session-modified (wg-current-session)) t)))
 

	
 
(defun wg-find-workgroup-by (slotkey value &optional noerror)
 
  "Return the workgroup on which ACCESSOR returns VALUE or error."
 
  (let ((accessor (cl-ecase slotkey
 
                    (:name 'wg-workgroup-name)
 
                    (:uid  'wg-workgroup-uid))))
 
    (or (cl-find value (wg-workgroup-list-or-error noerror) :test 'equal :key accessor)
 
        (unless noerror
 
          (error "No are no workgroups with a %S of %S"
 
                 accessor value)))))
 

	
 
(defun wg-first-workgroup ()
 
  "Return a first workgroup."
 
  (interactive)
 
  (car (wg-workgroup-list-or-error)))
 

	
 
(defun wg-current-workgroup (&optional noerror frame)
 
  "Return the current workgroup in FRAME, or error unless NOERROR."
 
  (or wg-current-workgroup
 
      (wg-aif (frame-parameter frame 'wg-current-workgroup-uid)
 
          (wg-find-workgroup-by :uid it noerror)
 
        (unless noerror (error "No current workgroup in this frame")))))
 

	
 
(defun wg-previous-workgroup (&optional noerror frame)
 
  "Return the previous workgroup in FRAME, or error unless NOERROR."
 
  (wg-aif (frame-parameter frame 'wg-previous-workgroup-uid)
 
      (wg-find-workgroup-by :uid it noerror)
 
    (unless noerror (error "No previous workgroup in this frame"))))
src/workgroups-pickel.el
Show inline comments
 
@@ -92,97 +92,97 @@
 
     (wg-pickelable-or-error (cdr obj)))
 
    (vector
 
     (cl-map nil 'wg-pickelable-or-error obj))
 
    (hash-table
 
     (wg-dohash (key value obj)
 
       (wg-pickelable-or-error key)
 
       (wg-pickelable-or-error value)))))
 

	
 
(defun wg-pickelable-p (obj)
 
  (condition-case err
 
      (progn (wg-pickelable-or-error obj) t)
 
    (wg-pickel-unpickelable-type-error nil)))
 

	
 
(defun wg-pickel-p (obj)
 
  "Return t when OBJ is a pickel, nil otherwise."
 
  (and (consp obj) (eq (car obj) wg-pickel-identifier)))
 

	
 

	
 

	
 
;; accessor functions
 

	
 
(defun wg-pickel-object-serializer (obj)
 
  "Return the object serializer for the `type-of' OBJ."
 
  (or (wg-aget wg-pickel-object-serializers (type-of obj))
 
      (error "Invalid type: %S" (type-of obj))))
 

	
 
(defun wg-pickel-link-serializer (obj)
 
  "Return the link serializer for the `type-of' OBJ."
 
  (wg-aget wg-pickel-link-serializers (type-of obj)))
 

	
 
(defun wg-pickel-object-deserializer (key)
 
  "Return the object deserializer for type key KEY, or error."
 
  (or (wg-aget wg-pickel-object-deserializers key)
 
      (error "Invalid object deserializer key: %S" key)))
 

	
 
(defun wg-pickel-link-deserializer (key)
 
  "Return the link deserializer for type key KEY, or error."
 
  (or (wg-aget wg-pickel-link-deserializers key)
 
      (error "Invalid link deserializer key: %S" key)))
 

	
 

	
 

	
 
;;; bindings
 

	
 
(defun wg-pickel-make-bindings-table (obj)
 
  "Return a table binding unique subobjects of OBJ to ids."
 
  (let ((binds (make-hash-table :test 'eq))
 
        (id -1))
 
    (dflet
 
    (cl-flet
 
     ((inner (obj)
 
           (unless (gethash obj binds)
 
              (puthash obj (cl-incf id) binds)
 
              (cl-case (type-of obj)
 
                (cons
 
                 (inner (car obj))
 
                 (inner (cdr obj)))
 
                (vector
 
                 (dotimes (idx (length obj))
 
                   (inner (aref obj idx))))
 
                (hash-table
 
                 (wg-dohash (key val obj)
 
                   (inner key)
 
                   (inner val)))))))
 
      (inner obj)
 
      binds)))
 

	
 

	
 

	
 
;;; object serialization
 

	
 
(defun wg-pickel-symbol-serializer (symbol)
 
  "Return SYMBOL's serialization."
 
  (cond ((eq symbol t) t)
 
        ((eq symbol nil) nil)
 
        ((intern-soft symbol) symbol)
 
        (t (list 's (symbol-name symbol)))))
 

	
 
(defun wg-pickel-cons-serializer (cons)
 
  "Return CONS's serialization."
 
  (list 'c))
 

	
 
(defun wg-pickel-vector-serializer (vector)
 
  "Return VECTOR's serialization."
 
  (list 'v (length vector)))
 

	
 
(defun wg-pickel-hash-table-serializer (table)
 
  "Return HASH-TABLE's serialization."
 
  (list 'h
 
        (hash-table-test table)
 
        (hash-table-size table)
 
        (hash-table-rehash-size table)
 
        (hash-table-rehash-threshold table)
 
        (hash-table-weakness table)))
 

	
 
(defun wg-pickel-serialize-objects (binds)
 
  "Return a list of serializations of the objects in BINDS."
 
  (let (result)
src/workgroups-specialbufs.el
Show inline comments
 
@@ -68,98 +68,98 @@ Can be restored using \"(eval commands)\"."
 
        (with-current-buffer org-agenda-buffer-name
 
          (let* ((p (or (and (looking-at "\\'") (1- (point))) (point)))
 
                 (series-redo-cmd (get-text-property p 'org-series-redo-cmd)))
 
            (if series-redo-cmd
 
                (get-text-property p 'org-series-redo-cmd)
 
              (get-text-property p 'org-redo-cmd)))))))
 

	
 
(defun wg-run-agenda-cmd (f)
 
  "Run commands F in Agenda buffer.
 
You can get these commands using `wg-get-org-agenda-view-commands'."
 
  (when (and (boundp 'org-agenda-buffer-name)
 
             (fboundp 'org-current-line)
 
             (fboundp 'org-goto-line))
 
    (if (get-buffer org-agenda-buffer-name)
 
        (save-window-excursion
 
          (with-current-buffer org-agenda-buffer-name
 
            (let* ((line (org-current-line)))
 
              (if f (eval f))
 
              (org-goto-line line)))))))
 

	
 
(wg-support 'org-agenda-mode 'org-agenda
 
            '((serialize . (lambda (buffer)
 
                             (wg-get-org-agenda-view-commands)))
 
              (deserialize . (lambda (buffer vars)
 
                               (org-agenda-list)
 
                               (wg-awhen (get-buffer org-agenda-buffer-name)
 
                                 (set-buffer it)
 
                                 (wg-run-agenda-cmd vars))
 
                               ))))
 

	
 
;; eshell
 
(wg-support 'eshell-mode 'esh-mode
 
            '((deserialize . (lambda (buffer vars)
 
                               (prog1 (eshell t)
 
                                 (rename-buffer (wg-buf-name buffer) t))))))
 

	
 
;; term-mode
 
;;
 
;; This should work for `ansi-term's, too, as there doesn't seem to
 
;; be any difference between the two except how the name of the
 
;; buffer is generated.
 
;;
 
(wg-support 'term-mode 'term
 
            `((serialize . ,(lambda (buffer)
 
                              (if (get-buffer-process buffer)
 
                                  (wg-last1 (process-command (get-buffer-process buffer)))
 
                                "/bin/bash")))
 
              (deserialize . ,(lambda (buffer vars)
 
                                (dflet ((term-window-width () 80)
 
                                        (window-height () 24))
 
                                (cl-flet ((term-window-width () 80)
 
                                          (window-height () 24))
 
                                  (prog1 (term vars)
 
                                    (rename-buffer (wg-buf-name buffer) t)))))))
 

	
 
;; Python
 
(wg-support 'inferior-python-mode 'python
 
            `((save . (python-shell-interpreter python-shell-interpreter-args))
 
              (deserialize . ,(lambda (buffer vars)
 
                                (wg-dbind (pythoncmd pythonargs) vars
 
                                  (save-window-excursion
 
                                    (run-python (concat pythoncmd " " pythonargs)))
 
                                  (wg-awhen (get-buffer (process-buffer (python-shell-get-or-create-process)))
 
                                    (set-buffer it)
 
                                    (switch-to-buffer (process-buffer (python-shell-get-or-create-process)))
 
                                    (goto-char (point-max)))
 
                                  )))))
 

	
 
;; Sage shell
 
(wg-support 'inferior-sage-mode 'sage-mode
 
            `((deserialize . ,(lambda (buffer vars)
 
                                (save-window-excursion
 
                                  (if (boundp' sage-command)
 
                                      (run-sage t sage-command t)))
 
                                (if (boundp 'sage-buffer)
 
                                    (wg-awhen (and
 
                                               sage-buffer)
 
                                      (set-buffer it)
 
                                      (switch-to-buffer sage-buffer)
 
                                      (goto-char (point-max))))))))
 

	
 
;; inferior-ess-mode   (ess-inf.el)
 
;; R shell, M-x R
 
(wg-support 'inferior-ess-mode 'ess-inf
 
            `((save . (inferior-ess-program))
 
              (deserialize . ,(lambda (buffer vars)
 
                                (wg-dbind (cmd) vars
 
                                  (let ((ess-ask-about-transfile nil)
 
                                        (ess-ask-for-ess-directory nil)
 
                                        (ess-history-file nil))
 
                                    (R)))))))
 

	
 
;; inferior-octave-mode
 
(wg-support 'inferior-octave-mode 'octave
 
            `((deserialize . ,(lambda (buffer vars)
 
                                (prog1 (run-octave)
 
                                  (rename-buffer (wg-buf-name buffer) t))))))
 

	
 
;; Prolog shell
 
(wg-support 'prolog-inferior-mode 'prolog
src/workgroups-utils-basic.el
Show inline comments
 
@@ -177,98 +177,98 @@ into a var, like so: (a (b c) . rest)
 
  "Evaluate all CONDITIONS.  Return the first non-nil return value."
 
  (let ((syms (mapcar (lambda (x) (cl-gensym)) conditions)))
 
    `(let ,(cl-mapcar 'list syms conditions)
 
       (or ,@syms))))
 

	
 
(defmacro wg-eager-and (&rest conditions)
 
  "Evaluate all conditions.  If any return nil, return nil.
 
Otherwise return the return value of the last condition."
 
  (let ((syms (mapcar (lambda (x) (cl-gensym)) conditions)))
 
    `(let ,(cl-mapcar 'list syms conditions)
 
       (and ,@syms))))
 

	
 

	
 

	
 
;;; numbers
 

	
 
(defun wg-step-to (n m step)
 
  "Increment or decrement N toward M by STEP.
 
Return M when the difference between N and M is less than STEP."
 
  (cond ((= n m) n)
 
        ((< n m) (min (+ n step) m))
 
        ((> n m) (max (- n step) m))))
 

	
 
(defun wg-within (num lo hi &optional hi-inclusive)
 
  "Return t when NUM is within bounds LO and HI.
 
HI-INCLUSIVE non-nil means the HI bound is inclusive."
 
  (and (>= num lo) (if hi-inclusive (<= num hi) (< num hi))))
 

	
 
(defun wg-int-to-b36-one-digit (i)
 
  "Return a character in 0..9 or A..Z from I, and integer 0<=I<32.
 
Cribbed from `org-id-int-to-b36-one-digit'."
 
  (cond ((not (wg-within i 0 36))
 
         (error "%s out of range" i))
 
        ((< i 10) (+ ?0 i))
 
        ((< i 36) (+ ?A i -10))))
 

	
 
(defun wg-b36-to-int-one-digit (i)
 
  "Turn a character 0..9, A..Z, a..z into a number 0..61.
 
The input I may be a character, or a single-letter string.
 
Cribbed from `org-id-b36-to-int-one-digit'."
 
  (and (stringp i) (setq i (string-to-char i)))
 
  (cond ((and (>= i ?0) (<= i ?9)) (- i ?0))
 
        ((and (>= i ?A) (<= i ?Z)) (+ (- i ?A) 10))
 
        (t (error "Invalid b36 character"))))
 

	
 
(defun wg-int-to-b36 (i &optional length)
 
  "Return a base 36 string from I."
 
  (let ((base 36) b36)
 
    (dflet ((add-digit () (push (wg-int-to-b36-one-digit (mod i base)) b36)
 
                      (setq i (/ i base))))
 
    (cl-flet ((add-digit () (push (wg-int-to-b36-one-digit (mod i base)) b36)
 
                         (setq i (/ i base))))
 
      (add-digit)
 
      (while (> i 0) (add-digit))
 
      (setq b36 (cl-map 'string 'identity b36))
 
      (if (not length) b36
 
        (concat (make-string (max 0 (- length (length b36))) ?0) b36)))))
 

	
 
(defun wg-b36-to-int (str)
 
  "Convert STR, a base-36 string, into the corresponding integer.
 
Cribbed from `org-id-b36-to-int'."
 
  (let ((result 0))
 
    (mapc (lambda (i)
 
            (setq result (+ (* result 36)
 
                            (wg-b36-to-int-one-digit i))))
 
          str)
 
    result))
 

	
 

	
 

	
 
;;; lists
 

	
 
(defmacro wg-removef-p (item seq-place &rest keys)
 
  "If ITEM is a `member*' of SEQ-PLACE, remove it from SEQ-PLACE and return t.
 
Otherwise return nil.  KEYS can be any keywords accepted by `remove*'."
 
  `(> (length ,seq-place)
 
      (length (setf ,seq-place (cl-remove ,item ,seq-place ,@keys)))))
 

	
 
(defmacro wg-pushnew-p (item seq-place &rest keys)
 
  "If ITEM is not a `member' of SEQ-PLACE, push it to SEQ-PLACE and return t.
 
Otherwise return nil.  KEYS can be any keyword args accepted by `pushnew'."
 
  `(< (length ,seq-place)
 
      (length (cl-pushnew ,item ,seq-place ,@keys))))
 

	
 
(defun wg-last1 (list)
 
  "Return the last element of LIST."
 
  (car (last list)))
 

	
 
(defun wg-take (list n)
 
  "Return a list of the first N elts in LIST."
 
  (butlast list (- (length list) n)))
 

	
 
(defun wg-leave (list n)
 
  "Return a list of the last N elts in LIST."
 
  (nthcdr (- (length list) n) list))
 

	
 
(defun wg-rnth (n list)
 
  "Return the Nth element of LIST, counting from the end."
 
  (nth (- (length list) n 1) list))
 

	
 
@@ -469,157 +469,157 @@ BUFFER-LIST should contain buffer objects and/or buffer names."
 
  (cl-find regexp (or buffer-list (buffer-list))
 
           :test 'string-match :key 'wg-buffer-name))
 

	
 

	
 

	
 
;;; files
 

	
 
(defun wg-write-sexp-to-file (sexp file)
 
  "Write the printable representation of SEXP to FILE."
 
  (with-temp-buffer
 
    (let ((print-level nil)  (print-length nil))
 
      (insert (format "%S" sexp)))
 
    (write-file file)))
 

	
 
(defun wg-read-sexp-from-file (file)
 
  "Return a Lisp object from FILE."
 
  (with-temp-buffer
 
    (insert-file-contents file)
 
    (goto-char (point-min))
 
    (read (current-buffer))))
 
(defalias 'wg-lisp-object-from-file 'wg-read-sexp-from-file)
 

	
 
(defun wg-file-under-root-path-p (root-path file-path)
 
  "Return t when FILE-PATH is under ROOT-PATH, nil otherwise."
 
  (string-match (concat "^" (regexp-quote (expand-file-name root-path)))
 
                (expand-file-name file-path)))
 

	
 

	
 

	
 
;;; frames
 

	
 
(defun wg-cyclic-nth-from-frame (&optional n frame)
 
  "Return the frame N places away from FRAME in `frame-list' cyclically.
 
N defaults to 1, and FRAME defaults to `selected-frame'."
 
  (wg-cyclic-nth-from-elt
 
   (or frame (selected-frame)) (frame-list) (or n 1)))
 

	
 

	
 

	
 
;;; namespace-prefixed defstruct
 

	
 
(defmacro wg-defstruct (prefix name-form &rest slot-defs)
 
  "`defstruct' wrapper that namespace-prefixes all generated functions.
 
Note: this doesn't yet work with :conc-name, and possibly other
 
options."
 
  (declare (indent 2))
 
  (let* ((name (if (consp name-form) (car name-form) name-form))
 
         (prefixed-name (wg-symcat prefix "-" name)))
 
    (dflet ((rebind (opstr)
 
                   (let ((oldfnsym (wg-symcat opstr "-" prefix "-" name)))
 
                     `((fset ',(wg-symcat prefix "-" opstr "-" name)
 
                             (symbol-function ',oldfnsym))
 
                       (fmakunbound ',oldfnsym)))))
 
    (cl-flet ((rebind (opstr)
 
                      (let ((oldfnsym (wg-symcat opstr "-" prefix "-" name)))
 
                        `((fset ',(wg-symcat prefix "-" opstr "-" name)
 
                                (symbol-function ',oldfnsym))
 
                          (fmakunbound ',oldfnsym)))))
 
      ;; `eval-and-compile' gets rid of byte-comp warnings ("function `foo' not
 
      ;; known to be defined").  We can accomplish this with `declare-function'
 
      ;; too, but it annoyingly requires inclusion of the function's arglist,
 
      ;; which gets ugly.
 
      `(eval-and-compile
 
         (cl-defstruct ,(if (symbolp name-form) prefixed-name
 
                       `(,prefixed-name ,@(cdr name-form)))
 
           ,@slot-defs)
 
         ,@(rebind "make")
 
         ,@(rebind "copy")
 
         ',prefixed-name))))
 

	
 
(defmacro wg-with-slots (obj slot-bindings &rest body)
 
  "Bind OBJ's slot values to symbols in BINDS, then eval BODY.
 
The car of each element of SLOT-BINDINGS is the bound symbol, and
 
the cadr as the accessor function."
 
  (declare (indent 2))
 
  (wg-with-gensyms (objsym)
 
    `(let* ((,objsym ,obj)
 
            ,@(wg-docar (slot slot-bindings)
 
                `(,(car slot) (,(cadr slot) ,objsym))))
 
       ,@body)))
 

	
 

	
 

	
 
;;; misc
 

	
 
(defun wg-minibuffer-inactive-p ()
 
  "Return t when `minibuffer-depth' returns zero, nil otherwise."
 
  (zerop (minibuffer-depth)))
 

	
 
(defun wg-minibuffer-active-p ()
 
  "Return t when `minibuffer-depth' does not return zero, nil otherwise."
 
  (not (wg-minibuffer-inactive-p)))
 

	
 
(defun wg-fill-keymap (keymap &rest binds)
 
  "Return KEYMAP after defining in it all keybindings in BINDS."
 
  (while binds
 
    (define-key keymap (car binds) (cadr binds))
 
    (setq binds (cddr binds)))
 
  keymap)
 

	
 
(defun wg-add-or-remove-hooks (remove &rest pairs)
 
  "Add FUNCTION to or remove it from HOOK, depending on REMOVE."
 
  (dolist (pair (wg-partition pairs 2))
 
    (funcall (if remove 'remove-hook 'add-hook)
 
             (car pair) (cadr pair))))
 

	
 

	
 
(defun wg-read-object (prompt test warning &optional initial-contents keymap
 
                              read hist default-value inherit-input-method)
 
  "PROMPT for an object that satisfies TEST, WARNING if necessary.
 
ARGS are `read-from-minibuffer's args, after PROMPT."
 
  (dflet ((read () (read-from-minibuffer
 
                    prompt initial-contents keymap read hist
 
                    default-value inherit-input-method)))
 
  (cl-flet ((read () (read-from-minibuffer
 
                      prompt initial-contents keymap read hist
 
                      default-value inherit-input-method)))
 
    (let ((obj (read)))
 
      (when (and (equal obj "") default-value) (setq obj default-value))
 
      (while (not (funcall test obj))
 
        (message warning)
 
        (sit-for wg-minibuffer-message-timeout)
 
        (setq obj (read)))
 
      obj)))
 

	
 
(defvar wg-readable-types
 
  '(integer float cons symbol vector string char-table bool-vector)
 
  "List of types with readable printed representations.")
 

	
 
(defun wg-is-readable-p (obj)
 
  "Return non-nil if OBJ's printed representation is readable."
 
  (memq (type-of obj) wg-readable-types))
 

	
 
(defun wg-take-until-unreadable (list)
 
  "Return a new list of elements of LIST up to the first unreadable element."
 
  (wg-take-until-fail 'wg-is-readable-p list))
 

	
 
(defun wg-add-face (facekey string)
 
  "Return a copy of STRING fontified according to FACEKEY.
 
FACEKEY must be a key in `wg-face-abbrevs'."
 
  (let ((face (wg-aget wg-face-abbrevs facekey))
 
        (string  (copy-sequence string)))
 
    (unless face (error "No face with key %s" facekey))
 
    (if (not wg-use-faces) string
 
      (put-text-property 0 (length string) 'face face string)
 
      string)))
 

	
 
(defmacro wg-fontify (&rest specs)
 
  "A small fontification DSL.
 
The results of all SPECS are `concat'd together.
 
If a spec is a cons with a keyword car, apply `wg-add-face' to it.
 
Other conses get evaluated, and should produce a strings.
 
If a spec is a string it is used unmodified.
 
Anything else is formatted with %s to produce a string."
 
  (declare (indent defun))
 
  `(concat
 
    ,@(wg-docar (spec specs)
 
        (cond ((and (consp spec)
 
                    (keywordp (car spec)))
 
               `(wg-add-face ,@spec))
 
              ;;((listp spec) (cdr (eval spec)))
 
              ;;((listp spec)
 
              ;; ;;(prin1-to-string (nth 1 (eval spec)))
 
              ;; )
 
              ((consp spec) spec)
0 comments (0 inline, 0 general)