Now that we are loading package autoloads files (as part of the generated doom-package-autoload-file when running make autoloads), many :commands properties are redundant. In fact, many def-package! blocks are redundant. In some cases, we can do without a config.el file entirely, and can move into the autoloads file or rely entirely on package autoloads. Also, many settings have been moved in their module's autoloads files, which makes them available ASAP; their use no longer depends on module load order. This gained me a modest ~10% boost in startup speed.
219 lines
8.6 KiB
EmacsLisp
219 lines
8.6 KiB
EmacsLisp
;;; lang/javascript/config.el -*- lexical-binding: t; -*-
|
|
|
|
;;
|
|
;; Major modes
|
|
;;
|
|
|
|
(def-package! js2-mode
|
|
:mode "\\.js\\'"
|
|
:interpreter "node"
|
|
:config
|
|
(setq js2-skip-preprocessor-directives t
|
|
js2-highlight-external-variables nil
|
|
js-chain-indent t
|
|
;; let flycheck handle this
|
|
js2-mode-show-parse-errors nil
|
|
js2-mode-show-strict-warnings nil
|
|
;; Flycheck provides these features, so disable them: conflicting with
|
|
;; the eslint settings.
|
|
js2-strict-trailing-comma-warning nil
|
|
js2-strict-missing-semi-warning nil)
|
|
|
|
(add-hook! 'js2-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
|
|
|
|
(set! :electric 'js2-mode :chars '(?\} ?\) ?. ?:))
|
|
(set! :repl 'js2-mode #'+javascript/repl)
|
|
|
|
;; Conform switch-case indentation to js2 normal indent
|
|
(defvaralias 'js-switch-indent-offset 'js2-basic-offset)
|
|
|
|
(sp-with-modes '(js2-mode rjsx-mode)
|
|
(sp-local-pair "/*" "*/" :post-handlers '(("| " "SPC"))))
|
|
|
|
(map! :map js2-mode-map
|
|
:localleader
|
|
:n "S" #'+javascript/skewer-this-buffer))
|
|
|
|
|
|
(def-package! rjsx-mode
|
|
:mode "components/.+\\.js$"
|
|
:init
|
|
(defun +javascript-jsx-file-p ()
|
|
"Detect React or preact imports early in the file."
|
|
(and buffer-file-name
|
|
(string= (file-name-extension buffer-file-name) "js")
|
|
(re-search-forward "\\(^\\s-*import +React\\|\\( from \\|require(\\)[\"']p?react\\)"
|
|
magic-mode-regexp-match-limit t)
|
|
(progn (goto-char (match-beginning 1))
|
|
(not (sp-point-in-string-or-comment)))))
|
|
(map-put magic-mode-alist #'+javascript-jsx-file-p 'rjsx-mode)
|
|
:config
|
|
(set! :electric 'rjsx-mode :chars '(?\} ?\) ?. ?>))
|
|
(add-hook! 'rjsx-mode-hook
|
|
;; jshint doesn't know how to deal with jsx
|
|
(push 'javascript-jshint flycheck-disabled-checkers))
|
|
|
|
;; `rjsx-electric-gt' relies on js2's parser to tell it when the cursor is in
|
|
;; a self-closing tag, so that it can insert a matching ending tag at point.
|
|
;; However, the parser doesn't run immediately, so a fast typist can outrun
|
|
;; it, causing issues, so force it to parse.
|
|
(defun +javascript|reparse (n)
|
|
;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself
|
|
(if (= n 1) (rjsx-maybe-reparse)))
|
|
(advice-add #'rjsx-electric-gt :before #'+javascript|reparse))
|
|
|
|
|
|
(after! typescript-mode
|
|
(add-hook! 'typescript-mode-hook #'(flycheck-mode rainbow-delimiters-mode))
|
|
(set! :electric 'typescript-mode
|
|
:chars '(?\} ?\)) :words '("||" "&&")))
|
|
|
|
|
|
;; `coffee-mode'
|
|
(setq coffee-indent-like-python-mode t)
|
|
|
|
|
|
;;
|
|
;; Tools
|
|
;;
|
|
|
|
(def-package! tide
|
|
:hook (js2-mode . tide-setup)
|
|
:hook (typescript-mode . tide-setup)
|
|
:init
|
|
(defun +javascript|init-tide-in-web-mode ()
|
|
"Enable `tide-mode' if in a *.tsx file."
|
|
(when (string= (file-name-extension (or buffer-file-name "")) "tsx")
|
|
(tide-setup)))
|
|
(add-hook 'web-mode-hook #'+javascript|init-tide-in-web-mode)
|
|
:config
|
|
(setq tide-completion-detailed t
|
|
tide-always-show-documentation t)
|
|
;; code completion
|
|
(after! company
|
|
;; tide affects the global `company-backends', undo this so doom can handle
|
|
;; it buffer-locally
|
|
(setq-default company-backends (delq 'company-tide (default-value 'company-backends))))
|
|
(set! :company-backend 'tide-mode 'company-tide)
|
|
|
|
;; navigation
|
|
(set! :lookup 'tide-mode
|
|
:definition #'tide-jump-to-definition
|
|
:references #'tide-references
|
|
:documentation #'tide-documentation-at-point)
|
|
|
|
;; resolve to `doom-project-root' if `tide-project-root' fails
|
|
(advice-add #'tide-project-root :override #'+javascript*tide-project-root)
|
|
|
|
;; cleanup tsserver when no tide buffers are left
|
|
(add-hook! 'tide-mode-hook
|
|
(add-hook 'kill-buffer-hook #'+javascript|cleanup-tide-processes nil t))
|
|
|
|
(def-menu! +javascript/refactor-menu
|
|
"Refactoring commands for `js2-mode' buffers."
|
|
'(("Restart tsserver" :exec tide-restart-server :when (bound-and-true-p tide-mode))
|
|
("Reformat buffer/region (tide)" :exec tide-reformat :when (bound-and-true-p tide-mode))
|
|
("Organize imports" :exec tide-organize-imports :when (bound-and-true-p tide-mode))
|
|
("Rename symbol" :exec tide-rename-symbol :when (bound-and-true-p tide-mode) :region nil)
|
|
("Reformat buffer (eslint_d)" :exec eslintd-fix :when (bound-and-true-p eslintd-fix-mode) :region nil)
|
|
("Extract into function" :exec js2r-extract-function :region t)
|
|
("Extract into method" :exec js2r-extract-method :region t)
|
|
("Introduce parameter to function" :exec js2r-introduce-parameter :region t)
|
|
("Localize parameter" :exec js2r-localize-parameter :region nil)
|
|
("Expand object" :exec js2r-expand-object :region nil)
|
|
("Expand function" :exec js2r-expand-function :region nil)
|
|
("Expand array" :exec js2r-expand-array :region nil)
|
|
("Contract object" :exec js2r-contract-object :region nil)
|
|
("Contract function" :exec js2r-contract-function :region nil)
|
|
("Contract array" :exec js2r-contract-array :region nil)
|
|
("Wrap buffer in IIFE" :exec js2r-wrap-buffer-in-iife :region nil)
|
|
("Inject global into IIFE" :exec js2r-inject-global-in-iife :region t)
|
|
("Add to globals annotation" :exec js2r-add-to-globals-annotation :region nil)
|
|
("Extract variable" :exec js2r-extract-var :region t)
|
|
("Inline variable" :exec js2r-inline-var :region t)
|
|
("Rename variable" :exec js2r-rename-var :region nil)
|
|
("Replace var with this" :exec js2r-var-to-this :region nil)
|
|
("Arguments to object" :exec js2r-arguments-to-object :region nil)
|
|
("Ternary to if" :exec js2r-ternary-to-if :region nil)
|
|
("Split var declaration" :exec js2r-split-var-declaration :region nil)
|
|
("Split string" :exec js2r-split-string :region nil)
|
|
("Unwrap" :exec js2r-unwrap :region t)
|
|
("Log this" :exec js2r-log-this)
|
|
("Debug this" :exec js2r-debug-this))
|
|
:prompt "Refactor: ")
|
|
|
|
(map! :map tide-mode-map
|
|
:localleader
|
|
:n "r" #'+javascript/refactor-menu))
|
|
|
|
|
|
(def-package! xref-js2
|
|
:when (featurep! :feature lookup)
|
|
:commands xref-js2-xref-backend
|
|
:init (set! :lookup 'js2-mode :xref-backend #'xref-js2-xref-backend))
|
|
|
|
|
|
(def-package! js2-refactor
|
|
:commands
|
|
(js2r-extract-function js2r-extract-method js2r-introduce-parameter
|
|
js2r-localize-parameter js2r-expand-object js2r-contract-object
|
|
js2r-expand-function js2r-contract-function js2r-expand-array
|
|
js2r-contract-array js2r-wrap-buffer-in-iife js2r-inject-global-in-iife
|
|
js2r-add-to-globals-annotation js2r-extract-var js2r-inline-var
|
|
js2r-rename-var js2r-var-to-this js2r-arguments-to-object js2r-ternary-to-if
|
|
js2r-split-var-declaration js2r-split-string js2r-unwrap js2r-log-this
|
|
js2r-debug-this js2r-forward-slurp js2r-forward-barf))
|
|
|
|
|
|
(def-package! eslintd-fix
|
|
:commands eslintd-fix
|
|
:config
|
|
(defun +javascript|set-flycheck-executable-to-eslint ()
|
|
(setq flycheck-javascript-eslint-executable eslintd-fix-executable))
|
|
(add-hook 'eslintd-fix-mode-hook #'+javascript|set-flycheck-executable-to-eslint))
|
|
|
|
|
|
;; `skewer-mode'
|
|
(map! (:after skewer-mode
|
|
:map skewer-mode-map
|
|
:localleader
|
|
:n "sE" #'skewer-eval-last-expression
|
|
:n "se" #'skewer-eval-defun
|
|
:n "sf" #'skewer-load-buffer)
|
|
|
|
(:after skewer-css
|
|
:map skewer-css-mode-map
|
|
:localleader
|
|
:n "se" #'skewer-css-eval-current-declaration
|
|
:n "sr" #'skewer-css-eval-current-rule
|
|
:n "sb" #'skewer-css-eval-buffer
|
|
:n "sc" #'skewer-css-clear-all)
|
|
|
|
(:after skewer-html
|
|
:map skewer-html-mode-map
|
|
:localleader
|
|
:n "se" #'skewer-html-eval-tag))
|
|
|
|
|
|
;; `web-beautify'
|
|
(map! :map* (json-mode-map js2-mode-map) :n "gQ" #'web-beautify-js)
|
|
|
|
|
|
;;
|
|
;; Projects
|
|
;;
|
|
|
|
(def-project-mode! +javascript-screeps-mode
|
|
:match "/screeps\\(?:-ai\\)?/.+$"
|
|
:modes (+javascript-npm-mode)
|
|
:add-hooks (+javascript|init-screeps-mode)
|
|
:on-load (load! +screeps))
|
|
|
|
(def-project-mode! +javascript-gulp-mode
|
|
:files "gulpfile.js")
|
|
|
|
(def-project-mode! +javascript-npm-mode
|
|
:modes (html-mode css-mode web-mode js2-mode markdown-mode)
|
|
:files "package.json"
|
|
:add-hooks (+javascript|add-node-modules-path))
|
|
|