Malabarba / names

A Namespace implementation for Emacs-Lisp
250 stars 19 forks source link

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

Open davidshepherd7 opened 9 years ago

davidshepherd7 commented 9 years ago

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
Malabarba commented 9 years ago

Hey david.

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

Yes. The problem is that this is happening during autoload generation, and not byte-compilation. So the dash library hasn't been required yet.

This is a Names bug. As long as you don't use any dash function or macro in your autoloads (and I see that you didn't), then autoload generation should work fine. I'll try to fix it asap.

Malabarba commented 9 years ago

Ok. This should be fixed in version 20150723.0. Let me know if it works for you.

davidshepherd7 commented 9 years ago

Perfect, and so fast! Thanks :+1: