Mercurial > hg > dotemacs
changeset 174:bd5ad617c85a
d-mode: update
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Sun, 07 Jan 2018 12:03:05 -0500 |
parents | 66cbafedef6c |
children | 56ea66d76309 |
files | dotemacs.el packages/d-mode.el |
diffstat | 2 files changed, 275 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/dotemacs.el +++ b/dotemacs.el @@ -184,6 +184,7 @@ '( ("\\.m\\'" . octave-mode) ("\\.eml\\'" . mail-mode) + ("\\.d[i]?\\'" . d-mode) ("\\.pro\\'" . conf-mode) ;; Qt project files ("\\.php\\'" . web-mode) ;; Default php mode isn't as good ("\\.?hgrc\\'" . conf-mode)
--- a/packages/d-mode.el +++ b/packages/d-mode.el @@ -2,14 +2,19 @@ ;;; Requires a cc-mode of version 5.30 or greater ;; Author: William Baxter -;; Contributors: Andrei Alexandrescu -;; Contributors: Russel Winder +;; Contributor: Andrei Alexandrescu +;; Contributor: Russel Winder ;; Maintainer: Russel Winder <russel@winder.org.uk> +;; Vladimir Panteleev <vladimir@thecybershadow.net> ;; Created: March 2007 -;; Version: 201512060745 +;; Version: 201610221417 ;; Keywords: D programming language emacs cc-mode -;;;; NB Version number is date and time yyyymmddhhMM in GMT (aka UTC). +;;;; NB Version number is date and time yyyymmddhhMM UTC. +;;;; A hook to update it automatically on save is available here: +;;;; https://gist.github.com/CyberShadow/28f60687c3bf83d32900cd6074c012cb + +;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -49,8 +54,9 @@ ;; https://github.com/Emacs-D-Mode-Maintainers/Emacs-D-Mode/issues ;;; Versions: -;; This mode is available on MELPA which tracks the mainline Git repository on GitHub, so there is a rolling release -;; system based on commits to the mainline. +;; This mode is available on MELPA which tracks the mainline Git repository on GitHub, so there is a +;; rolling release system based on commits to the mainline. For those wanting releases, the repository is +;; tagged from time to time and this creates an entry in MELPA Stable and a tarball on GitHub. ;;; Notes: @@ -72,8 +78,14 @@ (require 'compile) ;; The set-difference function is used from the Common Lisp extensions. +;; Note that this line produces a compilation warning in Emacs 24 and newer, +;; however the replacement (cl-seq.el for our use case) was introduced +;; in the same major version. (require 'cl) +;; Used to specify regular expressions in a sane way. +(require 'rx) + ;; These are only required at compile time to get the sources for the ;; language constants. (The cc-fonts require and the font-lock ;; related constants could additionally be put inside an @@ -183,25 +195,42 @@ ;;; Patterns to recognize the compiler generated messages -;; The following regexp recognizes messages generated by the LDC and DMD -;; compilers. Subexpression 1 is the filename, 2 is the line number, nil is the -;; column, because it's not present in the LDC error messages, and the -;; subexpressions 3 and 4 are the message type -- error, warning, or info. +(defun d-mode-add-dmd-message-pattern (expr level symbol) + "Register DMD `compile' pattern for an error level. -;; GDC messages are recognized by gnu symbol already listed in -;; compilation-error-regexp-alist. -(add-to-list 'compilation-error-regexp-alist-alist - '(ldc - "^\\([^: \n]+\\)(\\([0-9]+\\)): \\(?: *\\(?3:\\(?:W\\(?::\\|arning\\)\\|warning\\)\\)\\| *\\(?4:[Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|\\[ skipping \\.+ ]\\|instantiated from\\|required from\\|[Nn]ote\\)\\| *\\(?:[Ee]rror\\)\\| *Deprecation\\)" - 1 2 nil (3 . 4))) -(add-to-list 'compilation-error-regexp-alist 'ldc) +EXPR is the `rx' message sub-expression indicating the error level LEVEL. +The expression is added to `compilation-error-regexp-alist' and +`compilation-error-regexp-alist-alist' as SYMBOL." + (add-to-list + 'compilation-error-regexp-alist-alist + `(,symbol + ,(rx-form + `(and + line-start + (group-n 1 (one-or-more any)) ; File name + "(" + (group-n 2 (one-or-more digit)) ; Line number + (zero-or-one + "," + (group-n 3 (one-or-more digit))) ; Column number + "): " + ,expr + (group-n 4 (one-or-more nonl)) ; Message + line-end)) + 1 2 3 ,level 4)) + (add-to-list 'compilation-error-regexp-alist symbol)) + +(d-mode-add-dmd-message-pattern "Error: " 2 'dmd-error ) +(d-mode-add-dmd-message-pattern "Warning: " 1 'dmd-warning ) +(d-mode-add-dmd-message-pattern "Deprecation: " 1 'dmd-deprecation ) +(d-mode-add-dmd-message-pattern '(one-or-more " ") 0 'dmd-continuation) ;; The following regexp recognizes messages generated by the D runtime for ;; unhandled exceptions (e.g. assert failures). (add-to-list 'compilation-error-regexp-alist-alist '(d-exceptions - "^[^@]*?@\\(.*?\\)(\\([0-9]+\\)):" + "^[a-zA-z0-9\.]*?@\\(.*?\\)(\\([0-9]+\\)):" 1 2 nil 2)) (add-to-list 'compilation-error-regexp-alist 'd-exceptions) @@ -209,14 +238,14 @@ ;; Built-in basic types (c-lang-defconst c-primitive-type-kwds - d '("bit" "bool" "byte" "ubyte" "char" "delegate" "double" "float" + d '("bool" "byte" "ubyte" "char" "delegate" "double" "float" "function" "int" "long" "short" "uint" "ulong" "ushort" - "cent" "ucent" "real" "ireal" "ifloat" "creal" "cfloat" "cdouble" + "cent" "ucent" "real" "ireal" "idouble" "ifloat" "creal" "cfloat" "cdouble" "wchar" "dchar" "void" "string" "wstring" "dstring")) ;; Keywords that can prefix normal declarations of identifiers (c-lang-defconst c-modifier-kwds - d '("__gshared" "abstract" "const" "deprecated" "extern" + d '("__gshared" "abstract" "deprecated" "extern" "final" "in" "out" "inout" "lazy" "mixin" "override" "private" "protected" "public" "ref" "scope" "shared" "static" "synchronized" "volatile" "__vector")) @@ -230,7 +259,7 @@ ;; d '("enum")) (c-lang-defconst c-type-modifier-kwds - d '("__gshared" "const" "inout" "lazy" "shared" "volatile" + d '("__gshared" "inout" "lazy" "shared" "volatile" "invariant" "enum" "__vector")) (c-lang-defconst c-type-prefix-kwds @@ -259,7 +288,7 @@ (c-lang-defconst c-protection-kwds ;; Access protection label keywords in classes. d '("deprecated" "static" "extern" "final" "synchronized" "override" - "abstract" "scope" "const" "inout" "shared" "__gshared" + "abstract" "scope" "inout" "shared" "__gshared" "private" "package" "protected" "public" "export")) ;;(c-lang-defconst c-postfix-decl-spec-kwds @@ -436,15 +465,73 @@ (cons "D" (c-lang-const c-mode-menu d))) (defconst d-imenu-method-name-pattern - (concat - "^\\s-*" - "\\(?:[_a-z@]+\\s-+\\)*" ; qualifiers - "\\([][_a-zA-Z0-9.*!]+\\)\\s-+" ; type - "\\([_a-zA-Z0-9]+\\)\\s-*" ; function name - "\\(?:([^)]*)\\s-*\\)?" ; type arguments - "([^)]*)\\s-*" ; arguments - "\\(?:[a-z@]+\\s-*\\)?" ; pure/const etc. - "\\(?:;\\|[ \t\n]*\\(?:if\\|{\\)\\)")) ; ';' or 'if' or '{' + (rx + ;; Whitespace + bol + (zero-or-more space) + + ;; Conditionals + (zero-or-one + "else" + (zero-or-more space)) + (zero-or-one + "version" + (zero-or-more space) + "(" + (zero-or-more space) + (one-or-more (any "a-zA-Z0-9_")) + (zero-or-more space) + ")" + (zero-or-more space)) + + ;; Qualifiers + (zero-or-more + (one-or-more (any "a-z_@()C+")) + (one-or-more space)) + + ;; Type + (group + (one-or-more (any "a-zA-Z0-9_.*![]()"))) + (one-or-more space) + + ;; Function name + (group + (one-or-more (any "a-zA-Z0-9_"))) + (zero-or-more space) + + ;; Type arguments + (zero-or-one + "(" (zero-or-more (not (any ")"))) ")" + (zero-or-more space)) + + ;; Arguments + "(" + (zero-or-more (not (any "()"))) + (zero-or-more + "(" + (zero-or-more (not (any "()"))) + ")" + (zero-or-more (not (any "()")))) + ")" + (zero-or-more (any " \t\n")) + + ;; Pure/const etc. + (zero-or-more + (one-or-more (any "a-z@")) + (zero-or-more (any " \t\n"))) + + (zero-or-more + "//" + (zero-or-more not-newline) + (zero-or-more space)) + + ;; ';' or 'if' or '{' + (or + ";" + (and + (zero-or-more (any " \t\n")) + (or "if" "{"))) + )) (defun d-imenu-method-index-function () (and @@ -470,10 +557,127 @@ (not invis)))))) (defvar d-imenu-generic-expression - `(("*Classes*" "^\\s-*\\(?:\\(?:final\\|abstract\\)\\s-+\\)?\\<class\\s-+\\([a-zA-Z0-9_]+\\)" 1) - ("*Interfaces*" "^\\s-*\\<interface\\s-+\\([a-zA-Z0-9_]+\\)" 1) - ("*Structs*" "^\\s-*\\<struct\\s-+\\([a-zA-Z0-9_]+\\)" 1) - ("*Templates*" "^\\s-*\\(?:mixin\\s-+\\)?\\<template\\s-+\\([a-zA-Z0-9_]+\\)" 1) + `(("*Classes*" + ,(rx + line-start + (zero-or-more (syntax whitespace)) + (zero-or-more + (or "final" "abstract" "private" "package" "protected" "public" "export" "static") + (one-or-more (syntax whitespace))) + word-start + "class" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z))))) + 1) + ("*Interfaces*" + ,(rx + line-start + (zero-or-more (syntax whitespace)) + word-start + "interface" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z))))) + 1) + ("*Structs*" + ,(rx + line-start + (zero-or-more (syntax whitespace)) + (zero-or-more + (or "private" "package" "protected" "public" "export" "static") + (one-or-more (syntax whitespace))) + word-start + "struct" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z))))) + 1) + ("*Templates*" + ,(rx + line-start + (zero-or-more (syntax whitespace)) + (zero-or-one + "mixin" + (one-or-more (syntax whitespace))) + word-start + "template" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z))))) + 1) + ("*Enums*" + ,(rx + line-start + (zero-or-more (syntax whitespace)) + word-start + "enum" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z)))) + (zero-or-more (any " \t\n")) + (or ":" "{")) + 1) + ;; NB: We can't easily distinguish aliases declared outside + ;; functions from local ones, so just search for those that are + ;; declared at the beginning of lines. + ("*Aliases*" + ,(rx + line-start + "alias" + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z)))) + (zero-or-more (syntax whitespace)) + "=") + 1) + ("*Aliases*" + ,(rx + line-start + "alias" + (one-or-more (syntax whitespace)) + (one-or-more + (not (any ";"))) + (one-or-more (syntax whitespace)) + (submatch + (one-or-more + (any ?_ + (?0 . ?9) + (?A . ?Z) + (?a . ?z)))) + (zero-or-more (syntax whitespace)) + ";" + (zero-or-more (syntax whitespace)) + (or + eol + "//" + "/*") + ) + 1) (nil d-imenu-method-index-function 2))) ;;---------------------------------------------------------------------------- @@ -502,7 +706,7 @@ (advice-add 'c-add-stmt-syntax :around #'d-around--c-add-stmt-syntax)) ;;---------------------------------------------------------------------------- -(add-to-list 'auto-mode-alist '("\\.d[i]?\\'" . d-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.d[i]?\\'" . d-mode)) ;; Custom variables ;;;###autoload @@ -531,23 +735,41 @@ abbrev-mode t) (use-local-map d-mode-map) (c-init-language-vars d-mode) - (c-common-init 'd-mode) - (easy-menu-add d-menu) - (c-run-mode-hooks 'c-mode-common-hook 'd-mode-hook) - (c-update-modeline) - (cc-imenu-init d-imenu-generic-expression) + (when (fboundp 'c-make-noise-macro-regexps) + (c-make-noise-macro-regexps)) + ;; Generate a function that applies D-specific syntax properties. ;; Concretely, inside back-quoted string literals the backslash ;; character '\' is treated as a punctuation symbol. See help for ;; syntax-propertize-rules function for more information. (when (version<= "24.3" emacs-version) - (setq-local syntax-propertize-function - (syntax-propertize-rules ("`[^\\\\`]*?\\(\\(\\\\\\)[^\\\\`]*?\\)+?`" (2 ".")))))) + (setq-local + syntax-propertize-function + (syntax-propertize-rules + ((rx + "`" + (minimal-match + (zero-or-more + (not (any "`\\")))) + (minimal-match + (one-or-more + (submatch "\\") + (minimal-match + (zero-or-more + (not (any "`\\")))))) + "`") + (1 "."))))) + + (c-common-init 'd-mode) + (easy-menu-add d-menu) + (c-run-mode-hooks 'c-mode-common-hook 'd-mode-hook) + (c-update-modeline) + (cc-imenu-init d-imenu-generic-expression)) ;;---------------------------------------------------------------------------- ;; "Hideous hacks" to support appropriate font-lock behaviour. ;; -;; * auto/immutable: If we leave them in c-modifier-kwds (like +;; * auto/const/immutable: If we leave them in c-modifier-kwds (like ;; c++-mode) then in the form "auto var;" var will be highlighted in ;; type name face. Moving auto/immutable to font-lock-add-keywords ;; lets cc-mode seeing them as a type name, so the next symbol can @@ -580,7 +802,7 @@ (defun d-match-fun-decl (limit) (d-try-match-decl d-fun-decl-pattern)) (defun d-match-auto (limit) - (c-syntactic-re-search-forward "\\<\\(auto\\|immutable\\)\\>" limit t)) + (c-syntactic-re-search-forward "\\<\\(auto\\|const\\|immutable\\)\\>" limit t)) (font-lock-add-keywords 'd-mode @@ -599,10 +821,12 @@ ;; StackOverflow, and then amended by Nordlöw (https://stackoverflow.com/users/683710/nordl%C3%B6w) it ;; provides a function that people can make use of in their d-mode-hook thus: ;; -;; (add-hook 'd-mode-hook -;; '(lambda () -;; (add-to-list 'c-offsets-alist '(arglist-cont-nonempty . d-lineup-cascaded-calls)) -;; (add-to-list 'c-offsets-alist '(statement-cont . d-lineup-cascaded-calls)))) +;; (add-hook 'd-mode-hook 'd-setup-cascaded-call-indentation) + +(defun d-setup-cascaded-call-indentation () + "Set up `d-lineup-cascaded-calls'." + (add-to-list 'c-offsets-alist '(arglist-cont-nonempty . d-lineup-cascaded-calls)) + (add-to-list 'c-offsets-alist '(statement-cont . d-lineup-cascaded-calls))) (defun d-lineup-cascaded-calls (langelem) "This is a modified `c-lineup-cascaded-calls' function for the