summaryrefslogtreecommitdiff
path: root/elisp.el
diff options
context:
space:
mode:
Diffstat (limited to 'elisp.el')
-rw-r--r--elisp.el237
1 files changed, 237 insertions, 0 deletions
diff --git a/elisp.el b/elisp.el
new file mode 100644
index 0000000..b1f1be4
--- /dev/null
+++ b/elisp.el
@@ -0,0 +1,237 @@
+;;; -*- lexical-binding: t; -*-
+
+;;; a simpler mode name
+
+(add-hook 'emacs-lisp-mode-hook
+ (lambda () (set 'mode-name "ELisp")))
+
+;;; fontification of extra keywords in emacs lisp files
+
+(require 'advice)
+
+(font-lock-add-keywords
+ 'emacs-lisp-mode
+ `(("^;;;###\\(autoload\\)[ \n]" (1 font-lock-warning-face t))
+ (emacs-lisp-highlight-vars-and-faces . emacs-lisp-face)
+ ("\\(\\(?:#'\\|['`]\\)\\)\\(?:[[:space:]]*\\(\\(?:\\sw\\|\\s_\\)+\\)\\)?"
+ (1 font-lock-keyword-face)
+ (2 font-lock-constant-face nil t))))
+
+;;;###autoload
+(defvar emacs-lisp-face nil
+ "The face used to highlight extra emacs lisp keywords.")
+
+;;;###autoload
+(defun emacs-lisp-highlight-vars-and-faces (end)
+ (catch 'matcher
+ (while (re-search-forward "\\(?:\\sw\\|\\s_\\)+" end t)
+ (let ((ppss (save-excursion (syntax-ppss))))
+ (cond ((nth 3 ppss) ; strings
+ (search-forward "\"" end t))
+ ((nth 4 ppss) ; comments
+ (forward-line +1))
+ ((let ((symbol (intern-soft (match-string-no-properties 0))))
+ (and (cond ((null symbol) nil)
+ ((eq symbol t) nil)
+ ((keywordp symbol) nil)
+ ((special-variable-p symbol)
+ (setq emacs-lisp-face 'font-lock-variable-name-face))
+ ((and (fboundp symbol)
+ (eq (char-before (match-beginning 0)) ?\()
+ (not (memq (char-before (1- (match-beginning 0)))
+ (list ?\' ?\`))))
+ (let ((unaliased (indirect-function symbol)))
+ (cond ((or (macrop unaliased)
+ (special-form-p unaliased))
+ (setq emacs-lisp-face 'font-lock-keyword-face))
+ (t
+ (let (unadvised)
+ (while (not (eq (setq unadvised (ad-get-orig-definition unaliased))
+ (setq unaliased (indirect-function unadvised)))))
+ unaliased)
+ (setq emacs-lisp-face
+ (if (subrp unaliased)
+ 'font-lock-constant-face
+ 'font-lock-function-name-face)))))))
+ (throw 'matcher t)))))))
+ nil))
+
+;;; a better indentation
+
+(advice-add #'calculate-lisp-indent :override #'better-calculate-lisp-indent)
+
+;;;###autoload
+(defun better-calculate-lisp-indent (&optional parse-start)
+ "Add better indentation for quoted and backquoted lists."
+ ;; This line because `calculate-lisp-indent-last-sexp` was defined with `defvar`
+ ;; with it's value ommited, marking it special and only defining it locally. So
+ ;; if you don't have this, you'll get a void variable error.
+ (defvar calculate-lisp-indent-last-sexp)
+ (save-excursion
+ (beginning-of-line)
+ (let ((indent-point (point))
+ state
+ ;; setting this to a number inhibits calling hook
+ (desired-indent nil)
+ (retry t)
+ calculate-lisp-indent-last-sexp containing-sexp)
+ (cond ((or (markerp parse-start) (integerp parse-start))
+ (goto-char parse-start))
+ ((null parse-start) (beginning-of-defun))
+ (t (setq state parse-start)))
+ (unless state
+ ;; Find outermost containing sexp
+ (while (< (point) indent-point)
+ (setq state (parse-partial-sexp (point) indent-point 0))))
+ ;; Find innermost containing sexp
+ (while (and retry
+ state
+ (> (elt state 0) 0))
+ (setq retry nil)
+ (setq calculate-lisp-indent-last-sexp (elt state 2))
+ (setq containing-sexp (elt state 1))
+ ;; Position following last unclosed open.
+ (goto-char (1+ containing-sexp))
+ ;; Is there a complete sexp since then?
+ (if (and calculate-lisp-indent-last-sexp
+ (> calculate-lisp-indent-last-sexp (point)))
+ ;; Yes, but is there a containing sexp after that?
+ (let ((peek (parse-partial-sexp calculate-lisp-indent-last-sexp
+ indent-point 0)))
+ (if (setq retry (car (cdr peek))) (setq state peek)))))
+ (if retry
+ nil
+ ;; Innermost containing sexp found
+ (goto-char (1+ containing-sexp))
+ (if (not calculate-lisp-indent-last-sexp)
+ ;; indent-point immediately follows open paren.
+ ;; Don't call hook.
+ (setq desired-indent (current-column))
+ ;; Find the start of first element of containing sexp.
+ (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
+ (cond ((looking-at "\\s(")
+ ;; First element of containing sexp is a list.
+ ;; Indent under that list.
+ )
+ ((> (save-excursion (forward-line 1) (point))
+ calculate-lisp-indent-last-sexp)
+ ;; This is the first line to start within the containing sexp.
+ ;; It's almost certainly a function call.
+ (if (or
+ ;; Containing sexp has nothing before this line
+ ;; except the first element. Indent under that element.
+ (= (point) calculate-lisp-indent-last-sexp)
+
+ ;; First sexp after `containing-sexp' is a keyword. This
+ ;; condition is more debatable. It's so that I can have
+ ;; unquoted plists in macros. It assumes that you won't
+ ;; make a function whose name is a keyword.
+ ;; (when-let (char-after (char-after (1+ containing-sexp)))
+ ;; (char-equal char-after ?:))
+
+ ;; Check for quotes or backquotes around.
+ (let* ((positions (elt state 9))
+ (last (car (last positions)))
+ (rest (reverse (butlast positions)))
+ (any-quoted-p nil)
+ (point nil))
+ (or
+ (when-let (char (char-before last))
+ (or (char-equal char ?')
+ (char-equal char ?`)))
+ (progn
+ (while (and rest (not any-quoted-p))
+ (setq point (pop rest))
+ (setq any-quoted-p
+ (or
+ (when-let (char (char-before point))
+ (or (char-equal char ?')
+ (char-equal char ?`)))
+ (save-excursion
+ (goto-char (1+ point))
+ (looking-at-p
+ "\\(?:back\\)?quote[\t\n\f\s]+(")))))
+ any-quoted-p))))
+ ;; Containing sexp has nothing before this line
+ ;; except the first element. Indent under that element.
+ nil
+ ;; Skip the first element, find start of second (the first
+ ;; argument of the function call) and indent under.
+ (progn (forward-sexp 1)
+ (parse-partial-sexp (point)
+ calculate-lisp-indent-last-sexp
+ 0 t)))
+ (backward-prefix-chars))
+ (t
+ ;; Indent beneath first sexp on same line as
+ ;; `calculate-lisp-indent-last-sexp'. Again, it's
+ ;; almost certainly a function call.
+ (goto-char calculate-lisp-indent-last-sexp)
+ (beginning-of-line)
+ (parse-partial-sexp (point) calculate-lisp-indent-last-sexp
+ 0 t)
+ (backward-prefix-chars)))))
+ ;; Point is at the point to indent under unless we are inside a string.
+ ;; Call indentation hook except when overridden by lisp-indent-offset
+ ;; or if the desired indentation has already been computed.
+ (let ((normal-indent (current-column)))
+ (cond ((elt state 3)
+ ;; Inside a string, don't change indentation.
+ nil)
+ ((and (integerp lisp-indent-offset) containing-sexp)
+ ;; Indent by constant offset
+ (goto-char containing-sexp)
+ (+ (current-column) lisp-indent-offset))
+ ;; in this case calculate-lisp-indent-last-sexp is not nil
+ (calculate-lisp-indent-last-sexp
+ (or
+ ;; try to align the parameters of a known function
+ (and lisp-indent-function
+ (not retry)
+ (funcall lisp-indent-function indent-point state))
+ ;; If the function has no special alignment
+ ;; or it does not apply to this argument,
+ ;; try to align a constant-symbol under the last
+ ;; preceding constant symbol, if there is such one of
+ ;; the last 2 preceding symbols, in the previous
+ ;; uncommented line.
+ (and (save-excursion
+ (goto-char indent-point)
+ (skip-chars-forward " \t")
+ (looking-at ":"))
+ ;; The last sexp may not be at the indentation
+ ;; where it begins, so find that one, instead.
+ (save-excursion
+ (goto-char calculate-lisp-indent-last-sexp)
+ ;; Handle prefix characters and whitespace
+ ;; following an open paren. (Bug#1012)
+ (backward-prefix-chars)
+ (while (not (or (looking-back "^[ \t]*\\|([ \t]+"
+ (line-beginning-position))
+ (and containing-sexp
+ (>= (1+ containing-sexp) (point)))))
+ (forward-sexp -1)
+ (backward-prefix-chars))
+ (setq calculate-lisp-indent-last-sexp (point)))
+ (> calculate-lisp-indent-last-sexp
+ (save-excursion
+ (goto-char (1+ containing-sexp))
+ (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
+ (point)))
+ (let ((parse-sexp-ignore-comments t)
+ indent)
+ (goto-char calculate-lisp-indent-last-sexp)
+ (or (and (looking-at ":")
+ (setq indent (current-column)))
+ (and (< (line-beginning-position)
+ (prog2 (backward-sexp) (point)))
+ (looking-at ":")
+ (setq indent (current-column))))
+ indent))
+ ;; another symbols or constants not preceded by a constant
+ ;; as defined above.
+ normal-indent))
+ ;; in this case calculate-lisp-indent-last-sexp is nil
+ (desired-indent)
+ (t
+ normal-indent))))))