From: Artur Malabarba Date: Thu, 18 Jun 2015 17:14:30 +0000 (+0100) Subject: Merge commit 'b1da26d96cbe8308d0988f6b92737819f98f20fd' X-Git-Url: https://code.delx.au/gnu-emacs-elpa/commitdiff_plain/d75791d74e92fac5ab8c757276a048c4d029180c?hp=-c Merge commit 'b1da26d96cbe8308d0988f6b92737819f98f20fd' --- d75791d74e92fac5ab8c757276a048c4d029180c diff --combined packages/names/TheNittyGritty.org index 78bf88bb2,84bf6b873..84bf6b873 --- a/packages/names/TheNittyGritty.org +++ b/packages/names/TheNittyGritty.org @@@ -139,6 -139,41 +139,41 @@@ need to worry about, it should just do This is only relevant if you write your own macros. If you do, remember to add a debug declaration in them. + + *** The theading macros (~->~ and ~-->~) + + The threading macros would require special treatment to namespace + correctly. However, you can use the ~:functionlike-macros~ keyword to + tell *Names* to treat them as regular functions. + + For example, in the following snippet: + #+BEGIN_SRC emacs-lisp + (require 'dash) + (define-namespace foo- + :functionlike-macros (-> ->>) + + (defvar var nil) + (defun fun (x &optional y) + (concat x y)) + + (-> "some string" + (fun var) + fun) + ) + #+END_SRC + the ~(fun var)~ part would be namespaced prefectly fine (~fun~ and + ~var~ will be identified as a function and variable respectively), + because it looks like a regular function call. However, the second use + of ~fun~ will not be correctly namespaced, because that ~fun~ looks + like a variable. + + In other words, you should use these macros like this instead: + #+BEGIN_SRC emacs-lisp + (-> "some string" + (fun var) + (fun)) + #+END_SRC + ** Accessing Global Symbols If one of your definitions shadows a global definition, you can still access it by prefixing it with =::=. diff --combined packages/names/UsageExample.org index b27160e7d,5730966a1..5730966a1 --- a/packages/names/UsageExample.org +++ b/packages/names/UsageExample.org @@@ -14,7 -14,10 +14,10 @@@ The important items are already listed ;;; Code: - ;; `define-namespace' is autoloaded, so there's no need to require `names'. + ;; `define-namespace' is autoloaded, so there's no need to require + ;; `names'. However, requiring it here means it will also work for + ;; people who don't install through package.el. + (eval-when-compile (require 'names)) ;;;###autoload (define-namespace example- diff --combined packages/names/names-dev.el index 013360427,0c2dc2025..0c2dc2025 --- a/packages/names/names-dev.el +++ b/packages/names/names-dev.el @@@ -62,11 -62,11 +62,11 @@@ (defmacro names-print (name &rest forms) "Return the expanded results of (namespace NAME :global :verbose FORMS). Ideal for determining why a specific form isn't being parsed - correctly." + correctly. You may need to set `eval-expression-print-level' and + `eval-expression-print-length' to nil in order to see your full + expansion." (declare (indent (lambda (&rest x) 0)) (debug 0)) - `(let ((eval-expression-print-level (max eval-expression-print-level 300)) - (eval-expression-print-length (max eval-expression-print-length 300))) - (macroexpand '(define-namespace ,name :global :verbose ,@forms)))) + `(define-namespace ,name :global :verbose ,@forms)) (defvar names-font-lock '(("^:autoload\\_>" 0 'font-lock-warning-face prepend) @@@ -152,12 -152,17 +152,17 @@@ If KILL is non-nil, kill the temp buffe (kill-buffer b)))))) (defun names--top-of-namespace () - "" - (progn - (beginning-of-defun) - (ignore-errors - (backward-up-list) - (names--looking-at-namespace)))) + "Move to the top of current namespace, and return non-nil. + If not inside a namespace, return nil and don't move point." + (let ((top (save-excursion + (beginning-of-defun) + (ignore-errors + (backward-up-list)) + (when (names--looking-at-namespace) + (point))))) + (when top + (goto-char top) + t))) (defun names-eval-defun (edebug-it) "Identical to `eval-defun', except it works for forms inside namespaces. @@@ -176,7 -181,9 +181,9 @@@ to be edebugged. ;;; eval-last-sexp (defalias 'names--preceding-sexp-original - (symbol-function 'elisp--preceding-sexp)) + (if (fboundp 'elisp--preceding-sexp) + (symbol-function 'elisp--preceding-sexp) + (symbol-function 'preceding-sexp))) (defun names--preceding-sexp () "Like `elisp--preceding-sexp', but expand namespaces." @@@ -188,19 -195,28 +195,28 @@@ "Identical to `eval-last-sexp', except it works for forms inside namespaces. Argument EVAL-LAST-SEXP-ARG-INTERNAL is the same as `eval-last-sexp'." (interactive "P") - (cl-letf (((symbol-function 'elisp--preceding-sexp) - #'names--preceding-sexp)) + (cl-letf (((symbol-function 'elisp--preceding-sexp) #'names--preceding-sexp) + ((symbol-function 'preceding-sexp) #'names--preceding-sexp)) (eval-last-sexp eval-last-sexp-arg-internal))) (defun names-eval-print-last-sexp (eval-last-sexp-arg-internal) "Identical to `eval-print-last-sexp', except it works for forms inside namespaces. Argument EVAL-LAST-SEXP-ARG-INTERNAL is the same as `eval-print-last-sexp'." (interactive "P") - (cl-letf (((symbol-function 'elisp--preceding-sexp) - #'names--preceding-sexp)) + (cl-letf (((symbol-function 'elisp--preceding-sexp) #'names--preceding-sexp) + ((symbol-function 'preceding-sexp) #'names--preceding-sexp)) (eval-print-last-sexp eval-last-sexp-arg-internal))) - ;; (pp (symbol-function 'names-eval-defun) (current-buffer)) + ;; (pp (symbol-function 'names--preceding-sexp-original) (current-buffer)) + + (defun names-pprint () + "Pretty-print an expansion of the namespace around point." + (interactive) + (save-excursion + (when (names--top-of-namespace) + (let ((ns (cdr (read (current-buffer))))) + (pp-macroexpand-expression + (macroexpand (cons 'names-print ns))))))) ;;; Find stuff diff --combined packages/names/names.el index ee8768c84,b5f403e99..71bd0d172 --- a/packages/names/names.el +++ b/packages/names/names.el @@@ -5,7 -5,7 +5,7 @@@ ;; Author: Artur Malabarba ;; Maintainer: Artur Malabarba ;; URL: http://github.com/Bruce-Connor/names - ;; Version: 20150115.1 + ;; Version: 20150618.0 ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5")) ;; Keywords: extensions lisp ;; Prefix: names @@@ -64,7 -64,7 +64,7 @@@ "Load autoloaded definition DEF from function named NAME." (unless (load (cadr def) 'noerror) (error "Macro `%s' is autoloaded, but its file (%s) couldn't be loaded" - name (cadr def))) + name (cadr def))) (symbol-function name)) (lambda (f prop &rest _) @@@ -86,7 -86,8 +86,8 @@@ it will set PROP. (if (fboundp 'macrop) #'macrop (lambda (object) "Non-nil if and only if OBJECT is a macro." - (let ((def (indirect-function object t))) + (let ((def (or (ignore-errors (indirect-function object t)) + (ignore-errors (indirect-function object))))) (when (consp def) (or (eq 'macro (car def)) (and (names--autoloadp def) (memq (nth 4 def) '(macro t))))))))) @@@ -124,7 -125,7 +125,7 @@@ ;;; --------------------------------------------------------------- ;;; Variables - (defconst names-version "20150115.1" "Version of the names.el package.") + (defconst names-version "20150618.0" "Version of the names.el package.") (defvar names--name nil "Name of the current namespace inside the `define-namespace' macro.") @@@ -186,6 -187,22 +187,22 @@@ Is only non-nil if the :group keyword i "The version number given by :version. Used to define a constant and a command.") + (defvar names--functionlike-macros nil + "Function-like macros, even if their debug-spec says otherwise. + When expanding the namespace, these macros will be treated + exactly like functions. This means that their contents will be + namespaced like regular function arguments. + + To add macros to this list, pass the :functionlike-macros keyword + to your namespace along with a list of macro names (as unquoted + symbols). + Example: + + (define-namespace foo- + :functionlike-macros (-> ->> thread-first thread-last) + ;; Rest of code + )") + (defconst names--keyword-list `((:group 1 ,(lambda (x) @@@ -244,6 -261,12 +261,12 @@@ needed by the :version and :group keywo (format "\\`%s" (regexp-quote val))))) "Change the value of the `names--protection' variable.") + (:functionlike-macros + 1 + ,(lambda (x) (setq names--functionlike-macros + (append x names--functionlike-macros))) + "A list of values to be appended to `names--functionlike-macros'.") + (:no-let-vars 0 nil "Indicates variables assigned in let-bind are NOT candidates for namespacing.") @@@ -296,8 -319,8 +319,8 @@@ behaviour." (remove nil (mapcar (lambda (x) (when (funcall (or ,pred #'identity) (or (car-safe x) x)) - (or (car-safe x) x))) - ,var)))) + (or (car-safe x) x))) + ,var)))) (defmacro names--next-keyword (body) "If car of BODY is a known keyword, `pop' it (and its arguments) from body. @@@ -411,6 -434,7 +434,7 @@@ See `define-namespace' for more informa (names--remove-namespace-from-list (names--filter-if-bound byte-compile-macro-environment (lambda (x) (not (names--compat-macrop x)))) (names--filter-if-bound byte-compile-function-environment (lambda (x) (not (names--compat-macrop x)))))) + (names--functionlike-macros names--functionlike-macros) names--keywords names--local-vars key-and-args names--version names--package names--group-parent) ;; Read keywords @@@ -597,28 -621,29 +621,29 @@@ Also adds `version' to `names--fbound' byte-compile-macro-environment)))))))) ;;;###autoload - (defadvice find-function-search-for-symbol - (around names-around-find-function-search-for-symbol-advice - (symbol type library) activate) - "Make sure `find-function-search-for-symbol' understands namespaces." - ad-do-it - (ignore-errors - (unless (cdr ad-return-value) - (with-current-buffer (car ad-return-value) - (search-forward-regexp "^(define-namespace\\_>") - (skip-chars-forward "\r\n[:blank:]") - (let* ((names--regexp - (concat "\\`" (regexp-quote - (symbol-name (read (current-buffer)))))) - (short-symbol - ;; We manually implement `names--remove-namespace' - ;; because it might not be loaded. - (let ((name (symbol-name symbol))) - (when (string-match names--regexp name) - (intern (replace-match "" nil nil name)))))) - (when short-symbol - (ad-set-arg 0 short-symbol) - ad-do-it)))))) + (eval-after-load 'find-func + '(defadvice find-function-search-for-symbol + (around names-around-find-function-search-for-symbol-advice + (symbol type library) activate) + "Make sure `find-function-search-for-symbol' understands namespaces." + ad-do-it + (ignore-errors + (unless (cdr ad-return-value) + (with-current-buffer (car ad-return-value) + (search-forward-regexp "^(define-namespace\\_>") + (skip-chars-forward "\r\n[:blank:]") + (let* ((names--regexp + (concat "\\`" (regexp-quote + (symbol-name (read (current-buffer)))))) + (short-symbol + ;; We manually implement `names--remove-namespace' + ;; because it might not be loaded. + (let ((name (symbol-name symbol))) + (when (string-match names--regexp name) + (intern (replace-match "" nil nil name)))))) + (when short-symbol + (ad-set-arg 0 short-symbol) + ad-do-it))))))) (defun names--extract-autoloads (body) "Return a list of the forms in BODY preceded by :autoload." @@@ -749,7 -774,6 +774,6 @@@ returns nil. "If non-nil, verbose message are printed regardless of the :verbose keyword. Use this to easily turn on verbosity during tests.") - ;; This is calling edebug even on `when' and `unless' (defun names--args-of-function-or-macro (function args macro) "Namespace FUNCTION's arguments ARGS, with special treatment if MACRO is non-nil." (if macro @@@ -757,7 -781,8 +781,8 @@@ (names--verbose (eq function 'push))) (names--message "Edebug-spec of `%s' is %s" function it) ;; Macros where we evaluate all arguments are like functions. - (if (equal it t) + (if (or (equal it t) + (memq function names--functionlike-macros)) (names--args-of-function-or-macro function args nil) ;; Macros where nothing is evaluated we can just return. (if (equal it 0) @@@ -953,8 -978,7 +978,7 @@@ the keyword arguments, if any. ;; Defun, defmacro, and defsubst macros are pretty predictable. (defun names--convert-defmacro (form) "Special treatment for `defmacro' FORM." - (let* (;; (names--name-already-prefixed t) ;FIXME: Unused?! - (name (cadr form)) + (let* ((name (cadr form)) (spaced-name (names--prepend name)) decl) (add-to-list 'names--macro name)