names icon indicating copy to clipboard operation
names copied to clipboard

Possible issue with macro debug spec not being defined when names runs

Open davidshepherd7 opened this issue 8 years ago • 3 comments

I'm having some trouble with electric-operator installs and I think it's coming from Names. Starting emacs with the following .emacs file and an empty .emacs.d/ fails with an error in a Names function:

;; Initialise package.el
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)
(package-refresh-contents)

;; (package-install 'dash)
;; (require 'dash)

(package-install 'electric-operator)

However if I uncomment the dash install and require lines then everything works.

I looked into the backtrace, and it appears to have problems with a -let* macro expression. -let* has some strange forms as arguments because it's a destructuring bind. However it does have a debug declaration so it should work (and it does if I require dash before installing electric-operator).

So it looks like Names isn't seeing the debug declaration for the macro, is that possible?

Is there a fix (other than telling people to make sure they install and load dash before installing my package)?

The full wall-of-text error is:

Debugger entered--Lisp error: (wrong-type-argument sequencep action)
  mapcar(names-convert-form action)
  (cons function (mapcar (quote names-convert-form) args))
  (if macro (let ((it (names--get-edebug-spec function)) (names--verbose (eq function (quote push)))) (names--message "Edebug-spec of `%s' is %s" function it) (if (or (equal it t) (memq function names--functionlike-macros)) (names--args-of-function-or-macro function args nil) (if (equal it 0) (cons function args) (names--macro-args-using-edebug (cons function args))))) (cons function (mapcar (quote names-convert-form) args)))
  names--args-of-function-or-macro(operator action nil)
  (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))
  (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func))))
  (if (memq func names--ignored-forms) (cons func args) (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))))
  names--handle-args(operator action)
  (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form))))
  (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))
  (cond ((null form) form) ((consp form) (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null ...) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))) ((symbolp form) (names--message "Symbol handling: %s" form) (or (names--remove-protection form) (if (names--boundp form) (intern (format "%s%s" names--name form)) form))) (t form))
  names-convert-form((operator . action))
  mapcar(names-convert-form ((operator . action) rule))
  (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form))))
  (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))
  (cond ((null form) form) ((consp form) (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null ...) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))) ((symbolp form) (names--message "Symbol handling: %s" form) (or (names--remove-protection form) (if (names--boundp form) (intern (format "%s%s" names--name form)) form))) (t form))
  names-convert-form(((operator . action) rule))
  mapcar(names-convert-form ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)))
  (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form))))
  (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))
  (cond ((null form) form) ((consp form) (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null ...) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))) ((symbolp form) (names--message "Symbol handling: %s" form) (or (names--remove-protection form) (if (names--boundp form) (intern (format "%s%s" names--name form)) form))) (t form))
  names-convert-form(((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)))
  mapcar(names-convert-form (((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action)))))))
  (cons function (mapcar (quote names-convert-form) args))
  (if macro (let ((it (names--get-edebug-spec function)) (names--verbose (eq function (quote push)))) (names--message "Edebug-spec of `%s' is %s" function it) (if (or (equal it t) (memq function names--functionlike-macros)) (names--args-of-function-or-macro function args nil) (if (equal it 0) (cons function args) (names--macro-args-using-edebug (cons function args))))) (cons function (mapcar (quote names-convert-form) args)))
  names--args-of-function-or-macro(-let* (((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action)))))) nil)
  (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))
  (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func))))
  (if (memq func names--ignored-forms) (cons func args) (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))))
  names--handle-args(-let* (((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action)))))))
  (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form))))
  (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))
  (cond ((null form) form) ((consp form) (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null ...) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))) ((symbolp form) (names--message "Symbol handling: %s" form) (or (names--remove-protection form) (if (names--boundp form) (intern (format "%s%s" names--name form)) form))) (t form))
  names-convert-form((-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action)))))))
  mapcar(names-convert-form ((-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  (progn (mapcar (quote names-convert-form) forms))
  (append (list (car form) (cadr form)) (if (stringp (car forms)) (progn (prog1 (list (car forms)) (setq forms (cdr forms))))) (if (eq (quote interactive) (car-safe (car forms))) (progn (prog1 (list (list (car (car forms)) (names-convert-form (cadr ...)))) (setq forms (cdr forms))))) (progn (mapcar (quote names-convert-form) forms)))
  (let ((names--local-vars (append (names--vars-from-arglist (cadr form)) names--local-vars)) (forms (cdr (cdr form)))) (append (list (car form) (cadr form)) (if (stringp (car forms)) (progn (prog1 (list (car forms)) (setq forms (cdr forms))))) (if (eq (quote interactive) (car-safe (car forms))) (progn (prog1 (list (list (car ...) (names-convert-form ...))) (setq forms (cdr forms))))) (progn (mapcar (quote names-convert-form) forms))))
  names--convert-lambda((electric-operator-post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  (cons (car form) (names--convert-lambda (cons (intern (format "%s%s" names--name name)) (cddr form))))
  (let* ((name (cadr form))) (add-to-list (quote names--fbound) name) (cons (car form) (names--convert-lambda (cons (intern (format "%s%s" names--name name)) (cddr form)))))
  names--convert-defun((defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  funcall(names--convert-defun (defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args)))
  (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))
  (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func))))
  (if (memq func names--ignored-forms) (cons func args) (let ((handler (intern-soft (format "names--convert-%s" func)))) (if (fboundp handler) (progn (names--message "Special handling: %s" handler) (funcall handler (cons func args))) (names--args-of-function-or-macro func args (names--compat-macrop func)))))
  names--handle-args(defun (post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form))))
  (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null (functionp kar)) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))
  (cond ((null form) form) ((consp form) (let ((kar (car form)) func) (cond ((and (symbolp kar) (setq func (names--remove-protection kar))) (names--message "Protected: %s" kar) (names--handle-args func (cdr form))) ((consp kar) (if (and (null ...) (> names--current-run 1)) (progn (names--warn "Ran into the following strange form.\nEither it's an undefined macro, a macro with a bad debug declaration, or we have a bug.\n%s" form))) (mapcar (quote names-convert-form) form)) ((names--fboundp kar) (names--message "Namespaced: %s" kar) (names--args-of-function-or-macro (intern (format "%s%s" names--name kar)) (cdr form) (names--macrop kar))) (t (names--handle-args kar (cdr form)))))) ((symbolp form) (names--message "Symbol handling: %s" form) (or (names--remove-protection form) (if (names--boundp form) (intern (format "%s%s" names--name form)) form))) (t form))
  names-convert-form((defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))))
  mapc(names-convert-form ((defcustom double-space-docs nil "Enable double spacing of . in document lines - e,g, type '.' => get '.  '." :type (quote boolean) :group (quote electricity)) (defcustom enable-in-docs nil "Enable electric-operator in strings and comments." :type (quote boolean) :group (quote electricity)) (defcustom c-pointer-type-style (quote variable) "Defines how C/C++ mode pointer and reference types are spaced.\n\nIf set to 'variable then the operator is touching the variable\nname, as in `int *x'.\n\nIf set to 'type then the operator is touching the type name , as\nin `int* x'." :group (quote electricity) :options (quote (variable type))) (defvar mode-rules-table (make-hash-table) "A hash table of replacement rule lists for specific major modes") (defun -add-rule (initial new-rule) "Replace or append a new rule\n\nReturns a modified copy of the rule list." (let* ((op (car new-rule)) (existing-rule (assoc op initial))) (if existing-rule (-replace existing-rule new-rule initial) (-snoc initial new-rule)))) (defun -add-rule-list (initial new-rules) "Replace or append a list of rules\n\nReturns a modified copy of the rule list." (-reduce (function -add-rule) (-concat (list initial) new-rules))) (defun add-rules (initial &rest new-rules) "Replace or append multiple rules\n\nReturns a modified copy of the rule list." (-add-rule-list initial new-rules)) (defun add-rules-for-mode (major-mode-symbol &rest new-rules) "Replace or add spacing rules for major mode\n\nDestructively modifies mode-rules-table to use the new rules for\nthe given major mode." (puthash major-mode-symbol (-add-rule-list (gethash major-mode-symbol mode-rules-table) new-rules) mode-rules-table)) (defvar prog-mode-rules (list (cons "=" " = ") (cons "<" " < ") (cons ">" " > ") (cons "%" " % ") (cons "+" " + ") (cons "-" (function prog-mode--)) (cons "*" " * ") (cons "/" (function prog-mode-/)) (cons "&" " & ") (cons "|" " | ") (cons "?" "? ") (cons "," ", ") (cons "^" " ^ ") (cons "==" " == ") (cons "!=" " != ") (cons "<=" " <= ") (cons ">=" " >= ") (cons "*=" " *= ") (cons "+=" " += ") (cons "/=" " /= ") (cons "-=" " -= ") (cons "&&" " && ") (cons "||" " || ")) "Default spacing rules for programming modes") (defvar prose-rules (add-rules (quote nil) (cons "." (function docs-\.)) (cons "," ", ")) "Rules to use in comments, strings and text modes.") (defun get-rules-list nil "Pick which rule list is appropriate for spacing at point" (cond ((in-docs\?) (if enable-in-docs prose-rules (list))) ((gethash major-mode mode-rules-table)) ((derived-mode-p (quote prog-mode)) prog-mode-rules) (t prose-rules))) (defun rule-regex-with-whitespace (op) "Construct regex matching operator and any whitespace before/inside/after.\n\nFor example for the operator '+=' we allow '+=', ' +=', '+ ='. etc.\n\nWhitespace before the operator is captured for possible use later.\n" (concat "\\( *\\)" (mapconcat (function regexp-quote) (split-string op "" t) " *") " *")) (defun longest-matching-rule (rule-list) "Return the rule with the most characters that applies to text before point" (->> rule-list (-filter (lambda (rule) (looking-back (rule-regex-with-whitespace (car rule))))) (-sort (lambda (p1 p2) (> (length (car p1)) (length (car p2))))) (car))) (defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))) :autoload (define-minor-mode mode "Toggle automatic insertion of spaces around operators (Electric Spacing mode).\n\nWith a prefix argument ARG, enable Electric Spacing mode if ARG is\npositive, and disable it otherwise.  If called from Lisp, enable\nthe mode if ARG is omitted or nil.\n\nThis is a local minor mode.  When enabled, typing an operator automatically\ninserts surrounding spaces, e.g., `=' becomes ` = ',`+=' becomes ` += '." :global nil :group (quote electricity) :lighter " _+_" (if mode (add-hook (quote post-self-insert-hook) (function post-self-insert-function) nil t) (remove-hook (quote post-self-insert-hook) (function post-self-insert-function) t))) (defun in-docs\? nil "Check if we are inside a string or comment" (nth 8 (syntax-ppss))) (defun hashbang-line\? nil "Does the current line contain a UNIX hashbang?" (and (eq 1 (line-number-at-pos)) (save-excursion (move-beginning-of-line nil) (looking-at "#!")))) (defun enclosing-paren nil "Return the opening parenthesis of the enclosing parens, or nil\nif not inside any parens." (interactive) (let ((ppss (syntax-ppss))) (when (nth 1 ppss) (char-after (nth 1 ppss))))) (defun probably-unary-operator\? nil "Try to guess if the operator we are about to insert will be unary\n\n(i.e. takes one argument). This is a bit of a fudge based on C-like syntax." (or (looking-back "^") (looking-back "[=,:*+-/><&^([{]") (looking-back "\\(return\\)"))) (defun docs-\. nil "Double space if setting tells us to" (if double-space-docs ".  " ". ")) (defun prog-mode-- nil "Handle exponent and negative number notation" (cond ((looking-back "[0-9.]+[eE]") "-") ((probably-unary-operator\?) (if (or (looking-back "[[(]") (looking-back "^")) "-" " -")) (t " - "))) (defun prog-mode-/ nil "Handle path separator in UNIX hashbangs" (cond ((and (hashbang-line\?) (looking-back "#!")) " /") ((hashbang-line\?) "/") (t " / "))) (apply (function add-rules-for-mode) (quote c-mode) prog-mode-rules) (add-rules-for-mode (quote c-mode) (cons "->" "->") (cons "?" " ? ") (cons ":" (function c-mode-:)) (cons "*" (function c-mode-*)) (cons "&" (function c-mode-&)) (cons "**" (function c-mode-**)) (cons "++" (function c-mode-++)) (cons "--" (function c-mode---)) (cons "<" (function c-mode-<)) (cons ">" (function c-mode->)) (cons "<<" " << ") (cons ">>" " >> ") (cons "/*" "/* ") (cons "//" "// ") (cons "++;" "++;") (cons "--;" "--;") (cons "%=" " %= ") (cons "^=" " ^= ") (cons "&=" " &= ") (cons "|=" " |= ") (cons "<<=" " <<= ") (cons ">>=" " >>= ")) (puthash (quote c++-mode) (gethash (quote c-mode) mode-rules-table) mode-rules-table) (add-rules-for-mode (quote c++-mode) (cons "&&" (function c++-mode-&&)) (cons ">>" (function c++-mode->>))) (defvar c-user-types-regex "_t" "Regex used in looking-back to check for C types\n\nFor now we just assume that anything ending in '_t' is a type.\nI'm not sure if we can do any better by default.\n\nYou could add your own type names to this if needed. Send pull\nrequests/bug reports if you find any widely used type names that\ncould be added here.") (defun c-after-type\? nil (or (looking-back (concat c-primitive-type-key "?")) (looking-back c-user-types-regex))) (defvar c-function-definition-syntax-list (quote (topmost-intro topmost-intro-cont arglist-intro arglist-cont-nonempty)) "syntax symbols for lines which contain a function definition\n\nSee `c-guess-basic-syntax'.") (defun c-is-function-definition\? nil "Try to guess if we are in function definition/declaration\n\nUsing `cc-mode''s syntactic analysis." (->> (c-guess-basic-syntax) (-map (function car)) (-intersection c-function-definition-syntax-list))) (defun c-mode-: nil "Handle the : part of ternary operator" (if (looking-back "\\?.+") " : " ":")) (defun c-mode-++ nil "Handle ++ operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "++ " " ++")) (defun c-mode--- nil "Handle -- operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "-- " " --")) (defun c-mode-< nil "Handle #include brackets and templates" (cond ((looking-back "# *include *") " <") ((c-is-function-definition\?) "<") (t " < "))) (defun c-mode-> nil "Handle #include brackets and templates" (cond ((looking-back "# *include.*") ">") ((c-is-function-definition\?) "> ") (t " > "))) (defun c++-mode->> nil "Handle nested templates" (cond ((c-is-function-definition\?) ">> ") (t " >> "))) (defun c-space-pointer-type (op) "Space a C pointer types operator as specified by\n  `c-pointer-type-style'.\n\n For example `int* x'  or `int *x'." (cond ((eq c-pointer-type-style (quote variable)) (concat " " op)) ((eq c-pointer-type-style (quote type)) (concat op " ")) (t (error "Unrecognised value for c-pointer-type-style.")))) (defun c-mode-& nil "Handle C address-of operator and reference types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "&")) ((looking-back "(") "&") ((probably-unary-operator\?) " &") (t " & "))) (defun c-mode-* nil "Handle C dereference operator and pointer types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "*")) ((looking-back "(") "*") ((probably-unary-operator\?) " *") (t " * "))) (defun c-mode-** nil "C pointer to pointer." (c-space-pointer-type "**")) (defun c++-mode-&& nil "Handle move constructor" (if (c-is-function-definition\?) (c-space-pointer-type "&&") " && ")) (apply (function add-rules-for-mode) (quote python-mode) prog-mode-rules) (add-rules-for-mode (quote python-mode) (cons "**" (function python-mode-**)) (cons "*" (function python-mode-*)) (cons ":" (function python-mode-:)) (cons "//" " // ") (cons "=" (function python-mode-kwargs-=)) (cons "-" (function python-mode-negative-slices))) (defun python-mode-: nil "Handle python dict assignment" (if (and (not (in-string-p)) (eq (enclosing-paren) 123)) ": " ":")) (defun python-mode-* nil "Handle python *args" (cond ((looking-back ",") " *") ((looking-back "[(,^)][     ]*") "*") (t " * "))) (defun python-mode-** nil "Handle python **kwargs" (cond ((looking-back ",") " **") ((looking-back "[(,^)][   ]*") "**") (t " ** "))) (defun python-mode-kwargs-= nil (if (eq (enclosing-paren) 40) "=" " = ")) (defun python-mode-negative-slices nil "Handle cases like a[1:-1], see issue #2." (if (and (eq (enclosing-paren) 91) (looking-back ":")) "-" (prog-mode--))) (puthash (quote ruby-mode) (add-rules prog-mode-rules (cons "=~" " =~ ")) mode-rules-table) ...))
  (let* ((names--name name) (names--regexp (concat "\\`" (regexp-quote (symbol-name name)))) (names--current-run 0) (names--protection "\\`::") (names--bound (names--remove-namespace-from-list (if (boundp (quote byte-compile-bound-variables)) (progn (remove nil (mapcar ... byte-compile-bound-variables)))) (if (boundp (quote byte-compile-variables)) (progn (remove nil (mapcar ... byte-compile-variables)))))) (names--fbound (names--remove-namespace-from-list (if (boundp (quote byte-compile-macro-environment)) (progn (remove nil (mapcar ... byte-compile-macro-environment)))) (if (boundp (quote byte-compile-function-environment)) (progn (remove nil (mapcar ... byte-compile-function-environment)))))) (names--macro (names--remove-namespace-from-list (if (boundp (quote byte-compile-macro-environment)) (progn (remove nil (mapcar ... byte-compile-macro-environment)))) (if (boundp (quote byte-compile-function-environment)) (progn (remove nil (mapcar ... byte-compile-function-environment)))))) (names--functionlike-macros names--functionlike-macros) names--keywords names--local-vars key-and-args names--version names--package names--group-parent) (while (setq key-and-args (let ((kar (car-safe body)) out n) (and kar (keywordp kar) (setq n (assoc kar names--keyword-list)) (setq n (cadr n)) (let ((--dotimes-limit-- ...) (--dotimes-counter-- 0)) (while (< --dotimes-counter-- --dotimes-limit--) (let ... ...) (setq --dotimes-counter-- ...)) (let (...) out)) (nreverse out)))) (names--handle-keyword key-and-args) (setq names--keywords (cons key-and-args names--keywords))) (mapc (quote names-convert-form) body) (setq names--current-run (1+ names--current-run)) (setq body (cons (quote progn) (append (if (and names--group-parent (null (names--keyword :clean-output))) (progn (list (names--generate-defgroup)))) (if (and names--version (null (names--keyword :clean-output))) (progn (names--generate-version))) (mapcar (quote names-convert-form) (if names--inside-make-autoload (names--extract-autoloads body) body))))) (if (and (boundp (quote byte-compile-current-buffer)) byte-compile-current-buffer (null names--inside-make-autoload) (version< emacs-version "24.4")) (let ((byte-compile-macro-environment (if (boundp (quote byte-compile-macro-environment)) (progn byte-compile-macro-environment)))) (mapc (function names--add-macro-to-environment) (cdr body)) (macroexpand-all body byte-compile-macro-environment)) body))
  (unwind-protect (let* ((names--name name) (names--regexp (concat "\\`" (regexp-quote (symbol-name name)))) (names--current-run 0) (names--protection "\\`::") (names--bound (names--remove-namespace-from-list (if (boundp (quote byte-compile-bound-variables)) (progn (remove nil ...))) (if (boundp (quote byte-compile-variables)) (progn (remove nil ...))))) (names--fbound (names--remove-namespace-from-list (if (boundp (quote byte-compile-macro-environment)) (progn (remove nil ...))) (if (boundp (quote byte-compile-function-environment)) (progn (remove nil ...))))) (names--macro (names--remove-namespace-from-list (if (boundp (quote byte-compile-macro-environment)) (progn (remove nil ...))) (if (boundp (quote byte-compile-function-environment)) (progn (remove nil ...))))) (names--functionlike-macros names--functionlike-macros) names--keywords names--local-vars key-and-args names--version names--package names--group-parent) (while (setq key-and-args (let ((kar (car-safe body)) out n) (and kar (keywordp kar) (setq n (assoc kar names--keyword-list)) (setq n (cadr n)) (let (... ...) (while ... ... ...) (let ... out)) (nreverse out)))) (names--handle-keyword key-and-args) (setq names--keywords (cons key-and-args names--keywords))) (mapc (quote names-convert-form) body) (setq names--current-run (1+ names--current-run)) (setq body (cons (quote progn) (append (if (and names--group-parent (null ...)) (progn (list ...))) (if (and names--version (null ...)) (progn (names--generate-version))) (mapcar (quote names-convert-form) (if names--inside-make-autoload (names--extract-autoloads body) body))))) (if (and (boundp (quote byte-compile-current-buffer)) byte-compile-current-buffer (null names--inside-make-autoload) (version< emacs-version "24.4")) (let ((byte-compile-macro-environment (if (boundp ...) (progn byte-compile-macro-environment)))) (mapc (function names--add-macro-to-environment) (cdr body)) (macroexpand-all body byte-compile-macro-environment)) body)) (mapc (function (lambda (x) (set x nil))) names--var-list))
  names--define-namespace-implementation(electric-operator- (:functionlike-macros (-> ->>) (defcustom double-space-docs nil "Enable double spacing of . in document lines - e,g, type '.' => get '.  '." :type (quote boolean) :group (quote electricity)) (defcustom enable-in-docs nil "Enable electric-operator in strings and comments." :type (quote boolean) :group (quote electricity)) (defcustom c-pointer-type-style (quote variable) "Defines how C/C++ mode pointer and reference types are spaced.\n\nIf set to 'variable then the operator is touching the variable\nname, as in `int *x'.\n\nIf set to 'type then the operator is touching the type name , as\nin `int* x'." :group (quote electricity) :options (quote (variable type))) (defvar mode-rules-table (make-hash-table) "A hash table of replacement rule lists for specific major modes") (defun -add-rule (initial new-rule) "Replace or append a new rule\n\nReturns a modified copy of the rule list." (let* ((op (car new-rule)) (existing-rule (assoc op initial))) (if existing-rule (-replace existing-rule new-rule initial) (-snoc initial new-rule)))) (defun -add-rule-list (initial new-rules) "Replace or append a list of rules\n\nReturns a modified copy of the rule list." (-reduce (function -add-rule) (-concat (list initial) new-rules))) (defun add-rules (initial &rest new-rules) "Replace or append multiple rules\n\nReturns a modified copy of the rule list." (-add-rule-list initial new-rules)) (defun add-rules-for-mode (major-mode-symbol &rest new-rules) "Replace or add spacing rules for major mode\n\nDestructively modifies mode-rules-table to use the new rules for\nthe given major mode." (puthash major-mode-symbol (-add-rule-list (gethash major-mode-symbol mode-rules-table) new-rules) mode-rules-table)) (defvar prog-mode-rules (list (cons "=" " = ") (cons "<" " < ") (cons ">" " > ") (cons "%" " % ") (cons "+" " + ") (cons "-" (function prog-mode--)) (cons "*" " * ") (cons "/" (function prog-mode-/)) (cons "&" " & ") (cons "|" " | ") (cons "?" "? ") (cons "," ", ") (cons "^" " ^ ") (cons "==" " == ") (cons "!=" " != ") (cons "<=" " <= ") (cons ">=" " >= ") (cons "*=" " *= ") (cons "+=" " += ") (cons "/=" " /= ") (cons "-=" " -= ") (cons "&&" " && ") (cons "||" " || ")) "Default spacing rules for programming modes") (defvar prose-rules (add-rules (quote nil) (cons "." (function docs-\.)) (cons "," ", ")) "Rules to use in comments, strings and text modes.") (defun get-rules-list nil "Pick which rule list is appropriate for spacing at point" (cond ((in-docs\?) (if enable-in-docs prose-rules (list))) ((gethash major-mode mode-rules-table)) ((derived-mode-p (quote prog-mode)) prog-mode-rules) (t prose-rules))) (defun rule-regex-with-whitespace (op) "Construct regex matching operator and any whitespace before/inside/after.\n\nFor example for the operator '+=' we allow '+=', ' +=', '+ ='. etc.\n\nWhitespace before the operator is captured for possible use later.\n" (concat "\\( *\\)" (mapconcat (function regexp-quote) (split-string op "" t) " *") " *")) (defun longest-matching-rule (rule-list) "Return the rule with the most characters that applies to text before point" (->> rule-list (-filter (lambda (rule) (looking-back (rule-regex-with-whitespace (car rule))))) (-sort (lambda (p1 p2) (> (length (car p1)) (length (car p2))))) (car))) (defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))) :autoload (define-minor-mode mode "Toggle automatic insertion of spaces around operators (Electric Spacing mode).\n\nWith a prefix argument ARG, enable Electric Spacing mode if ARG is\npositive, and disable it otherwise.  If called from Lisp, enable\nthe mode if ARG is omitted or nil.\n\nThis is a local minor mode.  When enabled, typing an operator automatically\ninserts surrounding spaces, e.g., `=' becomes ` = ',`+=' becomes ` += '." :global nil :group (quote electricity) :lighter " _+_" (if mode (add-hook (quote post-self-insert-hook) (function post-self-insert-function) nil t) (remove-hook (quote post-self-insert-hook) (function post-self-insert-function) t))) (defun in-docs\? nil "Check if we are inside a string or comment" (nth 8 (syntax-ppss))) (defun hashbang-line\? nil "Does the current line contain a UNIX hashbang?" (and (eq 1 (line-number-at-pos)) (save-excursion (move-beginning-of-line nil) (looking-at "#!")))) (defun enclosing-paren nil "Return the opening parenthesis of the enclosing parens, or nil\nif not inside any parens." (interactive) (let ((ppss (syntax-ppss))) (when (nth 1 ppss) (char-after (nth 1 ppss))))) (defun probably-unary-operator\? nil "Try to guess if the operator we are about to insert will be unary\n\n(i.e. takes one argument). This is a bit of a fudge based on C-like syntax." (or (looking-back "^") (looking-back "[=,:*+-/><&^([{]") (looking-back "\\(return\\)"))) (defun docs-\. nil "Double space if setting tells us to" (if double-space-docs ".  " ". ")) (defun prog-mode-- nil "Handle exponent and negative number notation" (cond ((looking-back "[0-9.]+[eE]") "-") ((probably-unary-operator\?) (if (or (looking-back "[[(]") (looking-back "^")) "-" " -")) (t " - "))) (defun prog-mode-/ nil "Handle path separator in UNIX hashbangs" (cond ((and (hashbang-line\?) (looking-back "#!")) " /") ((hashbang-line\?) "/") (t " / "))) (apply (function add-rules-for-mode) (quote c-mode) prog-mode-rules) (add-rules-for-mode (quote c-mode) (cons "->" "->") (cons "?" " ? ") (cons ":" (function c-mode-:)) (cons "*" (function c-mode-*)) (cons "&" (function c-mode-&)) (cons "**" (function c-mode-**)) (cons "++" (function c-mode-++)) (cons "--" (function c-mode---)) (cons "<" (function c-mode-<)) (cons ">" (function c-mode->)) (cons "<<" " << ") (cons ">>" " >> ") (cons "/*" "/* ") (cons "//" "// ") (cons "++;" "++;") (cons "--;" "--;") (cons "%=" " %= ") (cons "^=" " ^= ") (cons "&=" " &= ") (cons "|=" " |= ") (cons "<<=" " <<= ") (cons ">>=" " >>= ")) (puthash (quote c++-mode) (gethash (quote c-mode) mode-rules-table) mode-rules-table) (add-rules-for-mode (quote c++-mode) (cons "&&" (function c++-mode-&&)) (cons ">>" (function c++-mode->>))) (defvar c-user-types-regex "_t" "Regex used in looking-back to check for C types\n\nFor now we just assume that anything ending in '_t' is a type.\nI'm not sure if we can do any better by default.\n\nYou could add your own type names to this if needed. Send pull\nrequests/bug reports if you find any widely used type names that\ncould be added here.") (defun c-after-type\? nil (or (looking-back (concat c-primitive-type-key "?")) (looking-back c-user-types-regex))) (defvar c-function-definition-syntax-list (quote (topmost-intro topmost-intro-cont arglist-intro arglist-cont-nonempty)) "syntax symbols for lines which contain a function definition\n\nSee `c-guess-basic-syntax'.") (defun c-is-function-definition\? nil "Try to guess if we are in function definition/declaration\n\nUsing `cc-mode''s syntactic analysis." (->> (c-guess-basic-syntax) (-map (function car)) (-intersection c-function-definition-syntax-list))) (defun c-mode-: nil "Handle the : part of ternary operator" (if (looking-back "\\?.+") " : " ":")) (defun c-mode-++ nil "Handle ++ operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "++ " " ++")) (defun c-mode--- nil "Handle -- operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "-- " " --")) (defun c-mode-< nil "Handle #include brackets and templates" (cond ((looking-back "# *include *") " <") ((c-is-function-definition\?) "<") (t " < "))) (defun c-mode-> nil "Handle #include brackets and templates" (cond ((looking-back "# *include.*") ">") ((c-is-function-definition\?) "> ") (t " > "))) (defun c++-mode->> nil "Handle nested templates" (cond ((c-is-function-definition\?) ">> ") (t " >> "))) (defun c-space-pointer-type (op) "Space a C pointer types operator as specified by\n  `c-pointer-type-style'.\n\n For example `int* x'  or `int *x'." (cond ((eq c-pointer-type-style (quote variable)) (concat " " op)) ((eq c-pointer-type-style (quote type)) (concat op " ")) (t (error "Unrecognised value for c-pointer-type-style.")))) (defun c-mode-& nil "Handle C address-of operator and reference types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "&")) ((looking-back "(") "&") ((probably-unary-operator\?) " &") (t " & "))) (defun c-mode-* nil "Handle C dereference operator and pointer types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "*")) ((looking-back "(") "*") ((probably-unary-operator\?) " *") (t " * "))) (defun c-mode-** nil "C pointer to pointer." (c-space-pointer-type "**")) (defun c++-mode-&& nil "Handle move constructor" (if (c-is-function-definition\?) (c-space-pointer-type "&&") " && ")) (apply (function add-rules-for-mode) (quote python-mode) prog-mode-rules) (add-rules-for-mode (quote python-mode) (cons "**" (function python-mode-**)) (cons "*" (function python-mode-*)) (cons ":" (function python-mode-:)) (cons "//" " // ") (cons "=" (function python-mode-kwargs-=)) (cons "-" (function python-mode-negative-slices))) (defun python-mode-: nil "Handle python dict assignment" (if (and (not (in-string-p)) (eq (enclosing-paren) 123)) ": " ":")) (defun python-mode-* nil "Handle python *args" (cond ((looking-back ",") " *") ((looking-back "[(,^)][     ]*") "*") (t " * "))) (defun python-mode-** nil "Handle python **kwargs" (cond ((looking-back ",") " **") ((looking-back "[(,^)][   ]*") "**") (t " ** "))) (defun python-mode-kwargs-= nil (if (eq (enclosing-paren) 40) "=" " = ")) ...))
  (let ((names--has-reloaded names--has-reloaded)) (if names--has-reloaded nil (setq names--has-reloaded t) (names--reload-if-upgraded)) (names--error-if-using-vars) (names--define-namespace-implementation name body))
  (closure (global-edebug-prefix edebug-inhibit-emacs-lisp-mode-bindings t) (name &rest body) "Inside the namespace NAME, execute BODY.\nNAME can be any symbol (not quoted), but it's highly recommended\nto use some form of separator (such as :, /, or -). For a\ncomplete description of this macro, please visit the frontpage\nwith \\[names-view-manual].\n\nIn summary, this macro has two main effects:\n\n1. Any definitions inside BODY will have NAME prepended to the\nsymbol given. Ex:\n\n    (define-namespace foo-\n    (defvar bar 1 \"docs\")\n    )\n\nexpands to\n\n    (defvar foo-bar 1 \"docs\")\n\n\n2. Any function calls and variable names get NAME prepended to\nthem if such a variable or function exists. Ex:\n\n    (define-namespace foo:\n    (defun message (x y) nil)\n    (message \"%s\" my-var)\n    )\n\nexpands to\n\n    (defun foo:message (x y) nil)\n    (foo:message \"%s\" my-var)\n\nNote how `message' is expanded to `foo:message' in the second\nform, because that function exists. Meanwhile, `bar' is left\nuntouched because `foo:bar' is not a known variable name.\n\n===============================\n\nAUTOLOAD\n\nIn order for `define-namespace' to work with \";;;###autoload\"\ncomments must replace all instances of \";;;###autoload\" inside\nyour `define-namespace' with `:autoload'.\nAfterwards, add an \";;;###autoload\" comment just above your\n`define-namespace'.\n\n===============================\n\nKEYWORDS\n\nImmediately after NAME you may add keywords which customize the\nbehaviour of `define-namespace'. For a list of possible keywords\nand a description of their effects, see the variable\n`names--keyword-list'.\n\n(fn NAME [KEYWORD ...] BODY)" (let ((names--has-reloaded names--has-reloaded)) (if names--has-reloaded nil (setq names--has-reloaded t) (names--reload-if-upgraded)) (names--error-if-using-vars) (names--define-namespace-implementation name body)))(electric-operator- :functionlike-macros (-> ->>) (defcustom double-space-docs nil "Enable double spacing of . in document lines - e,g, type '.' => get '.  '." :type (quote boolean) :group (quote electricity)) (defcustom enable-in-docs nil "Enable electric-operator in strings and comments." :type (quote boolean) :group (quote electricity)) (defcustom c-pointer-type-style (quote variable) "Defines how C/C++ mode pointer and reference types are spaced.\n\nIf set to 'variable then the operator is touching the variable\nname, as in `int *x'.\n\nIf set to 'type then the operator is touching the type name , as\nin `int* x'." :group (quote electricity) :options (quote (variable type))) (defvar mode-rules-table (make-hash-table) "A hash table of replacement rule lists for specific major modes") (defun -add-rule (initial new-rule) "Replace or append a new rule\n\nReturns a modified copy of the rule list." (let* ((op (car new-rule)) (existing-rule (assoc op initial))) (if existing-rule (-replace existing-rule new-rule initial) (-snoc initial new-rule)))) (defun -add-rule-list (initial new-rules) "Replace or append a list of rules\n\nReturns a modified copy of the rule list." (-reduce (function -add-rule) (-concat (list initial) new-rules))) (defun add-rules (initial &rest new-rules) "Replace or append multiple rules\n\nReturns a modified copy of the rule list." (-add-rule-list initial new-rules)) (defun add-rules-for-mode (major-mode-symbol &rest new-rules) "Replace or add spacing rules for major mode\n\nDestructively modifies mode-rules-table to use the new rules for\nthe given major mode." (puthash major-mode-symbol (-add-rule-list (gethash major-mode-symbol mode-rules-table) new-rules) mode-rules-table)) (defvar prog-mode-rules (list (cons "=" " = ") (cons "<" " < ") (cons ">" " > ") (cons "%" " % ") (cons "+" " + ") (cons "-" (function prog-mode--)) (cons "*" " * ") (cons "/" (function prog-mode-/)) (cons "&" " & ") (cons "|" " | ") (cons "?" "? ") (cons "," ", ") (cons "^" " ^ ") (cons "==" " == ") (cons "!=" " != ") (cons "<=" " <= ") (cons ">=" " >= ") (cons "*=" " *= ") (cons "+=" " += ") (cons "/=" " /= ") (cons "-=" " -= ") (cons "&&" " && ") (cons "||" " || ")) "Default spacing rules for programming modes") (defvar prose-rules (add-rules (quote nil) (cons "." (function docs-\.)) (cons "," ", ")) "Rules to use in comments, strings and text modes.") (defun get-rules-list nil "Pick which rule list is appropriate for spacing at point" (cond ((in-docs\?) (if enable-in-docs prose-rules (list))) ((gethash major-mode mode-rules-table)) ((derived-mode-p (quote prog-mode)) prog-mode-rules) (t prose-rules))) (defun rule-regex-with-whitespace (op) "Construct regex matching operator and any whitespace before/inside/after.\n\nFor example for the operator '+=' we allow '+=', ' +=', '+ ='. etc.\n\nWhitespace before the operator is captured for possible use later.\n" (concat "\\( *\\)" (mapconcat (function regexp-quote) (split-string op "" t) " *") " *")) (defun longest-matching-rule (rule-list) "Return the rule with the most characters that applies to text before point" (->> rule-list (-filter (lambda (rule) (looking-back (rule-regex-with-whitespace (car rule))))) (-sort (lambda (p1 p2) (> (length (car p1)) (length (car p2))))) (car))) (defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))) :autoload (define-minor-mode mode "Toggle automatic insertion of spaces around operators (Electric Spacing mode).\n\nWith a prefix argument ARG, enable Electric Spacing mode if ARG is\npositive, and disable it otherwise.  If called from Lisp, enable\nthe mode if ARG is omitted or nil.\n\nThis is a local minor mode.  When enabled, typing an operator automatically\ninserts surrounding spaces, e.g., `=' becomes ` = ',`+=' becomes ` += '." :global nil :group (quote electricity) :lighter " _+_" (if mode (add-hook (quote post-self-insert-hook) (function post-self-insert-function) nil t) (remove-hook (quote post-self-insert-hook) (function post-self-insert-function) t))) (defun in-docs\? nil "Check if we are inside a string or comment" (nth 8 (syntax-ppss))) (defun hashbang-line\? nil "Does the current line contain a UNIX hashbang?" (and (eq 1 (line-number-at-pos)) (save-excursion (move-beginning-of-line nil) (looking-at "#!")))) (defun enclosing-paren nil "Return the opening parenthesis of the enclosing parens, or nil\nif not inside any parens." (interactive) (let ((ppss (syntax-ppss))) (when (nth 1 ppss) (char-after (nth 1 ppss))))) (defun probably-unary-operator\? nil "Try to guess if the operator we are about to insert will be unary\n\n(i.e. takes one argument). This is a bit of a fudge based on C-like syntax." (or (looking-back "^") (looking-back "[=,:*+-/><&^([{]") (looking-back "\\(return\\)"))) (defun docs-\. nil "Double space if setting tells us to" (if double-space-docs ".  " ". ")) (defun prog-mode-- nil "Handle exponent and negative number notation" (cond ((looking-back "[0-9.]+[eE]") "-") ((probably-unary-operator\?) (if (or (looking-back "[[(]") (looking-back "^")) "-" " -")) (t " - "))) (defun prog-mode-/ nil "Handle path separator in UNIX hashbangs" (cond ((and (hashbang-line\?) (looking-back "#!")) " /") ((hashbang-line\?) "/") (t " / "))) (apply (function add-rules-for-mode) (quote c-mode) prog-mode-rules) (add-rules-for-mode (quote c-mode) (cons "->" "->") (cons "?" " ? ") (cons ":" (function c-mode-:)) (cons "*" (function c-mode-*)) (cons "&" (function c-mode-&)) (cons "**" (function c-mode-**)) (cons "++" (function c-mode-++)) (cons "--" (function c-mode---)) (cons "<" (function c-mode-<)) (cons ">" (function c-mode->)) (cons "<<" " << ") (cons ">>" " >> ") (cons "/*" "/* ") (cons "//" "// ") (cons "++;" "++;") (cons "--;" "--;") (cons "%=" " %= ") (cons "^=" " ^= ") (cons "&=" " &= ") (cons "|=" " |= ") (cons "<<=" " <<= ") (cons ">>=" " >>= ")) (puthash (quote c++-mode) (gethash (quote c-mode) mode-rules-table) mode-rules-table) (add-rules-for-mode (quote c++-mode) (cons "&&" (function c++-mode-&&)) (cons ">>" (function c++-mode->>))) (defvar c-user-types-regex "_t" "Regex used in looking-back to check for C types\n\nFor now we just assume that anything ending in '_t' is a type.\nI'm not sure if we can do any better by default.\n\nYou could add your own type names to this if needed. Send pull\nrequests/bug reports if you find any widely used type names that\ncould be added here.") (defun c-after-type\? nil (or (looking-back (concat c-primitive-type-key "?")) (looking-back c-user-types-regex))) (defvar c-function-definition-syntax-list (quote (topmost-intro topmost-intro-cont arglist-intro arglist-cont-nonempty)) "syntax symbols for lines which contain a function definition\n\nSee `c-guess-basic-syntax'.") (defun c-is-function-definition\? nil "Try to guess if we are in function definition/declaration\n\nUsing `cc-mode''s syntactic analysis." (->> (c-guess-basic-syntax) (-map (function car)) (-intersection c-function-definition-syntax-list))) (defun c-mode-: nil "Handle the : part of ternary operator" (if (looking-back "\\?.+") " : " ":")) (defun c-mode-++ nil "Handle ++ operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "++ " " ++")) (defun c-mode--- nil "Handle -- operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "-- " " --")) (defun c-mode-< nil "Handle #include brackets and templates" (cond ((looking-back "# *include *") " <") ((c-is-function-definition\?) "<") (t " < "))) (defun c-mode-> nil "Handle #include brackets and templates" (cond ((looking-back "# *include.*") ">") ((c-is-function-definition\?) "> ") (t " > "))) (defun c++-mode->> nil "Handle nested templates" (cond ((c-is-function-definition\?) ">> ") (t " >> "))) (defun c-space-pointer-type (op) "Space a C pointer types operator as specified by\n  `c-pointer-type-style'.\n\n For example `int* x'  or `int *x'." (cond ((eq c-pointer-type-style (quote variable)) (concat " " op)) ((eq c-pointer-type-style (quote type)) (concat op " ")) (t (error "Unrecognised value for c-pointer-type-style.")))) (defun c-mode-& nil "Handle C address-of operator and reference types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "&")) ((looking-back "(") "&") ((probably-unary-operator\?) " &") (t " & "))) (defun c-mode-* nil "Handle C dereference operator and pointer types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "*")) ((looking-back "(") "*") ((probably-unary-operator\?) " *") (t " * "))) (defun c-mode-** nil "C pointer to pointer." (c-space-pointer-type "**")) (defun c++-mode-&& nil "Handle move constructor" (if (c-is-function-definition\?) (c-space-pointer-type "&&") " && ")) (apply (function add-rules-for-mode) (quote python-mode) prog-mode-rules) (add-rules-for-mode (quote python-mode) (cons "**" (function python-mode-**)) (cons "*" (function python-mode-*)) (cons ":" (function python-mode-:)) (cons "//" " // ") (cons "=" (function python-mode-kwargs-=)) (cons "-" (function python-mode-negative-slices))) (defun python-mode-: nil "Handle python dict assignment" (if (and (not (in-string-p)) (eq (enclosing-paren) 123)) ": " ":")) (defun python-mode-* nil "Handle python *args" (cond ((looking-back ",") " *") ((looking-back "[(,^)][  ]*") "*") (t " * "))) (defun python-mode-** nil "Handle python **kwargs" (cond ((looking-back ",") " **") ((looking-back "[(,^)][   ]*") "**") (t " ** "))) (defun python-mode-kwargs-= nil (if (eq (enclosing-paren) 40) "=" " = ")) (defun python-mode-negative-slices nil "Handle cases like a[1:-1], see issue #2." (if (and (eq (enclosing-paren) 91) (looking-back ":")) "-" (prog-mode--))) (puthash (quote ruby-mode) (add-rules prog-mode-rules (cons "=~" " =~ ")) mode-rules-table) (puthash (quote perl-mode) (add-rules prog-mode-rules (cons "=~" " =~ ")) mode-rules-table) (puthash (quote cperl-mode) (gethash (quote cperl-mode) mode-rules-table) mode-rules-table) (puthash (quote java-mode) (add-rules prog-mode-rules (cons "?" " ? ") (cons ":" (function c-mode-:)) (cons "++" (function c-mode-++)) (cons "--" (function c-mode---)) (cons "<<" " << ") (cons ">>" " >> ") (cons ">>>" " >>> ") (cons "%=" " %= ") (cons "^=" " ^= ") (cons "&=" " &= ") (cons "|=" " |= ") (cons "<<=" " <<= ") (cons ">>=" " >>= ") (cons "/*" "/* ") (cons "//" "// ")) mode-rules-table) (puthash (quote haskell-mode) (add-rules prog-mode-rules (cons "." " . ") (cons "++" " ++ ") (cons "!!" " !! ") (cons "--" "-- ") (cons "$" " $ ") (cons "<-" " <- ") (cons "->" " -> ") (cons ":" nil) (cons "::" " :: ") (cons "!=" nil) (cons ".|." " .|. ") (cons ".&." " .&. ") (cons "^" " ^ ") (cons "**" " ** ") (cons "^^" " ^^ ")) mode-rules-table) (puthash (quote ess-mode) (add-rules prog-mode-rules (cons "." nil) (cons "<-" " <- ")) mode-rules-table) (eval-after-load (quote ess-mode) (advice-add (quote ess-smart-comma) :after (function post-self-insert-function))))
  macroexpand((define-namespace electric-operator- :functionlike-macros (-> ->>) (defcustom double-space-docs nil "Enable double spacing of . in document lines - e,g, type '.' => get '.  '." :type (quote boolean) :group (quote electricity)) (defcustom enable-in-docs nil "Enable electric-operator in strings and comments." :type (quote boolean) :group (quote electricity)) (defcustom c-pointer-type-style (quote variable) "Defines how C/C++ mode pointer and reference types are spaced.\n\nIf set to 'variable then the operator is touching the variable\nname, as in `int *x'.\n\nIf set to 'type then the operator is touching the type name , as\nin `int* x'." :group (quote electricity) :options (quote (variable type))) (defvar mode-rules-table (make-hash-table) "A hash table of replacement rule lists for specific major modes") (defun -add-rule (initial new-rule) "Replace or append a new rule\n\nReturns a modified copy of the rule list." (let* ((op (car new-rule)) (existing-rule (assoc op initial))) (if existing-rule (-replace existing-rule new-rule initial) (-snoc initial new-rule)))) (defun -add-rule-list (initial new-rules) "Replace or append a list of rules\n\nReturns a modified copy of the rule list." (-reduce (function -add-rule) (-concat (list initial) new-rules))) (defun add-rules (initial &rest new-rules) "Replace or append multiple rules\n\nReturns a modified copy of the rule list." (-add-rule-list initial new-rules)) (defun add-rules-for-mode (major-mode-symbol &rest new-rules) "Replace or add spacing rules for major mode\n\nDestructively modifies mode-rules-table to use the new rules for\nthe given major mode." (puthash major-mode-symbol (-add-rule-list (gethash major-mode-symbol mode-rules-table) new-rules) mode-rules-table)) (defvar prog-mode-rules (list (cons "=" " = ") (cons "<" " < ") (cons ">" " > ") (cons "%" " % ") (cons "+" " + ") (cons "-" (function prog-mode--)) (cons "*" " * ") (cons "/" (function prog-mode-/)) (cons "&" " & ") (cons "|" " | ") (cons "?" "? ") (cons "," ", ") (cons "^" " ^ ") (cons "==" " == ") (cons "!=" " != ") (cons "<=" " <= ") (cons ">=" " >= ") (cons "*=" " *= ") (cons "+=" " += ") (cons "/=" " /= ") (cons "-=" " -= ") (cons "&&" " && ") (cons "||" " || ")) "Default spacing rules for programming modes") (defvar prose-rules (add-rules (quote nil) (cons "." (function docs-\.)) (cons "," ", ")) "Rules to use in comments, strings and text modes.") (defun get-rules-list nil "Pick which rule list is appropriate for spacing at point" (cond ((in-docs\?) (if enable-in-docs prose-rules (list))) ((gethash major-mode mode-rules-table)) ((derived-mode-p (quote prog-mode)) prog-mode-rules) (t prose-rules))) (defun rule-regex-with-whitespace (op) "Construct regex matching operator and any whitespace before/inside/after.\n\nFor example for the operator '+=' we allow '+=', ' +=', '+ ='. etc.\n\nWhitespace before the operator is captured for possible use later.\n" (concat "\\( *\\)" (mapconcat (function regexp-quote) (split-string op "" t) " *") " *")) (defun longest-matching-rule (rule-list) "Return the rule with the most characters that applies to text before point" (->> rule-list (-filter (lambda (rule) (looking-back (rule-regex-with-whitespace (car rule))))) (-sort (lambda (p1 p2) (> (length (car p1)) (length (car p2))))) (car))) (defun post-self-insert-function nil "Check for a matching rule and apply it" (-let* ((rule (longest-matching-rule (get-rules-list))) ((operator . action) rule)) (when (and rule action) (looking-back (rule-regex-with-whitespace operator) nil t) (let ((pre-whitespace (match-string 1))) (delete-region (match-beginning 0) (match-end 0)) (if (looking-back "^ *") (insert pre-whitespace)) (if (stringp action) (insert action) (insert (funcall action))))))) :autoload (define-minor-mode mode "Toggle automatic insertion of spaces around operators (Electric Spacing mode).\n\nWith a prefix argument ARG, enable Electric Spacing mode if ARG is\npositive, and disable it otherwise.  If called from Lisp, enable\nthe mode if ARG is omitted or nil.\n\nThis is a local minor mode.  When enabled, typing an operator automatically\ninserts surrounding spaces, e.g., `=' becomes ` = ',`+=' becomes ` += '." :global nil :group (quote electricity) :lighter " _+_" (if mode (add-hook (quote post-self-insert-hook) (function post-self-insert-function) nil t) (remove-hook (quote post-self-insert-hook) (function post-self-insert-function) t))) (defun in-docs\? nil "Check if we are inside a string or comment" (nth 8 (syntax-ppss))) (defun hashbang-line\? nil "Does the current line contain a UNIX hashbang?" (and (eq 1 (line-number-at-pos)) (save-excursion (move-beginning-of-line nil) (looking-at "#!")))) (defun enclosing-paren nil "Return the opening parenthesis of the enclosing parens, or nil\nif not inside any parens." (interactive) (let ((ppss (syntax-ppss))) (when (nth 1 ppss) (char-after (nth 1 ppss))))) (defun probably-unary-operator\? nil "Try to guess if the operator we are about to insert will be unary\n\n(i.e. takes one argument). This is a bit of a fudge based on C-like syntax." (or (looking-back "^") (looking-back "[=,:*+-/><&^([{]") (looking-back "\\(return\\)"))) (defun docs-\. nil "Double space if setting tells us to" (if double-space-docs ".  " ". ")) (defun prog-mode-- nil "Handle exponent and negative number notation" (cond ((looking-back "[0-9.]+[eE]") "-") ((probably-unary-operator\?) (if (or (looking-back "[[(]") (looking-back "^")) "-" " -")) (t " - "))) (defun prog-mode-/ nil "Handle path separator in UNIX hashbangs" (cond ((and (hashbang-line\?) (looking-back "#!")) " /") ((hashbang-line\?) "/") (t " / "))) (apply (function add-rules-for-mode) (quote c-mode) prog-mode-rules) (add-rules-for-mode (quote c-mode) (cons "->" "->") (cons "?" " ? ") (cons ":" (function c-mode-:)) (cons "*" (function c-mode-*)) (cons "&" (function c-mode-&)) (cons "**" (function c-mode-**)) (cons "++" (function c-mode-++)) (cons "--" (function c-mode---)) (cons "<" (function c-mode-<)) (cons ">" (function c-mode->)) (cons "<<" " << ") (cons ">>" " >> ") (cons "/*" "/* ") (cons "//" "// ") (cons "++;" "++;") (cons "--;" "--;") (cons "%=" " %= ") (cons "^=" " ^= ") (cons "&=" " &= ") (cons "|=" " |= ") (cons "<<=" " <<= ") (cons ">>=" " >>= ")) (puthash (quote c++-mode) (gethash (quote c-mode) mode-rules-table) mode-rules-table) (add-rules-for-mode (quote c++-mode) (cons "&&" (function c++-mode-&&)) (cons ">>" (function c++-mode->>))) (defvar c-user-types-regex "_t" "Regex used in looking-back to check for C types\n\nFor now we just assume that anything ending in '_t' is a type.\nI'm not sure if we can do any better by default.\n\nYou could add your own type names to this if needed. Send pull\nrequests/bug reports if you find any widely used type names that\ncould be added here.") (defun c-after-type\? nil (or (looking-back (concat c-primitive-type-key "?")) (looking-back c-user-types-regex))) (defvar c-function-definition-syntax-list (quote (topmost-intro topmost-intro-cont arglist-intro arglist-cont-nonempty)) "syntax symbols for lines which contain a function definition\n\nSee `c-guess-basic-syntax'.") (defun c-is-function-definition\? nil "Try to guess if we are in function definition/declaration\n\nUsing `cc-mode''s syntactic analysis." (->> (c-guess-basic-syntax) (-map (function car)) (-intersection c-function-definition-syntax-list))) (defun c-mode-: nil "Handle the : part of ternary operator" (if (looking-back "\\?.+") " : " ":")) (defun c-mode-++ nil "Handle ++ operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "++ " " ++")) (defun c-mode--- nil "Handle -- operator pre/postfix" (if (looking-back "[a-zA-Z0-9_] *") "-- " " --")) (defun c-mode-< nil "Handle #include brackets and templates" (cond ((looking-back "# *include *") " <") ((c-is-function-definition\?) "<") (t " < "))) (defun c-mode-> nil "Handle #include brackets and templates" (cond ((looking-back "# *include.*") ">") ((c-is-function-definition\?) "> ") (t " > "))) (defun c++-mode->> nil "Handle nested templates" (cond ((c-is-function-definition\?) ">> ") (t " >> "))) (defun c-space-pointer-type (op) "Space a C pointer types operator as specified by\n  `c-pointer-type-style'.\n\n For example `int* x'  or `int *x'." (cond ((eq c-pointer-type-style (quote variable)) (concat " " op)) ((eq c-pointer-type-style (quote type)) (concat op " ")) (t (error "Unrecognised value for c-pointer-type-style.")))) (defun c-mode-& nil "Handle C address-of operator and reference types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "&")) ((looking-back "(") "&") ((probably-unary-operator\?) " &") (t " & "))) (defun c-mode-* nil "Handle C dereference operator and pointer types" (cond ((or (c-after-type\?) (c-is-function-definition\?)) (c-space-pointer-type "*")) ((looking-back "(") "*") ((probably-unary-operator\?) " *") (t " * "))) (defun c-mode-** nil "C pointer to pointer." (c-space-pointer-type "**")) (defun c++-mode-&& nil "Handle move constructor" (if (c-is-function-definition\?) (c-space-pointer-type "&&") " && ")) (apply (function add-rules-for-mode) (quote python-mode) prog-mode-rules) (add-rules-for-mode (quote python-mode) (cons "**" (function python-mode-**)) (cons "*" (function python-mode-*)) (cons ":" (function python-mode-:)) (cons "//" " // ") (cons "=" (function python-mode-kwargs-=)) (cons "-" (function python-mode-negative-slices))) (defun python-mode-: nil "Handle python dict assignment" (if (and (not (in-string-p)) (eq (enclosing-paren) 123)) ": " ":")) (defun python-mode-* nil "Handle python *args" (cond ((looking-back ",") " *") ((looking-back "[(,^)][   ]*") "*") (t " * "))) ...))
  ad-Advice-make-autoload(#[770 "C\211\242\242\301\203\201\302=\203\201\242A\211A\211@A\211\303:\203n@A\304=\203\360

davidshepherd7 avatar Jul 23 '15 11:07 davidshepherd7