;; Author: Artur Malabarba <emacs@endlessparentheses.com>
;; Keywords: convenience, lisp
-;; Version: 0.3
+;; Version: 0.5
;; Package-Requires: ((emacs "24.4"))
;; This program is free software; you can redistribute it and/or modify
:type '(alist string string))
(defvar nameless-aliases nil
- "Alist from namespaces to aliases.
-Samse syntax as `nameless-global-aliases', but designed to be
-used as a file-local variable.")
+ "Alist from aliases to namespaces.
+This variable takes the same syntax and has the same effect as
+`nameless-global-aliases'. Aliases set here take priority over
+those in `nameless-global-aliases'.
+This variable is designed to be used as a file-local or dir-local
+variable.")
+(put 'nameless-aliases 'safe-local-variable
+ (lambda (x) (ignore-errors
+ (let ((safe t))
+ (mapc (lambda (cell)
+ (unless (and (stringp (car cell))
+ (stringp (cdr cell)))
+ (setq safe nil)))
+ x)
+ safe))))
(defface nameless-face
'((t :inherit font-lock-type-face))
(const :tag "Don't affect indentation" nil)
(const :tag "Only outside strings" 'outside-strings)))
+(defcustom nameless-private-prefix nil
+ "If non-nil, private symbols are displayed with a double prefix.
+For instance, the function `foobar--internal-impl' will be
+displayed as `::internal-impl', instead of `:-internal-impl'."
+ :type 'boolean)
+
\f
;;; Font-locking
(defun nameless--make-composition (s)
(defvar nameless-mode)
(defun nameless--compose-as (display)
"Compose the matched region and return a face spec."
- (when nameless-mode
+ (when (and nameless-mode
+ (not (get-text-property (match-beginning 1) 'composition))
+ (not (get-text-property (match-beginning 1) 'display)))
(let ((compose (save-match-data
(and nameless-affect-indentation-and-filling
- (or (not (eq nameless-affect-indentation-and-filling 'outside-strings))
- (not (nth 3 (syntax-ppss)))))))
+ (or (not (eq nameless-affect-indentation-and-filling 'outside-strings))
+ (not (nth 3 (syntax-ppss)))))))
(dis (concat display nameless-prefix)))
(when compose
- (compose-region (match-beginning 1)
- (match-end 1)
- (nameless--make-composition dis)))
+ (if (and nameless-private-prefix
+ (equal "-" (substring (match-string 0) -1)))
+ (progn
+ (setq dis (concat dis nameless-prefix))
+ (compose-region (match-beginning 0)
+ (match-end 0)
+ (nameless--make-composition dis)))
+ (compose-region (match-beginning 1)
+ (match-end 1)
+ (nameless--make-composition dis))))
`(face nameless-face ,@(unless compose (list 'display dis))))))
(defvar-local nameless--font-lock-keywords nil)
(nameless--ensure))
(defun nameless--add-keywords (&rest r)
- "Add font-lock keywords displaying REGEXP as DISPLAY.
+ "Add font-lock keywords displaying ALIAS as DISPLAY.
+ALIAS may be nil, in which case it refers to `nameless-current-name'.
-\(fn (regexp . display) [(regexp . display) ...])"
+\(fn (alias . display) [(alias . display) ...])"
(setq-local font-lock-extra-managed-props
`(composition display ,@font-lock-extra-managed-props))
- (let ((kws (mapcar (lambda (x) `(,(nameless--name-regexp (cdr x)) 1 (nameless--compose-as ,(car x)) prepend)) r)))
+ (let ((kws (mapcar (lambda (x) `(,(nameless--name-regexp (cdr x)) 1 (nameless--compose-as ,(car x)))) r)))
(setq nameless--font-lock-keywords kws)
(font-lock-add-keywords nil kws t))
(nameless--ensure))
\f
;;; Name and regexp
(defvar-local nameless-current-name nil)
+(put 'nameless-current-name 'safe-local-variable #'stringp)
-(defun nameless--in-arglist-p ()
- "Is point inside an arglist?"
+(defun nameless--in-arglist-p (l)
+ "Is point L inside an arglist?"
(save-excursion
+ (goto-char l)
(ignore-errors
(backward-up-list)
(or (progn (forward-sexp -1)
(looking-at-p "[a-z-]lambda\\_>"))
(progn (forward-sexp -1)
- (looking-at-p "\\(cl-\\)?def\\(un\\|macro\\|inline\\)\\*?\\_>"))))))
+ (looking-at-p "\\(cl-\\)?def"))))))
(defun nameless-insert-name (&optional noerror)
"Insert `nameless-current-name' or the alias at point.
(assoc alias nameless-global-aliases))))))
(if full-name
(progn (delete-region l r)
- (insert full-name "-"))
+ (insert full-name "-")
+ t)
(unless noerror
(user-error "No name for alias `%s', see `nameless-aliases'" alias))))
(if nameless-current-name
(defun nameless-insert-name-or-self-insert (&optional self-insert)
"Insert the name of current package, with a hyphen."
(interactive "P")
- (if (or self-insert
- (not nameless-current-name)
- (eq (char-before) ?\\)
- (nameless--in-arglist-p))
- (call-interactively #'self-insert-command)
- (or (nameless-insert-name 'noerror)
- (call-interactively #'self-insert-command))))
+ (let ((l (point)))
+ (call-interactively #'self-insert-command)
+ (unless (or self-insert
+ (not nameless-current-name)
+ (eq (char-before l) ?\\)
+ (nameless--in-arglist-p l))
+ (undo-boundary)
+ (delete-region l (point))
+ (unless (nameless-insert-name 'noerror)
+ (call-interactively #'self-insert-command)))))
+
+(put 'nameless-insert-name-or-self-insert 'delete-selection t)
(defun nameless--name-regexp (name)
"Return a regexp of the current name."
;;; Minor mode
;;;###autoload
(define-minor-mode nameless-mode
- nil nil " :" '(("_" . nameless-insert-name-or-self-insert))
+ nil nil " :" `((,(kbd "C-c C--") . nameless-insert-name))
(if nameless-mode
(if (or nameless-current-name
(ignore-errors (string-match "\\.el\\'" (lm-get-package-name))))
(progn
(unless nameless-current-name
- (setq nameless-current-name (replace-regexp-in-string "\\.[^.]*\\'" "" (lm-get-package-name))))
+ (setq nameless-current-name (replace-regexp-in-string "\\(-mode\\)?\\.[^.]*\\'" "" (lm-get-package-name))))
(add-function :filter-return (local 'filter-buffer-substring-function)
#'nameless--filter-string)
(apply #'nameless--add-keywords
(setq nameless-current-name nil)
(nameless--remove-keywords)))
+;;;###autoload
+(defun nameless-mode-from-hook ()
+ "Turn on `nameless-mode'.
+Designed to be added to `emacs-lisp-mode-hook'.
+Interactively, just invoke `nameless-mode' directly."
+ (add-hook 'find-file-hook #'nameless-mode nil 'local))
+
(provide 'nameless)
;;; nameless.el ends here