* lisp/emacs-lisp/cl-generic.el: Add (major-mode MODE) context

(cl--generic-derived-specializers): New function.
(cl--generic-derived-generalizer): New generalizer.
(cl-generic-generalizers): New specializer (derived-mode MODE).
(cl--generic-split-args): Apply the rewriter, if any.
(cl-generic-define-context-rewriter): New macro.
(major-mode): Use it to define a new context-rewriter, so we can write
`(major-mode MODE)' instead of `(major-mode (derived-mode MODE))'.

* lisp/frame.el (window-system): New context-rewriter so we can write
`(window-system VAL)' instead of (window-system (eql VAL)).
(cl--generic-split-args): Apply the rewriter, if any.
(frame-creation-function): Use the new syntax.

* lisp/term/x-win.el (window-system-initialization)
(handle-args-function, frame-creation-function)
(gui-backend-set-selection, gui-backend-selection-owner-p)
(gui-backend-selection-exists-p, gui-backend-get-selection):
* lisp/term/w32-win.el (window-system-initialization)
(handle-args-function, frame-creation-function)
(gui-backend-set-selection, gui-backend-get-selection)
(gui-backend-selection-owner-p, gui-backend-selection-exists-p):
* lisp/term/pc-win.el (gui-backend-get-selection)
(gui-backend-selection-exists-p, gui-backend-selection-owner-p)
(gui-backend-set-selection, window-system-initialization)
(frame-creation-function, handle-args-function):
* lisp/term/ns-win.el (window-system-initialization)
(handle-args-function, frame-creation-function)
(gui-backend-set-selection, gui-backend-selection-exists-p)
(gui-backend-get-selection):
* lisp/startup.el (handle-args-function):
* lisp/term/xterm.el (gui-backend-get-selection)
(gui-backend-set-selection): Use the new syntax.
This commit is contained in:
Stefan Monnier 2015-10-29 11:06:31 -04:00
parent a4f754ca0b
commit 84dcdbeb74
8 changed files with 86 additions and 37 deletions

View file

@ -266,6 +266,15 @@ BODY, if present, is used as the body of a default method.
This macro can only be used within the lexical scope of a cl-generic method."
(error "cl-generic-current-method-specializers used outside of a method"))
(defmacro cl-generic-define-context-rewriter (name args &rest body)
"Define a special kind of context named NAME.
Whenever a context specializer of the form (NAME . ACTUALS) appears,
the specializer used will be the one returned by BODY."
(declare (debug (&define name lambda-list def-body)) (indent defun))
`(eval-and-compile
(put ',name 'cl-generic--context-rewriter
(lambda ,args ,@body))))
(eval-and-compile ;Needed while compiling the cl-defmethod calls below!
(defun cl--generic-fgrep (vars sexp) ;Copied from pcase.el.
"Check which of the symbols VARS appear in SEXP."
@ -292,6 +301,11 @@ This macro can only be used within the lexical scope of a cl-generic method."
((let 'context mandatory)
(unless (consp arg)
(error "Invalid &context arg: %S" arg))
(let* ((name (car arg))
(rewriter
(and (symbolp name)
(get name 'cl-generic--context-rewriter))))
(if rewriter (setq arg (apply rewriter (cdr arg)))))
(push `((&context . ,(car arg)) . ,(cadr arg)) specializers)
nil)
(`(,name . ,type)
@ -1106,6 +1120,37 @@ The value returned is a list of elements of the form
(cl--generic-prefill-dispatchers 0 integer)
;;; Dispatch on major mode.
;; Two parts:
;; - first define a specializer (derived-mode <mode>) to match symbols
;; representing major modes, while obeying the major mode hierarchy.
;; - then define a context-rewriter so you can write
;; "&context (major-mode c-mode)" rather than
;; "&context (major-mode (derived-mode c-mode))".
(defun cl--generic-derived-specializers (mode &rest _)
;; FIXME: Handle (derived-mode <mode1> ... <modeN>)
(let ((specializers ()))
(while mode
(push `(derived-mode ,mode) specializers)
(setq mode (get mode 'derived-mode-parent)))
(nreverse specializers)))
(cl-generic-define-generalizer cl--generic-derived-generalizer
90 (lambda (name) `(and (symbolp ,name) (functionp ,name) ,name))
#'cl--generic-derived-specializers)
(cl-defmethod cl-generic-generalizers ((_specializer (head derived-mode)))
"Support for the `(derived-mode MODE)' specializers."
(list cl--generic-derived-generalizer))
(cl-generic-define-context-rewriter major-mode (mode &rest modes)
`(major-mode ,(if (consp mode)
;;E.g. could be (eql ...)
(progn (cl-assert (null modes)) mode)
`(derived-mode ,mode . ,modes))))
;; Local variables:
;; generated-autoload-file: "cl-loaddefs.el"
;; End:

View file

@ -33,8 +33,12 @@ The window system startup file should add its frame creation
function to this method, which should take an alist of parameters
as its argument.")
(cl-defmethod frame-creation-function (params
&context (window-system (eql nil)))
(cl-generic-define-context-rewriter window-system (value)
;; If `value' is a `consp', it's probably an old-style specializer,
;; so just use it, and anyway `eql' isn't very useful on cons cells.
`(window-system ,(if (consp value) value `(eql ,value))))
(cl-defmethod frame-creation-function (params &context (window-system nil))
;; It's tempting to get rid of tty-create-frame-with-faces and turn it into
;; this method (i.e. move this method to faces.el), but faces.el is loaded
;; much earlier from loadup.el (before cl-generic and even before

View file

@ -720,7 +720,7 @@ Window system startup files should add their own function to this
method, which should parse the command line arguments. Those
pertaining to the window system should be processed and removed
from the returned command line.")
(cl-defmethod handle-args-function (args &context (window-system (eql nil)))
(cl-defmethod handle-args-function (args &context (window-system nil))
(tty-handle-args args))
(cl-defgeneric window-system-initialization (&optional _display)

View file

@ -848,7 +848,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;; Do the actual Nextstep Windows setup here; the above code just
;; defines functions and variables that we use now.
(cl-defmethod window-system-initialization (&context (window-system (eql ns))
(cl-defmethod window-system-initialization (&context (window-system ns)
&optional _display)
"Initialize Emacs for Nextstep (Cocoa / GNUstep) windowing."
(cl-assert (not ns-initialized))
@ -922,10 +922,10 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;; Any display name is OK.
(add-to-list 'display-format-alist '(".*" . ns))
(cl-defmethod handle-args-function (args &context (window-system (eql ns)))
(cl-defmethod handle-args-function (args &context (window-system ns))
(x-handle-args args))
(cl-defmethod frame-creation-function (params &context (window-system (eql ns)))
(cl-defmethod frame-creation-function (params &context (window-system ns))
(x-create-frame-with-faces params))
(declare-function ns-own-selection-internal "nsselect.m" (selection value))
@ -935,20 +935,20 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(declare-function ns-get-selection "nsselect.m" (selection-symbol target-type))
(cl-defmethod gui-backend-set-selection (selection value
&context (window-system (eql ns)))
&context (window-system ns))
(if value (ns-own-selection-internal selection value)
(ns-disown-selection-internal selection)))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system (eql ns)))
&context (window-system ns))
(ns-selection-owner-p selection))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system (eql ns)))
&context (window-system ns))
(ns-selection-exists-p selection))
(cl-defmethod gui-backend-get-selection (selection-symbol target-type
&context (window-system (eql ns)))
&context (window-system ns))
(ns-get-selection selection-symbol target-type))
(provide 'ns-win)

View file

@ -221,7 +221,7 @@ the operating system.")
;; gui-get-selection is used in select.el
(cl-defmethod gui-backend-get-selection (_selection-symbol _target-type
&context (window-system (eql pc)))
&context (window-system pc))
"Return the value of the current selection.
Consult the selection. Treat empty strings as if they were unset."
;; Don't die if x-get-selection signals an error.
@ -231,11 +231,11 @@ Consult the selection. Treat empty strings as if they were unset."
(declare-function w16-selection-exists-p "w16select.c")
;; gui-selection-owner-p is used in simple.el.
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system (eql pc)))
&context (window-system pc))
(w16-selection-exists-p selection))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system (eql pc)))
&context (window-system pc))
(w16-selection-owner-p selection))
(defun w16-selection-owner-p (_selection)
@ -258,7 +258,7 @@ Consult the selection. Treat empty strings as if they were unset."
(declare-function w16-set-clipboard-data "w16select.c"
(string &optional ignored))
(cl-defmethod gui-backend-set-selection (selection value
&context (window-system (eql pc)))
&context (window-system pc))
(if (not value)
(if (w16-selection-owner-p selection)
t)
@ -333,7 +333,7 @@ Errors out because it is not supposed to be called, ever."
(window-system)))
;; window-system-initialization is called by startup.el:command-line.
(cl-defmethod window-system-initialization (&context (window-system (eql pc))
(cl-defmethod window-system-initialization (&context (window-system pc)
&optional _display)
"Initialization function for the `pc' \"window system\"."
(or (eq (window-system) 'pc)
@ -377,12 +377,12 @@ Errors out because it is not supposed to be called, ever."
(run-hooks 'terminal-init-msdos-hook))
;; frame-creation-function is called by frame.el:make-frame.
(cl-defmethod frame-creation-function (params &context (window-system (eql pc)))
(cl-defmethod frame-creation-function (params &context (window-system pc))
(msdos-create-frame-with-faces params))
;; We don't need anything beyond tty-handle-args for handling
;; command-line argument; see startup.el.
(cl-defmethod handle-args-function (args &context (window-system (eql pc)))
(cl-defmethod handle-args-function (args &context (window-system pc))
(tty-handle-args args))
;; ---------------------------------------------------------------------------

View file

@ -290,7 +290,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(declare-function x-parse-geometry "frame.c" (string))
(defvar x-command-line-resources)
(cl-defmethod window-system-initialization (&context (window-system (eql w32))
(cl-defmethod window-system-initialization (&context (window-system w32)
&optional _display)
"Initialize Emacs for W32 GUI frames."
(cl-assert (not w32-initialized))
@ -377,10 +377,10 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(setq w32-initialized t))
(add-to-list 'display-format-alist '("\\`w32\\'" . w32))
(cl-defmethod handle-args-function (args &context (window-system (eql w32)))
(cl-defmethod handle-args-function (args &context (window-system w32))
(x-handle-args args))
(cl-defmethod frame-creation-function (params &context (window-system (eql w32)))
(cl-defmethod frame-creation-function (params &context (window-system w32))
(x-create-frame-with-faces params))
;;;; Selections
@ -408,19 +408,19 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(get 'x-selections (or selection 'PRIMARY))))
(cl-defmethod gui-backend-set-selection (type value
&context (window-system (eql w32)))
&context (window-system w32))
(w32--set-selection type value))
(cl-defmethod gui-backend-get-selection (type data-type
&context (window-system (eql w32)))
&context (window-system w32))
(w32--get-selection type data-type))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system (eql w32)))
&context (window-system w32))
(w32--selection-owner-p selection))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system (eql w32)))
&context (window-system w32))
(w32-selection-exists-p selection))
(when (eq system-type 'windows-nt)
@ -428,19 +428,19 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;; We could move those cl-defmethods outside of the `when' and use
;; "&context (system-type (eql windows-nt))" instead!
(cl-defmethod gui-backend-set-selection (type value
&context (window-system (eql nil)))
&context (window-system nil))
(w32--set-selection type value))
(cl-defmethod gui-backend-get-selection (type data-type
&context (window-system (eql nil)))
&context (window-system nil))
(w32--get-selection type data-type))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system (eql nil)))
&context (window-system nil))
(w32--selection-owner-p selection))
(cl-defmethod gui-selection-exists-p (selection
&context (window-system (eql nil)))
&context (window-system nil))
(w32-selection-exists-p selection)))
;; The "Windows" keys on newer keyboards bring up the Start menu

View file

@ -1197,7 +1197,7 @@ This returns an error if any Emacs frames are X frames."
(defvar x-display-name)
(defvar x-command-line-resources)
(cl-defmethod window-system-initialization (&context (window-system (eql x))
(cl-defmethod window-system-initialization (&context (window-system x)
&optional display)
"Initialize Emacs for X frames and open the first connection to an X server."
(cl-assert (not x-initialized))
@ -1327,27 +1327,27 @@ This returns an error if any Emacs frames are X frames."
(selection-symbol target-type &optional time-stamp terminal))
(add-to-list 'display-format-alist '("\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" . x))
(cl-defmethod handle-args-function (args &context (window-system (eql x)))
(cl-defmethod handle-args-function (args &context (window-system x))
(x-handle-args args))
(cl-defmethod frame-creation-function (params &context (window-system (eql x)))
(cl-defmethod frame-creation-function (params &context (window-system x))
(x-create-frame-with-faces params))
(cl-defmethod gui-backend-set-selection (selection value
&context (window-system (eql x)))
&context (window-system x))
(if value (x-own-selection-internal selection value)
(x-disown-selection-internal selection)))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system (eql x)))
&context (window-system x))
(x-selection-owner-p selection))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system (eql x)))
&context (window-system x))
(x-selection-exists-p selection))
(cl-defmethod gui-backend-get-selection (selection-symbol target-type
&context (window-system (eql x))
&context (window-system x)
&optional time-stamp terminal)
(x-get-selection-internal selection-symbol target-type time-stamp terminal))

View file

@ -821,7 +821,7 @@ We run the first FUNCTION whose STRING matches the input events."
(cl-defmethod gui-backend-get-selection
(type data-type
&context (window-system (eql nil))
&context (window-system nil)
;; Only applies to terminals which have it enabled.
((terminal-parameter nil 'xterm--get-selection) (eql t)))
(unless (eq data-type 'STRING)
@ -844,7 +844,7 @@ We run the first FUNCTION whose STRING matches the input events."
(cl-defmethod gui-backend-set-selection
(type data
&context (window-system (eql nil))
&context (window-system nil)
;; Only applies to terminals which have it enabled.
((terminal-parameter nil 'xterm--set-selection) (eql t)))
"Copy DATA to the X selection using the OSC 52 escape sequence.