Updating Doom Emacs.

This commit is contained in:
Derek Taylor
2020-06-19 22:43:40 -05:00
parent 0f664d532a
commit a5c86c514a
453 changed files with 13527 additions and 12455 deletions

View File

@@ -1,5 +1,13 @@
;;; lang/agda/config.el -*- lexical-binding: t; -*-
(when (and (featurep! +local)
(executable-find "agda-mode"))
(add-load-path!
(file-name-directory (shell-command-to-string "agda-mode locate")))
(unless (require 'agda2 nil t)
(message "Failed to find the `agda2' package")))
(map! :after agda2-mode
:map agda2-mode-map
:localleader

View File

@@ -1,15 +1,16 @@
;; -*- no-byte-compile: t; -*-
;;; lang/agda/packages.el
(unless (featurep! +local)
(package! agda-input
:recipe (:host github :repo "agda/agda"
:files ("src/data/emacs-mode/agda-input.el")
:nonrecursive t)
:pin "ff9173e14e")
(package! agda-input
:recipe
(:host github :repo "agda/agda"
:files ("src/data/emacs-mode/agda-input.el")))
(package! agda2-mode
:recipe
(:host github :repo "agda/agda"
:files
("src/data/emacs-mode/*.el"
(:exclude "agda-input.el"))))
(package! agda2-mode
:recipe (:host github :repo "agda/agda"
:files ("src/data/emacs-mode/*.el"
(:exclude "agda-input.el"))
:nonrecursive t)
:pin "ff9173e14e"))

View File

@@ -1,4 +0,0 @@
;;; lang/assembly/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.hax\\'" . haxor-mode))

View File

@@ -1,6 +0,0 @@
;; -*- no-byte-compile: t; -*-
;;; lang/assembly/packages.el
(package! mips-mode)
(package! haxor-mode)
(package! nasm-mode)

View File

@@ -16,6 +16,8 @@
- [[#configure][Configure]]
- [[#project-compile-settings][Project compile settings]]
- [[#known-issues-with-bear-on-macos][Known issues with bear on macOS]]
- [[#appendix][Appendix]]
- [[#eglot-specific-bindings][Eglot specific bindings]]
* Description
This module adds support for the C-family of languages: C, C++, and Objective-C.
@@ -42,7 +44,7 @@ This module adds support for the C-family of languages: C, C++, and Objective-C.
+ [[https://github.com/jimhourihan/glsl-mode][glsl-mode]]*
+ [[https://github.com/guidoschmidt/company-glsl][company-glsl]]*
+ =+lsp=
+ [[https://github.com/MaskRay/emacs-ccls][ccls]]
+ [[https://github.com/MaskRay/emacs-ccls][ccls]] if =:tools lsp= has *no* =+eglot= flag
+ =-lsp=
+ [[https://github.com/Sarcasm/irony-mode][irony]]
+ [[https://github.com/ikirill/irony-eldoc][irony-eldoc]]
@@ -76,7 +78,8 @@ mkdir irony-mode/server/build
pushd irony-mode/server/build
DEST="$HOME/.emacs.d/.local/etc/irony-server/"
cmake -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
-DCMAKE_INSTALL_PREFIX="$DEST" ../
cmake --build . --use-stderr --config Release --target install
@@ -172,3 +175,12 @@ bear gmake
Additional info:
+ [[https://github.com/rizsotto/Bear/issues/158][Empty compilation database with compiler in /usr/local]]
+ [[https://github.com/rizsotto/Bear/issues/152][Workaround for 'Empty compilation database on OS X Captain]]
* Appendix
** Eglot specific bindings
When using =+lsp= and =:tools (lsp +eglot)=, lsp-mode is replaced with eglot,
and an additional function to get inheritance type hierarchy is added
| Binding | Description |
|------------------------------+--------------------------------------------------|
| ~<localleader> c t~ | ~Display inheritance type hierarchy (upwards)~ |
| ~<prefix> <localleader> c t~ | ~Display inheritance type hierarchy (downwards)~ |

View File

@@ -3,6 +3,11 @@
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.cl\\'" . opencl-mode))
;; The plusses in c++-mode can be annoying to search for ivy/helm (which reads
;; queries as regexps), so we add these for convenience.
;;;###autoload (defalias 'cpp-mode 'c++-mode)
;;;###autoload (defvaralias 'cpp-mode-map 'c++-mode-map)
;;
;; Library
@@ -117,6 +122,34 @@ simpler."
#'rtags-imenu
#'imenu)))
;; Eglot specific helper, courtesy of MaskRay
;;;###autoload
(defun +cc/eglot-ccls-inheritance-hierarchy (&optional derived)
"Show inheritance hierarchy for the thing at point.
If DERIVED is non-nil (interactively, with prefix argument), show
the children of class at point."
(interactive "P")
(if-let* ((res (jsonrpc-request
(eglot--current-server-or-lose)
:$ccls/inheritance
(append (eglot--TextDocumentPositionParams)
`(:derived ,(if derived t :json-false))
'(:levels 100) '(:hierarchy t))))
(tree (list (cons 0 res))))
(with-help-window "*ccls inheritance*"
(with-current-buffer standard-output
(while tree
(pcase-let ((`(,depth . ,node) (pop tree)))
(cl-destructuring-bind (&key uri range) (plist-get node :location)
(insert (make-string depth ?\ ) (plist-get node :name) "\n")
(make-text-button (+ (point-at-bol 0) depth) (point-at-eol 0)
'action (lambda (_arg)
(interactive)
(find-file (eglot--uri-to-path uri))
(goto-char (car (eglot--range-region range)))))
(cl-loop for child across (plist-get node :children)
do (push (cons (1+ depth) child) tree)))))))
(eglot--error "Hierarchy unavailable")))
;;
;; Hooks

View File

@@ -33,33 +33,24 @@ This is ignored by ccls.")
;;; Packages
(use-package! cc-mode
:commands (c-mode c++-mode objc-mode java-mode)
:mode ("\\.mm\\'" . objc-mode)
:init
;; The plusses in c++-mode can be annoying to search for ivy/helm (which reads
;; queries as regexps), so we add these for convenience.
(defalias 'cpp-mode 'c++-mode)
(defvaralias 'cpp-mode-map 'c++-mode-map)
;; Activate `c-mode', `c++-mode' or `objc-mode' depending on heuristics
(add-to-list 'auto-mode-alist '("\\.h\\'" . +cc-c-c++-objc-mode))
;; Ensure find-file-at-point works in C modes, must be added before irony
;; and/or lsp hooks are run.
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
#'+cc-init-ffap-integration-h)
;; Use `c-mode'/`c++-mode'/`objc-mode' depending on heuristics
:mode ("\\.h\\'" . +cc-c-c++-objc-mode)
;; Ensure find-file-at-point recognize system libraries in C modes. It must be
;; set up before the likes of irony/lsp are initialized. Also, we use
;; local-vars hooks to ensure these only run in their respective major modes,
;; and not their derived modes.
:hook ((c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) . +cc-init-ffap-integration-h)
;;; Improve fontification in C/C++ (also see `modern-cpp-font-lock')
:hook (c-mode-common . rainbow-delimiters-mode)
:hook ((c-mode c++-mode) . +cc-fontify-constants-h)
:config
(set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{))
(set-docsets! 'c-mode "C")
(set-docsets! 'c++-mode "C++" "Boost")
(set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{))
(set-rotate-patterns! 'c++-mode
:symbols '(("public" "protected" "private")
("class" "struct")))
(set-pretty-symbols! '(c-mode c++-mode)
;; Functional
;; :def "void "
@@ -76,9 +67,12 @@ This is ignored by ccls.")
:return "return"
:yield "#require")
;;; Better fontification (also see `modern-cpp-font-lock')
(add-hook 'c-mode-common-hook #'rainbow-delimiters-mode)
(add-hook! '(c-mode-hook c++-mode-hook) #'+cc-fontify-constants-h)
;; HACK Suppress 'Args out of range' error in when multiple modifications are
;; performed at once in a `c++-mode' buffer, e.g. with `iedit' or
;; multiple cursors.
(undefadvice! +cc--suppress-silly-errors-a (orig-fn &rest args)
:around #'c-after-change-mark-abnormal-strings
(ignore-errors (apply orig-fn args)))
;; Custom style, based off of linux
(setq c-basic-offset tab-width
@@ -115,7 +109,10 @@ This is ignored by ccls.")
(label . 0))))
(when (listp c-default-style)
(setf (alist-get 'other c-default-style) "doom")))
(setf (alist-get 'other c-default-style) "doom"))
(after! ffap
(add-to-list 'ffap-alist '(c-mode . ffap-c-mode))))
(use-package! modern-cpp-font-lock
@@ -124,46 +121,40 @@ This is ignored by ccls.")
(use-package! irony
:unless (featurep! +lsp)
:commands (irony-install-server irony-mode)
:preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:init
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
(defun +cc-init-irony-mode-h ()
(if (file-directory-p irony-server-install-prefix)
(irony-mode +1)
(message "Irony server isn't installed"))))
:config
(setq irony-cdb-search-directory-list '("." "build" "build-conda"))
:commands irony-install-server
;; Initialize compilation database, if present. Otherwise, fall back on
;; `+cc-default-compiler-options'.
(add-hook 'irony-mode-hook #'+cc-init-irony-compile-options-h)
:hook (irony-mode . +cc-init-irony-compile-options-h)
;; Only initialize `irony-mode' if the server is available. Otherwise fail
;; quietly and gracefully.
:hook ((c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) . +cc-init-irony-mode-maybe-h)
:preface (setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:config
(defun +cc-init-irony-mode-maybe-h ()
(if (file-directory-p irony-server-install-prefix)
(irony-mode +1)
(message "Irony server isn't installed")))
(setq irony-cdb-search-directory-list '("." "build" "build-conda"))
(use-package! irony-eldoc
:hook (irony-mode . irony-eldoc))
(use-package! flycheck-irony
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:config (flycheck-irony-setup))
(use-package! company-irony
:when (featurep! :completion company)
:init
(set-company-backend! 'irony-mode
'(:separate company-irony-c-headers company-irony))
:config
(require 'company-irony-c-headers)))
:init (set-company-backend! 'irony-mode '(:separate company-irony-c-headers company-irony))
:config (require 'company-irony-c-headers)))
;;
;; Major modes
(use-package! cmake-mode
:defer t
:config (set-docsets! 'cmake-mode "CMake"))
(after! cmake-mode
(set-docsets! 'cmake-mode "CMake"))
(use-package! company-cmake ; for `cmake-mode'
:when (featurep! :completion company)
@@ -186,19 +177,17 @@ This is ignored by ccls.")
(use-package! rtags
:unless (featurep! +lsp)
:commands rtags-executable-find
:preface
(setq rtags-install-path (concat doom-etc-dir "rtags/"))
:init
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
(defun +cc-init-rtags-h ()
"Start an rtags server in c-mode and c++-mode buffers."
(when (and (require 'rtags nil t)
(rtags-executable-find rtags-rdm-binary-name))
(rtags-start-process-unless-running))))
;; Only initialize rtags-mode if rtags and rdm are available.
:hook ((c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) . +cc-init-rtags-maybe-h)
:preface (setq rtags-install-path (concat doom-etc-dir "rtags/"))
:config
(defun +cc-init-rtags-maybe-h ()
"Start an rtags server in c-mode and c++-mode buffers.
If rtags or rdm aren't available, fail silently instead of throwing a breaking error."
(and (require 'rtags nil t)
(rtags-executable-find rtags-rdm-binary-name)
(rtags-start-process-unless-running)))
(setq rtags-autostart-diagnostics t
rtags-use-bookmarks nil
rtags-completions-enabled nil
@@ -223,11 +212,13 @@ This is ignored by ccls.")
:definition #'rtags-find-symbol-at-point
:references #'rtags-find-references-at-point)
(add-hook! 'kill-emacs-hook (ignore-errors (rtags-cancel-process)))
;; Use rtags-imenu instead of imenu/counsel-imenu
(define-key! (c-mode-map c++-mode-map) [remap imenu] #'+cc/imenu)
;; Ensure rtags cleans up after itself properly when exiting Emacs, rather
;; than display a jarring confirmation prompt for killing it.
(add-hook! 'kill-emacs-hook (ignore-errors (rtags-cancel-process)))
(add-hook 'rtags-jump-hook #'better-jumper-set-jump)
(add-hook 'rtags-after-find-file-hook #'recenter))
@@ -245,9 +236,25 @@ This is ignored by ccls.")
(setq-local company-lsp-cache-candidates nil)
(lsp!))))
(when (and (featurep! +lsp) (featurep! :tools lsp +eglot))
;; Map eglot specific helper
(map! :localleader
:after cc-mode
:map c++-mode-map
:n :desc "Show type inheritance hierarchy" "ct" #'+cc/eglot-ccls-inheritance-hierarchy)
;; NOTE : This setting is untested yet
(after! eglot
;; IS-MAC custom configuration
(when IS-MAC
(add-to-list 'eglot-workspace-configuration
`((:ccls . ((:clang . ,(list :extraArgs ["-isystem/Library/Developer/CommandLineTools/usr/include/c++/v1"
"-isystem/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
"-isystem/usr/local/include"]
:resourceDir (string-trim (shell-command-to-string "clang -print-resource-dir")))))))))))
(use-package! ccls
:when (featurep! +lsp)
:when (and (featurep! +lsp) (not (featurep! :tools lsp +eglot)))
:after lsp
:init
(after! projectile

View File

@@ -1,27 +1,33 @@
;; -*- no-byte-compile: t; -*-
;;; lang/cc/packages.el
(package! cmake-mode :recipe (:host github :repo "emacsmirror/cmake-mode" :files (:defaults "*")))
(package! cuda-mode)
(package! demangle-mode)
(package! disaster)
(package! modern-cpp-font-lock)
(package! opencl-mode)
(package! cmake-mode
:recipe (:host github :repo "emacsmirror/cmake-mode" :files (:defaults "*"))
:pin "bfe85bc009")
(package! cuda-mode :pin "9ae9eacfdb")
(package! demangle-mode :pin "06903d731d")
(package! disaster :pin "10a785facc")
(package! modern-cpp-font-lock :pin "02f104701b")
(package! opencl-mode :pin "55cb49c824")
(when (package! glsl-mode)
(when (package! glsl-mode :pin "43d906688a")
(when (featurep! :completion company)
(package! company-glsl :recipe (:host github :repo "Kaali/company-glsl"))))
(package! company-glsl
:recipe (:host github :repo "Kaali/company-glsl")
:pin "404cd0694a")))
(if (featurep! +lsp)
(package! ccls)
(when (package! irony)
(package! irony-eldoc)
(when (featurep! :tools flycheck)
(package! flycheck-irony))
(unless (featurep! :tools lsp +eglot)
;; ccls package is necessary only for lsp-mode.
(package! ccls :pin "17ec7bb4cf"))
(when (package! irony :pin "5f75fc0c92")
(package! irony-eldoc :pin "0df5831eaa")
(when (featurep! :checkers syntax)
(package! flycheck-irony :pin "42dbecd4a8"))
(when (featurep! :completion company)
(package! company-irony)
(package! company-irony-c-headers)))
(when (package! rtags)
(package! company-irony :pin "b44711dfce")
(package! company-irony-c-headers :pin "72c386aeb0")))
(when (package! rtags :pin "d370c09007")
(when (featurep! :completion ivy)
(package! ivy-rtags))
(when (featurep! :completion helm)

View File

@@ -5,19 +5,32 @@
;; Large clojure buffers tend to be slower than large buffers of other modes, so
;; it should have a lower threshold too.
(add-to-list 'doom-large-file-size-alist '(clojure-mode . 0.5))
(add-to-list 'doom-large-file-size-alist '("\\.\\(?:clj[sc]?\\|dtm\\|edn\\)\\'" . 0.5))
;;
;;; Packages
;;;###package clojure-mode
(add-hook 'clojure-mode-hook #'rainbow-delimiters-mode)
(use-package! clojure-mode
:hook (clojure-mode . rainbow-delimiters-mode)
:config
(when (featurep! +lsp)
(add-hook! '(clojure-mode-local-vars-hook
clojurec-mode-local-vars-hook
clojurescript-mode-local-vars-hook)
(defun +clojure-disable-lsp-indentation-h ()
(setq-local lsp-enable-indentation nil))
#'lsp!)
(after! lsp-clojure
(dolist (m '(clojure-mode
clojurec-mode
clojurescript-mode
clojurex-mode))
(add-to-list 'lsp-language-id-configuration (cons m "clojure"))))))
(use-package! cider
;; NOTE: if you don't have an org directory set (the dir doesn't exist), cider
;; jack in won't work.
;; NOTE if `org-directory' doesn't exist, `cider-jack' in won't work
:hook (clojure-mode-local-vars . cider-mode)
:init
(after! clojure-mode
@@ -26,7 +39,7 @@
(set-eval-handler! '(clojure-mode clojurescript-mode) #'cider-eval-region))
:config
(add-hook 'cider-mode-hook #'eldoc-mode)
(set-lookup-handlers! 'cider-mode
(set-lookup-handlers! '(cider-mode cider-repl-mode)
:definition #'+clojure-cider-lookup-definition
:documentation #'cider-doc)
(set-popup-rules!
@@ -46,13 +59,18 @@
cider-repl-history-quit-action 'delete-and-restore
cider-repl-history-highlight-inserted-item t
cider-repl-history-size 1000
cider-repl-pop-to-buffer-on-connect 'display-only
cider-repl-result-prefix ";; => "
cider-repl-print-length 100
cider-repl-use-clojure-font-lock t
cider-repl-use-pretty-printing t
cider-repl-wrap-history nil
cider-stacktrace-default-filters '(tooling dup))
cider-stacktrace-default-filters '(tooling dup)
;; Don't focus the CIDER REPL when it starts. Since it can take so long
;; to start up, you either wait for a minute doing nothing or be
;; prepared for your cursor to suddenly change buffers without warning.
;; See https://github.com/clojure-emacs/cider/issues/1872
cider-repl-pop-to-buffer-on-connect 'display-only)
;; Error messages emitted from CIDER is silently funneled into *nrepl-server*
;; rather than the *cider-repl* buffer. How silly. We might want to see that
@@ -78,6 +96,8 @@
"\"" #'cider-jack-in-cljs
"c" #'cider-connect-clj
"C" #'cider-connect-cljs
"m" #'cider-macroexpand-1
"M" #'cider-macroexpand-all
(:prefix ("e" . "eval")
"b" #'cider-eval-buffer
"d" #'cider-eval-defun-at-point
@@ -94,16 +114,14 @@
(:prefix ("h" . "help")
"n" #'cider-find-ns
"a" #'cider-apropos
"c" #'cider-clojuredocs
"d" #'cider-doc
"g" #'cider-grimoire-web
"j" #'cider-javadoc)
"j" #'cider-javadoc
"w" #'cider-clojuredocs-web)
(:prefix ("i" . "inspect")
"e" #'cider-enlighten-mode
"i" #'cider-inspect
"r" #'cider-inspect-last-result)
(:prefix ("m" . "macro")
"e" #'cider-macroexpand-1
"E" #'cider-macroexpand-all)
(:prefix ("n" . "namespace")
"n" #'cider-browse-ns
"N" #'cider-browse-ns-all
@@ -111,7 +129,7 @@
(:prefix ("r" . "repl")
"n" #'cider-repl-set-ns
"q" #'cider-quit
"r" #'cider-refresh
"r" #'cider-ns-refresh
"R" #'cider-restart
"b" #'cider-switch-to-repl-buffer
"B" #'+clojure/cider-switch-to-repl-buffer-and-switch-ns
@@ -146,6 +164,25 @@
:i "U" #'cider-repl-history-undo-other-window)))
(after! cider-doc
;; Fixes raxod502/radian#446: CIDER tries to do color calculations when it's
;; loaded, sometimes too early, causing errors. Better to wait until something
;; is actually rendered.
(setq cider-docview-code-background-color nil)
(defadvice! +clojure--defer-color-calculation-a (&rest _)
"Set `cider-docview-code-background-color'.
This is needed because we have ripped out the code that would normally set it
(since that code will run during early init, which is a problem)."
:before #'cider-docview-fontify-code-blocks
(setq cider-docview-code-background-color (cider-scale-background-color)))
;; HACK Disable cider's advice on these; and hope no one else is using these
;; old-style advice.
(ad-deactivate #'enable-theme)
(ad-deactivate #'disable-theme))
(use-package! clj-refactor
:hook (clojure-mode . clj-refactor-mode)
:config
@@ -156,6 +193,6 @@
:desc "refactor" "R" #'hydra-cljr-help-menu/body))
(use-package! flycheck-joker
:when (featurep! :tools flycheck)
(use-package! flycheck-clj-kondo
:when (featurep! :checkers syntax)
:after flycheck)

View File

@@ -1,8 +1,9 @@
;; -*- no-byte-compile: t; -*-
;;; lang/clojure/packages.el
(package! cider)
(package! clj-refactor)
(package! clojure-mode :pin "da9f1ec717dac1194404b4a4562dba6bd9a4ee3a")
(package! cider :pin "2c8f510a5ae0e6c1bdb96195e04629f4791dea79")
(package! clj-refactor :pin "8259791e054382457b87d1f78061b5e3ce948907")
(when (featurep! :tools flycheck)
(package! flycheck-joker))
(when (featurep! :checkers syntax)
(package! flycheck-clj-kondo :pin "5472c26ffdf754a0661357564874ffd4f8598805"))

View File

@@ -8,38 +8,45 @@
;;
;; packages
;;;###package lisp-mode
(defvar inferior-lisp-program "sbcl")
(after! lisp-mode
(set-repl-handler! 'lisp-mode #'sly-mrepl)
(set-eval-handler! 'lisp-mode #'sly-eval-region)
(set-lookup-handlers! 'lisp-mode
:definition #'sly-edit-definition
:documentation #'sly-describe-symbol)
(add-hook 'lisp-mode-hook #'rainbow-delimiters-mode))
(add-hook 'lisp-mode-hook #'rainbow-delimiters-mode)
(after! sly
(use-package! sly
:defer t
:init
(after! lisp-mode
(set-repl-handler! 'lisp-mode #'sly-mrepl)
(set-eval-handler! 'lisp-mode #'sly-eval-region)
(set-lookup-handlers! 'lisp-mode
:definition #'sly-edit-definition
:documentation #'sly-describe-symbol))
;; HACK Ensures that sly's contrib modules are loaded as soon as possible, but
;; also as late as possible, so users have an opportunity to override
;; `sly-contrib' in an `after!' block.
(add-hook! 'doom-after-init-modules-hook
(after! sly (sly-setup)))
:config
(setq sly-mrepl-history-file-name (concat doom-cache-dir "sly-mrepl-history")
sly-kill-without-query-p t
sly-net-coding-system 'utf-8-unix
;; Doom defaults to non-fuzzy search, because it is slower and less
;; precise. Change this to `sly-flex-completions' for fuzzy completion
;; Doom defaults to non-fuzzy search, because it is faster and more
;; precise (but requires more keystrokes). Change this to
;; `sly-flex-completions' for fuzzy completion
sly-complete-symbol-function 'sly-simple-completions)
(set-popup-rules!
'(("^\\*sly-mrepl" :vslot 2 :size 0.3 :quit nil :ttl nil)
("^\\*sly-compilation" :vslot 3 :ttl nil)
("^\\*sly-traces" :vslot 4 :ttl nil)
("^\\*sly-description" :vslot 5 :size 0.3 :ttl 0)
;; Do not display debugger or inspector buffers in a popup window. These
;; buffers are meant to be displayed with sufficient vertical space.
("^\\*sly-\\(?:db\\|inspector\\)" :ignore t)))
(sp-with-modes '(sly-mrepl-mode)
(sp-local-pair "'" "'" :actions nil)
(sp-local-pair "`" "`" :actions nil))
(defun +common-lisp--cleanup-sly-maybe-h ()
"Kill processes and leftover buffers when killing the last sly buffer."
(unless (cl-loop for buf in (delq (current-buffer) (buffer-list))
@@ -66,26 +73,39 @@
((message "WARNING: Couldn't find `inferior-lisp-program' (%s)"
inferior-lisp-program)))))
(map! :localleader
:map lisp-mode-map
:desc "Sly" "'" #'sly
:desc "Sly (ask)" ";" (λ!! #'sly '-)
:desc "Expand macro" "m" #'macrostep-expand
(:prefix ("c" . "compile")
(map! (:map sly-db-mode-map
:n "gr" #'sly-db-restart-frame)
(:map sly-inspector-mode-map
:n "gb" #'sly-inspector-pop
:n "gr" #'sly-inspector-reinspect
:n "gR" #'sly-inspector-fetch-all
:n "K" #'sly-inspector-describe-inspectee)
(:map sly-xref-mode-map
:n "gr" #'sly-recompile-xref
:n "gR" #'sly-recompile-all-xrefs)
(:map lisp-mode-map
:n "gb" #'sly-pop-find-definition-stack)
(:localleader
:map lisp-mode-map
:desc "Sly" "'" #'sly
:desc "Sly (ask)" ";" (λ!! #'sly '-)
:desc "Expand macro" "m" #'macrostep-expand
(:prefix ("c" . "compile")
:desc "Compile file" "c" #'sly-compile-file
:desc "Compile/load file" "C" #'sly-compile-and-load-file
:desc "Compile toplevel form" "f" #'sly-compile-defun
:desc "Load file" "l" #'sly-load-file
:desc "Remove notes" "n" #'sly-remove-notes
:desc "Compile region" "r" #'sly-compile-region)
(:prefix ("e" . "evaluate")
:desc "Evaulate buffer" "b" #'sly-eval-buffer
(:prefix ("e" . "evaluate")
:desc "Evaluate buffer" "b" #'sly-eval-buffer
:desc "Evaluate last" "e" #'sly-eval-last-expression
:desc "Evaluate/print last" "E" #'sly-eval-print-last-expression
:desc "Evaluate defun" "f" #'sly-eval-defun
:desc "Undefine function" "F" #'sly-undefine-function
:desc "Evaluate region" "r" #'sly-eval-region)
(:prefix ("g" . "goto")
(:prefix ("g" . "goto")
:desc "Go back" "b" #'sly-pop-find-definition-stack
:desc "Go to" "d" #'sly-edit-definition
:desc "Go to (other window)" "D" #'sly-edit-definition-other-window
@@ -93,7 +113,7 @@
:desc "Previous note" "N" #'sly-previous-note
:desc "Next sticker" "s" #'sly-stickers-next-sticker
:desc "Previous sticker" "S" #'sly-stickers-prev-sticker)
(:prefix ("h" . "help")
(:prefix ("h" . "help")
:desc "Who calls" "<" #'sly-who-calls
:desc "Calls who" ">" #'sly-calls-who
:desc "Lookup format directive" "~" #'hyperspec-lookup-format
@@ -108,22 +128,22 @@
:desc "Who references" "r" #'sly-who-references
:desc "Who specializes" "s" #'sly-who-specializes
:desc "Who sets" "S" #'sly-who-sets)
(:prefix ("r" . "repl")
(:prefix ("r" . "repl")
:desc "Clear REPL" "c" #'sly-mrepl-clear-repl
:desc "Quit connection" "q" #'sly-quit-lisp
:desc "Restart connection" "r" #'sly-restart-inferior-lisp
:desc "Sync REPL" "s" #'sly-mrepl-sync)
(:prefix ("s" . "stickers")
(:prefix ("s" . "stickers")
:desc "Toggle breaking stickers" "b" #'sly-stickers-toggle-break-on-stickers
:desc "Clear defun stickers" "c" #'sly-stickers-clear-defun-stickers
:desc "Clear buffer stickers" "C" #'sly-stickers-clear-buffer-stickers
:desc "Fetch stickers" "f" #'sly-stickers-fetch
:desc "Replay stickers" "r" #'sly-stickers-replay
:desc "Add/remove sticker" "s" #'sly-stickers-dwim)
(:prefix ("t" . "trace")
(:prefix ("t" . "trace")
:desc "Toggle" "t" #'sly-toggle-trace-fdefinition
:desc "Toggle (fancy)" "T" #'sly-toggle-fancy-trace
:desc "Untrace all" "u" #'sly-untrace-all))
:desc "Untrace all" "u" #'sly-untrace-all)))
(when (featurep! :editor evil +everywhere)
(add-hook 'sly-mode-hook #'evil-normalize-keymaps)))
@@ -132,4 +152,4 @@
(use-package! sly-repl-ansi-color
:defer t
:init
(add-to-list 'sly-contribs 'sly-repl-ansi-color nil #'eq))
(add-to-list 'sly-contribs 'sly-repl-ansi-color))

View File

@@ -1,6 +1,6 @@
;; -*- no-byte-compile: t; -*-
;;; lang/common-lisp/packages.el
(package! sly)
(package! sly-macrostep)
(package! sly-repl-ansi-color)
(package! sly :pin "1382bda945")
(package! sly-macrostep :pin "5113e4e926")
(package! sly-repl-ansi-color :pin "b9cd52d1cf")

View File

@@ -1,22 +1,17 @@
;;; lang/coq/config.el -*- lexical-binding: t; -*-
;;;###package proof-general
;; HACK `proof-general' ascertains its own library path at compile time in its
;; autoloads file using `byte-compile-current-file' (and stores it in
;; `pg-init--script-full-path'). This means that when
;; `doom-package-autoload-file' is created and byte-compiled,
;; `pg-init--script-full-path' will be wrong, causing file-missing errors as it
;; tries to load `proof-site'. We prevent this by defining these two variables
;; early, in our own autoloads file.
(setq pg-init--script-full-path (locate-library "proof-general")
pg-init--pg-root (file-name-directory pg-init--script-full-path)
proof-splash-enable nil)
(setq proof-splash-enable nil)
;;;###package coq
;; Doom syncs other indent variables with `tab-width'; we trust major modes to
;; set it -- which most of them do -- but coq-mode doesn't, so...
(setq-hook! 'coq-mode-hook tab-width proof-indent)
(setq-hook! 'coq-mode-hook
;; Doom syncs other indent variables with `tab-width'; we trust major modes to
;; set it -- which most of them do -- but coq-mode doesn't, so...
tab-width proof-indent
;; HACK Fix #2081: Doom continues comments on RET, but coq-mode doesn't have a
;; sane `comment-line-break-function', so...
comment-line-break-function nil)
;; We've replaced coq-mode abbrevs with yasnippet snippets (in the snippets
;; library included with Doom).
@@ -77,11 +72,11 @@
(setq company-coq-disabled-features '(hello company-defaults))
(if (featurep! :completion company)
(map! :map coq-mode-map [remap company-complete-common]
#'company-indent-or-complete-common)
(define-key coq-mode-map [remap company-complete-common]
#'company-indent-or-complete-common)
;; `company-coq''s company defaults impose idle-completion on folks, so
;; we'll set up company ourselves.
;; See https://github.com/cpitclaudel/company-coq/issues/42
;; we'll set up company ourselves. See
;; https://github.com/cpitclaudel/company-coq/issues/42
(add-to-list 'company-coq-disabled-features 'company))
(map! :map coq-mode-map

View File

@@ -1,6 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; lang/coq/packages.el
(package! proof-general)
(package! company-coq)
(package! proof-general :pin "9196749d55")
(package! company-coq :pin "f9dba9ddff")

View File

@@ -11,12 +11,12 @@
(use-package! flycheck-crystal
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after crystal-mode)
(use-package! flycheck-ameba
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after crystal-mode
:config (flycheck-ameba-setup))

View File

@@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*-
;;; lang/crystal/packages.el
(package! crystal-mode)
(package! inf-crystal)
(when (featurep! :tools flycheck)
(package! flycheck-crystal)
(package! flycheck-ameba))
(package! crystal-mode :pin "2428b01624")
(package! inf-crystal :pin "02007b2a2a")
(when (featurep! :checkers syntax)
(package! flycheck-crystal :pin "2428b01624")
(package! flycheck-ameba :pin "0c4925ae0e"))

View File

@@ -8,3 +8,8 @@
(sp-point-after-word-p id action context))
((eq action 'autoskip)
(/= (char-before) 32)))))
;;;###autoload
(defun +csharp-kill-omnisharp-server-h ()
(unless (doom-buffers-in-mode 'csharp-mode (buffer-list))
(omnisharp-stop-server)))

View File

@@ -1,41 +1,39 @@
;;; lang/csharp/config.el -*- lexical-binding: t; -*-
(after! csharp-mode
(add-hook 'csharp-mode-hook #'rainbow-delimiters-mode)
(when (featurep! +lsp)
(add-hook 'csharp-mode-local-vars-hook #'lsp!))
(use-package! csharp-mode
:hook (csharp-mode . rainbow-delimiters-mode)
:config
(set-electric! 'csharp-mode :chars '(?\n ?\}))
(set-rotate-patterns! 'csharp-mode
:symbols '(("public" "protected" "private")
("class" "struct")))
(sp-local-pair 'csharp-mode "<" ">"
:when '(+csharp-sp-point-in-type-p)
:post-handlers '(("| " "SPC"))))
:post-handlers '(("| " "SPC")))
(when (featurep! +lsp)
(add-hook 'csharp-mode-local-vars-hook #'lsp!)))
(use-package! omnisharp
:unless (featurep! +lsp)
:hook (csharp-mode . omnisharp-mode)
:commands omnisharp-install-server
:hook (csharp-mode-local-vars . omnisharp-mode)
:preface
(setq omnisharp-auto-complete-want-documentation nil
omnisharp-cache-directory (concat doom-etc-dir "omnisharp"))
:config
(defun +csharp-cleanup-omnisharp-server-h ()
"Clean up the omnisharp server once you kill the last csharp-mode buffer."
(unless (doom-buffers-in-mode 'csharp-mode (buffer-list))
(omnisharp-stop-server)))
(add-hook! 'csharp-mode-hook
(add-hook 'kill-buffer-hook #'+csharp-cleanup-omnisharp-server-h nil t))
(set-company-backend! 'csharp-mode 'company-omnisharp)
(set-lookup-handlers! 'csharp-mode
(set-company-backend! 'omnisharp-mode 'company-omnisharp)
(set-lookup-handlers! 'omnisharp-mode
:definition #'omnisharp-go-to-definition
:references #'omnisharp-find-usages
:documentation #'omnisharp-current-type-documentation)
;; Kill the omnisharp server once the last csharp-mode buffer is killed
(add-hook! 'omnisharp-mode-hook
(add-hook 'kill-buffer-hook #'+csharp-kill-omnisharp-server-h nil t))
(map! :localleader
:map omnisharp-mode-map
"b" #'omnisharp-recompile
@@ -60,11 +58,11 @@
"b" #'omnisharp-unit-test-buffer)))
;;;###package shader-mode
(when (featurep! +unity)
;; Unity shaders
(add-to-list 'auto-mode-alist '("\\.shader\\'" . shader-mode))
;; Unity shaders
(use-package! shader-mode
:when (featurep! +unity)
:mode "\\.shader\\'"
:config
(def-project-mode! +csharp-unity-mode
:modes '(csharp-mode shader-mode)
:files (and "Assets" "Library/MonoManager.asset" "Library/ScriptMapper")))

View File

@@ -1,7 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; lang/csharp/doctor.el
(require 'omnisharp)
(let ((omnisharp-bin (or omnisharp-server-executable-path (omnisharp--server-installation-path t))))
(unless (file-exists-p omnisharp-bin)
(warn! "Omnisharp server isn't installed, completion won't work")))
(when (and (require 'omnisharp nil t) (not (featurep! +lsp)))
(let ((omnisharp-bin (or omnisharp-server-executable-path (omnisharp--server-installation-path t))))
(unless (file-exists-p omnisharp-bin)
(warn! "Omnisharp server isn't installed, completion won't work"))))

View File

@@ -1,10 +1,8 @@
;; -*- no-byte-compile: t; -*-
;;; lang/csharp/packages.el
(package! csharp-mode)
(package! csharp-mode :pin "57bd21bda4")
(unless (featurep! +lsp)
(package! omnisharp))
(package! omnisharp :pin "e658a18a76"))
(when (featurep! +unity)
(package! shader-mode))
(package! shader-mode :pin "d7dc8d0d6f"))

View File

@@ -1,9 +1,5 @@
;;; lang/data/config.el -*- lexical-binding: t; -*-
;; Built in plugins
(add-to-list 'auto-mode-alist '("/sxhkdrc\\'" . conf-mode))
(add-to-list 'auto-mode-alist '("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode))
(use-package! nxml-mode
:mode "\\.p\\(?:list\\|om\\)\\'" ; plist, pom
:mode "\\.xs\\(?:d\\|lt\\)\\'" ; xslt, xsd
@@ -16,9 +12,6 @@
(setq-hook! 'nxml-mode-hook tab-width nxml-child-indent))
;;
;;; Third-party plugins
;;;###package csv-mode
(map! :after csv-mode
:localleader
@@ -29,25 +22,3 @@
"S" #'csv-sort-numeric-fields
"k" #'csv-kill-fields
"t" #'csv-transpose)
(use-package! graphql-mode
:mode "\\.gql\\'"
:config (setq-hook! 'graphql-mode-hook tab-width graphql-indent-level))
(use-package! json-mode
:mode "\\.js\\(?:on\\|[hl]int\\(?:rc\\)?\\)\\'"
:config
(set-electric! 'json-mode :chars '(?\n ?: ?{ ?})))
(after! jsonnet-mode
(set-electric! 'jsonnet-mode :chars '(?\n ?: ?{ ?})))
(after! yaml-mode
(setq-hook! 'yaml-mode-hook tab-width yaml-indent-offset))
;;
;;; Frameworks
(def-project-mode! +data-vagrant-mode
:files ("Vagrantfile"))

View File

@@ -1,11 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/data/packages.el
(package! graphql-mode)
(package! json-mode)
(package! jsonnet-mode)
(package! yaml-mode)
(package! csv-mode)
(package! dhall-mode)
(package! protobuf-mode
:recipe (:host github :repo "emacsmirror/protobuf-mode" :files (:defaults "*")))
(package! csv-mode :pin "635337407c")

View File

@@ -16,10 +16,10 @@
* Description
This module provides support for [[https://elixir-lang.org/][Elixir programming language]] via [[https://github.com/tonini/alchemist.el][alchemist.el]]
or [[https://github.com/JakeBecker/elixir-ls/][elixir-ls]].
or [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]].
** Module flags
+ ~+lsp~ Enable LSP support. Requires [[https://github.com/JakeBecker/elixir-ls/][elixir-ls]].
+ ~+lsp~ Enable LSP support. Requires [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]].
** Plugins
+ [[https://github.com/elixir-editors/emacs-elixir][elixir-mode]]
@@ -33,7 +33,7 @@ manager or a version management tool such as [[https://github.com/asdf-vm/asdf-e
If you want to add support for LSP ([[modules/tools/lsp][:tools lsp]]), be sure to install [[https://github.com/JakeBecker/elixir-ls/][elixir-ls]]
and enable ~:tools lsp~ in your ~init.el~.
To support linting with [[https://github.com/rrrene/credo][credo]], add ~:tools flycheck~ to your ~init.el~
To support linting with [[https://github.com/rrrene/credo][credo]], add ~:checkers syntax~ to your ~init.el~
** Install Elixir
*** With ~asdf~
#+BEGIN_SRC sh
@@ -59,4 +59,4 @@ sudo zypper install elixir
- Mix integration
- Phoenix support
- ~iex~ integration (~:tools eval~)
- Syntax checking (~:tools flycheck~, using [[https://github.com/aaronjensen/flycheck-credo][flycheck-credo]]~)
- Syntax checking (~:checkers syntax~, using [[https://github.com/aaronjensen/flycheck-credo][flycheck-credo]]~)

View File

@@ -37,31 +37,30 @@
(sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p)))
(when (featurep! +lsp)
(add-hook 'elixir-mode-local-vars-hook #'lsp!))
(add-hook 'elixir-mode-local-vars-hook #'lsp!)))
(use-package! flycheck-credo
:when (featurep! :tools flycheck)
:config (flycheck-credo-setup)))
(use-package! flycheck-credo
:when (featurep! :checkers syntax)
:after elixir-mode
:config (flycheck-credo-setup))
(use-package! alchemist
:hook (elixir-mode . alchemist-mode)
:init
(after! elixir-mode
(set-lookup-handlers! 'elixir-mode
:definition #'alchemist-goto-definition-at-point
:documentation #'alchemist-help-search-at-point)
(set-eval-handler! 'elixir-mode #'alchemist-eval-region)
(set-repl-handler! 'elixir-mode #'alchemist-iex-project-run)))
:config
(set-lookup-handlers! 'alchemist-mode
:definition #'alchemist-goto-definition-at-point
:documentation #'alchemist-help-search-at-point)
(set-eval-handler! 'alchemist-mode #'alchemist-eval-region)
(set-repl-handler! 'alchemist-mode #'alchemist-iex-project-run))
(use-package! alchemist-company
:when (featurep! :completion company)
:commands alchemist-company
:init
(after! elixir-mode
(set-company-backend! 'elixir-mode '(alchemist-company company-yasnippet)))
:config
(set-company-backend! 'alchemist-mode '(alchemist-company company-yasnippet))
;; Alchemist doesn't use hook symbols to add these backends, so we have to use
;; the entire closure to get rid of it.
(let ((fn (byte-compile (lambda () (add-to-list (make-local-variable 'company-backends) 'alchemist-company)))))

View File

@@ -2,7 +2,7 @@
;;; lang/elixir/packages.el
;; +elixir.el
(package! elixir-mode)
(package! alchemist)
(when (featurep! :tools flycheck)
(package! flycheck-credo))
(package! elixir-mode :pin "231291ecad")
(package! alchemist :pin "6f99367511")
(when (featurep! :checkers syntax)
(package! flycheck-credo :pin "e88f11ead5"))

View File

@@ -1,9 +1,10 @@
;;; lang/elm/config.el -*- lexical-binding: t; -*-
(after! elm-mode
(add-hook 'elm-mode-hook #'rainbow-delimiters-mode)
(set-company-backend! 'elm-mode 'company-elm)
(if (featurep! +lsp)
(add-hook 'elm-mode-local-vars-hook #'lsp!)
(set-company-backend! 'elm-mode 'company-elm))
(set-repl-handler! 'elm-mode #'run-elm-interactive)
(set-pretty-symbols! 'elm-mode
:null "null"
@@ -17,6 +18,6 @@
(use-package! flycheck-elm
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after elm-mode
:config (add-to-list 'flycheck-checkers 'elm nil #'eq))
:config (add-to-list 'flycheck-checkers 'elm))

View File

@@ -1,7 +1,6 @@
;; -*- no-byte-compile: t; -*-
;;; lang/elm/packages.el
(package! elm-mode)
(when (featurep! :tools flycheck)
(package! flycheck-elm))
(package! elm-mode :pin "7782be0814")
(when (featurep! :checkers syntax)
(package! flycheck-elm :pin "1b60050efd"))

View File

@@ -22,57 +22,115 @@ to a pop up buffer."
(error (error-message-string e))))
(current-buffer)))
(defvar +emacs-lisp--face nil)
;;
;;; Handlers
(defun +emacs-lisp--module-at-point ()
(let ((origin (point)))
(save-excursion
(goto-char (point-min))
(when (re-search-forward "(doom! " nil 'noerror)
(goto-char (match-beginning 0))
(cl-destructuring-bind (beg . end)
(bounds-of-thing-at-point 'sexp)
(when (and (>= origin beg)
(<= origin end))
(goto-char origin)
(while (not (sexp-at-point))
(forward-symbol -1))
(let (category module flag)
(cond ((keywordp (setq category (sexp-at-point)))
(while (keywordp (sexp-at-point))
(forward-sexp 1))
(setq module (car (doom-enlist (sexp-at-point)))))
((and (symbolp (setq module (sexp-at-point)))
(string-prefix-p "+" (symbol-name module)))
(while (symbolp (sexp-at-point))
(thing-at-point--beginning-of-sexp))
(setq flag module
module (car (sexp-at-point)))
(when (re-search-backward "\\_<:\\w+\\_>" nil t)
(setq category (sexp-at-point))))
((symbolp module)
(when (re-search-backward "\\_<:\\w+\\_>" nil t)
(setq category (sexp-at-point)))))
(list category module flag))))))))
;;;###autoload
(defun +emacs-lisp-highlight-vars-and-faces (end)
"Match defined variables and functions.
Functions are differentiated into special forms, built-in functions and
library/userland functions"
(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)
((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)))
(unless (or (macrop unaliased)
(special-form-p unaliased))
(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))
;; `+emacs-lisp-highlight-vars-and-faces' is a potentially expensive function
;; and should be byte-compiled, no matter what, to ensure it runs as fast as
;; possible:
(unless (byte-code-function-p (symbol-function '+emacs-lisp-highlight-vars-and-faces))
(with-no-warnings
(byte-compile #'+emacs-lisp-highlight-vars-and-faces)))
(defun +emacs-lisp-lookup-definition (_thing)
"Lookup definition of THING."
(if-let (module (+emacs-lisp--module-at-point))
(doom/help-modules (car module) (cadr module) 'visit-dir)
(call-interactively #'elisp-def)))
;;;###autoload
(defun +emacs-lisp-lookup-documentation (thing)
"Lookup THING with `helpful-variable' if it's a variable, `helpful-callable'
if it's callable, `apropos' otherwise."
(if thing
(doom/describe-symbol thing)
(call-interactively #'doom/describe-symbol)))
(cond ((when-let (module (+emacs-lisp--module-at-point))
(doom/help-modules (car module) (cadr module))
(when (eq major-mode 'org-mode)
(with-demoted-errors "%s"
(re-search-forward
(if (caddr module)
"\\* Module Flags$"
"\\* Description$"))
(when (caddr module)
(re-search-forward (format "=\\%s=" (caddr module))
nil t))
(when (invisible-p (point))
(org-show-hidden-entry))))
'deferred))
(thing (helpful-symbol (intern thing)))
((call-interactively #'helpful-at-point))))
;;;###autoload
(defun +emacs-lisp-indent-function (indent-point state)
"A replacement for `lisp-indent-function'.
Indents plists more sensibly. Adapted from
https://emacs.stackexchange.com/questions/10230/how-to-indent-keywords-aligned"
(let ((normal-indent (current-column))
(orig-point (point))
;; TODO Refactor `target' usage (ew!)
target)
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
(cond ((and (elt state 2)
(or (not (looking-at-p "\\sw\\|\\s_"))
(eq (char-after) ?:)))
(unless (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp)
(goto-char calculate-lisp-indent-last-sexp)
(beginning-of-line)
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t))
(backward-prefix-chars)
(current-column))
((and (save-excursion
(goto-char indent-point)
(skip-syntax-forward " ")
(not (eq (char-after) ?:)))
(save-excursion
(goto-char orig-point)
(and (eq (char-after) ?:)
(eq (char-before) ?\()
(setq target (current-column)))))
(save-excursion
(move-to-column target t)
target))
((let* ((function (buffer-substring (point) (progn (forward-sexp 1) (point))))
(method (or (function-get (intern-soft function) 'lisp-indent-function)
(get (intern-soft function) 'lisp-indent-hook))))
(cond ((or (eq method 'defun)
(and (null method)
(> (length function) 3)
(string-match-p "\\`def" function)))
(lisp-indent-defform state indent-point))
((integerp method)
(lisp-indent-specform method state indent-point normal-indent))
(method
(funcall method indent-point state))))))))
;;
@@ -112,10 +170,30 @@ if it's callable, `apropos' otherwise."
load-path)))
(buttercup-run-discover)))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-on ()
"Toggle on instrumentalisation for the function under `defun'."
(interactive)
(eval-defun 'edebugit))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-off ()
"Toggle off instrumentalisation for the function under `defun'."
(interactive)
(eval-defun nil))
;;
;;; Hooks
(autoload 'straight-register-file-modification "straight")
;;;###autoload
(defun +emacs-lisp-init-straight-maybe-h ()
"Make sure straight sees modifications to installed packages."
(when (file-in-directory-p (or buffer-file-name default-directory) doom-local-dir)
(add-hook 'after-save-hook #'straight-register-file-modification
nil 'local)))
;;;###autoload
(defun +emacs-lisp-extend-imenu-h ()
"Improve imenu support in `emacs-lisp-mode', including recognition for Doom's API."
@@ -128,7 +206,7 @@ if it's callable, `apropos' otherwise."
("Minor modes" "^\\s-*(define-\\(?:global\\(?:ized\\)?-minor\\|generic\\|minor\\)-mode +\\([^ ()\n]+\\)" 1)
("Modelines" "^\\s-*(def-modeline! +\\([^ ()\n]+\\)" 1)
("Modeline segments" "^\\s-*(def-modeline-segment! +\\([^ ()\n]+\\)" 1)
("Advice" "^\\s-*(\\(?:def\\(?:\\(?:ine\\)?-advice\\)\\) +\\([^ )\n]+\\)" 1)
("Advice" "^\\s-*(\\(?:def\\(?:\\(?:ine-\\)?advice!?\\)\\) +\\([^ )\n]+\\)" 1)
("Macros" "^\\s-*(\\(?:cl-\\)?def\\(?:ine-compile-macro\\|macro\\) +\\([^ )\n]+\\)" 1)
("Inline functions" "\\s-*(\\(?:cl-\\)?defsubst +\\([^ )\n]+\\)" 1)
("Functions" "^\\s-*(\\(?:cl-\\)?def\\(?:un\\|un\\*\\|method\\|generic\\|-memoized!\\) +\\([^ ,)\n]+\\)" 1)
@@ -142,9 +220,8 @@ verbosity when editing a file in `doom-private-dir' or `doom-emacs-dir'."
(when (and (bound-and-true-p flycheck-mode)
(eq major-mode 'emacs-lisp-mode)
(or (not buffer-file-name)
(cl-loop for dir in (list doom-emacs-dir doom-private-dir)
if (file-in-directory-p buffer-file-name dir)
return t)))
(cl-find-if (doom-partial #'file-in-directory-p buffer-file-name)
+emacs-lisp-disable-flycheck-in-dirs)))
(add-to-list (make-local-variable 'flycheck-disabled-checkers)
'emacs-lisp-checkdoc)
(set (make-local-variable 'flycheck-emacs-lisp-check-form)
@@ -163,14 +240,64 @@ verbosity when editing a file in `doom-private-dir' or `doom-emacs-dir'."
(default-value 'flycheck-emacs-lisp-check-form)
")"))))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-on ()
"Toggle on instrumentalisation for the function under `defun'."
(interactive)
(eval-defun 'edebugit))
;;
;;; Fontification
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-off ()
"Toggle off instrumentalisation for the function under `defun'."
(interactive)
(eval-defun nil))
(defun +emacs-lisp-truncate-pin ()
"Truncates long SHA1 hashes in `package!' :pin's."
(save-excursion
(goto-char (match-beginning 0))
(and (stringp (plist-get (sexp-at-point) :pin))
(search-forward ":pin" nil t)
(let ((start (re-search-forward "\"[^\"]\\{10\\}" nil t))
(finish (and (re-search-forward "\"" (line-end-position) t)
(match-beginning 0))))
(when (and start finish)
(put-text-property start finish 'display "...")))))
nil)
(defvar +emacs-lisp--face nil)
;;;###autoload
(defun +emacs-lisp-highlight-vars-and-faces (end)
"Match defined variables and functions.
Functions are differentiated into special forms, built-in functions and
library/userland functions"
(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)
((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)))
(unless (or (macrop unaliased)
(special-form-p unaliased))
(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))
;; HACK Fontification is already expensive enough. We byte-compile
;; `+emacs-lisp-highlight-vars-and-faces' and `+emacs-lisp-truncate-pin' to
;; ensure they run as fast as possible:
(dolist (fn '(+emacs-lisp-highlight-vars-and-faces +emacs-lisp-truncate-pin))
(unless (byte-code-function-p (symbol-function fn))
(with-no-warnings (byte-compile fn))))

View File

@@ -7,6 +7,14 @@
"Regexp to use for `outline-regexp' in `emacs-lisp-mode'.
This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
(defvar +emacs-lisp-disable-flycheck-in-dirs
(list doom-emacs-dir doom-private-dir)
"List of directories to disable `emacs-lisp-checkdoc' in.
This checker tends to produce a lot of false positives in your .emacs.d and
private config, so it is mostly useless there. However, special hacks are
employed so that flycheck still does *some* helpful linting.")
;; `elisp-mode' is loaded at startup. In order to lazy load its config we need
;; to pretend it isn't loaded
@@ -19,18 +27,19 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
(use-package! elisp-mode
:mode ("\\.Cask\\'" . emacs-lisp-mode)
:config
(set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/open-repl)
(set-eval-handler! 'emacs-lisp-mode #'+emacs-lisp-eval)
(set-lookup-handlers! 'emacs-lisp-mode
:definition #'elisp-def
(set-repl-handler! '(emacs-lisp-mode lisp-interaction-mode) #'+emacs-lisp/open-repl)
(set-eval-handler! '(emacs-lisp-mode lisp-interaction-mode) #'+emacs-lisp-eval)
(set-lookup-handlers! '(emacs-lisp-mode lisp-interaction-mode helpful-mode)
:definition #'+emacs-lisp-lookup-definition
:documentation #'+emacs-lisp-lookup-documentation)
(set-docsets! 'emacs-lisp-mode "Emacs Lisp")
(set-docsets! '(emacs-lisp-mode lisp-interaction-mode) "Emacs Lisp")
(set-pretty-symbols! 'emacs-lisp-mode :lambda "lambda")
(set-rotate-patterns! 'emacs-lisp-mode
:symbols '(("t" "nil")
("let" "let*")
("when" "unless")
("advice-add" "advice-remove")
("defadvice!" "undefadvice!")
("add-hook" "remove-hook")
("add-hook!" "remove-hook!")
("it" "xit")
@@ -42,39 +51,60 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
mode-name "Elisp"
;; Don't treat autoloads or sexp openers as outline headers, we have
;; hideshow for that.
outline-regexp +emacs-lisp-outline-regexp)
outline-regexp +emacs-lisp-outline-regexp
;; Fixed indenter that intends plists sensibly.
lisp-indent-function #'+emacs-lisp-indent-function)
;; variable-width indentation is superior in elisp
(add-to-list 'doom-detect-indentation-excluded-modes 'emacs-lisp-mode nil #'eq)
;; Use helpful instead of describe-* from `company'
(advice-add #'elisp--company-doc-buffer :around #'doom-use-helpful-a)
;; variable-width indentation is superior in elisp. Otherwise, `dtrt-indent'
;; and `editorconfig' would force fixed indentation on elisp.
(add-to-list 'doom-detect-indentation-excluded-modes 'emacs-lisp-mode)
(add-hook! 'emacs-lisp-mode-hook
;; Allow folding of outlines in comments
#'outline-minor-mode
;; fontificiation
;; Make parenthesis depth easier to distinguish at a glance
#'rainbow-delimiters-mode
;; Make quoted symbols easier to distinguish from free variables
#'highlight-quoted-mode
;; initialization
#'+emacs-lisp-extend-imenu-h)
;; Extend imenu support to Doom constructs
#'+emacs-lisp-extend-imenu-h
;; Ensure straight sees modifications to installed packages
#'+emacs-lisp-init-straight-maybe-h)
;; Flycheck's two emacs-lisp checkers produce a *lot* of false positives in
;; emacs configs, so we disable `emacs-lisp-checkdoc' and reduce the
;; `emacs-lisp' checker's verbosity.
(add-hook 'flycheck-mode-hook #'+emacs-lisp-reduce-flycheck-errors-in-emacs-config-h)
;; Special syntax highlighting for elisp...
;; Enhance elisp syntax highlighting, by highlighting Doom-specific
;; constructs, defined symbols, and truncating :pin's in `package!' calls.
(font-lock-add-keywords
'emacs-lisp-mode
(append `(;; custom Doom cookies
("^;;;###\\(autodef\\|if\\|package\\)[ \n]" (1 font-lock-warning-face t)))
;; Shorten the :pin of `package!' statements to 10 characters
`(("(package!\\_>" (0 (+emacs-lisp-truncate-pin))))
;; highlight defined, special variables & functions
(when +emacs-lisp-enable-extra-fontification
`((+emacs-lisp-highlight-vars-and-faces . +emacs-lisp--face)))))
;; Recenter window after following definition
(advice-add #'elisp-def :after #'doom-recenter-a)
(defadvice! +emacs-lisp-append-value-to-eldoc-a (orig-fn sym)
"Display variable value next to documentation in eldoc."
:around #'elisp-get-var-docstring
(when-let (ret (funcall orig-fn sym))
(concat ret " "
(let* ((truncated " [...]")
(print-escape-newlines t)
(str (symbol-value sym))
(str (prin1-to-string str))
(limit (- (frame-width) (length ret) (length truncated) 1)))
(format (format "%%0.%ds%%s" limit)
(propertize str 'face 'warning)
(if (< (length str) limit) "" truncated))))))
(map! :localleader
:map emacs-lisp-mode-map
:desc "Expand macro" "m" #'macrostep-expand
@@ -92,7 +122,15 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
"v" #'find-variable
"l" #'find-library)))
;; Adapted from http://www.modernemacs.com/post/comint-highlighting/
(use-package! ielm
:defer t
:config
(set-lookup-handlers! 'inferior-emacs-lisp-mode
:definition #'+emacs-lisp-lookup-definition
:documentation #'+emacs-lisp-lookup-documentation))
;; Adapted from http://www.modernemacs.com/post/comint-highlighting/ to add
;; syntax highlighting to ielm REPLs.
(add-hook! 'ielm-mode-hook
(defun +emacs-lisp-init-syntax-highlighting-h ()
(font-lock-add-keywords
@@ -117,11 +155,12 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
;;;###package overseer
(autoload 'overseer-test "overseer" nil t)
(remove-hook 'emacs-lisp-mode-hook 'overseer-enable-mode)
;; Properly lazy load overseer by not loading it so early:
(remove-hook 'emacs-lisp-mode-hook #'overseer-enable-mode)
(use-package! flycheck-cask
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:defer t
:init
(add-hook! 'emacs-lisp-mode-hook
@@ -167,8 +206,8 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
(set-yas-minor-mode! 'buttercup-minor-mode)
(when (featurep 'evil)
(add-hook 'buttercup-minor-mode-hook #'evil-normalize-keymaps))
(map! :map buttercup-minor-mode-map
:localleader
(map! :localleader
:map buttercup-minor-mode-map
:prefix "t"
"t" #'+emacs-lisp/buttercup-run-file
"a" #'+emacs-lisp/buttercup-run-project

View File

@@ -3,13 +3,16 @@
(package! elisp-mode :built-in t)
(package! highlight-quoted)
(package! macrostep)
(package! overseer)
(package! elisp-def)
(package! elisp-demos)
;; Fontification plugins
(package! highlight-quoted :pin "24103478158cd19fbcfb4339a3f1fa1f054f1469")
(when (featurep! :tools flycheck)
(package! flycheck-cask))
;; Tools
(package! macrostep :pin "424e3734a1ee526a1bd7b5c3cd1d3ef19d184267")
(package! overseer :pin "02d49f582e80e36b4334c9187801c5ecfb027789")
(package! elisp-def :pin "da1f76391ac0d277e3c5758203e0150f6bae0beb")
(package! elisp-demos :pin "4cd55a30d5dbd8d36a0e6f87261c4fef17fc6db0")
(when (featurep! :checkers syntax)
(package! flycheck-cask :pin "3457ae553c4feaf8168008f063d78fdde8fb5f94"))
(package! buttercup)
;; Libraries
(package! buttercup :pin "e71a40f1ffef4847df28c9d4ad7edc1e360ee52a")

View File

@@ -3,23 +3,22 @@
(use-package! erlang
:mode ("\\.erlang\\'" . erlang-mode)
:mode ("/rebar\\.config\\(?:\\.script\\)?\\'" . erlang-mode)
:mode ("/\\(?:app\\|sys\\)\\.config\\'" . erlang-mode))
:mode ("/\\(?:app\\|sys\\)\\.config\\'" . erlang-mode)
:config
(when (featurep! +lsp)
(add-hook 'erlang-mode-local-vars-hook #'lsp!)))
(use-package! flycheck-rebar3
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after flycheck
:config (flycheck-rebar3-setup))
(use-package! ivy-erlang-complete
:when (featurep! :completion ivy)
:hook (erlang-mode . ivy-erlang-complete-init)
(use-package! company-erlang
:when (featurep! :completion company)
:unless (featurep! +lsp)
:hook (erlang-mode . company-erlang-init)
:config
(add-hook! 'erlang-mode-hook
(add-hook 'after-save-hook #'ivy-erlang-complete-reparse nil t)))
(use-package! company-erlang
:when (featurep! :completion company)
:hook (erlang-mode . company-erlang-init))

View File

@@ -1,13 +1,9 @@
;; -*- no-byte-compile: t; -*-
;;; private/erlang/packages.el
(package! erlang)
(when (featurep! :tools flycheck)
(package! flycheck-rebar3))
(when (featurep! :completion ivy)
(package! ivy-erlang-complete))
(when (featurep! :completion company)
(package! company-erlang))
(package! erlang :pin "3065fbf434")
(when (featurep! :checkers syntax)
(package! flycheck-rebar3 :pin "3cca1268c5"))
(unless (featurep! +lsp)
(when (featurep! :completion company)
(package! company-erlang :pin "bc0524a16f")))

View File

@@ -4,9 +4,16 @@ This module adds support for various statistics languages, including R, S-Plus,
SAS, Julia and Stata.
* Table of Contents :TOC:
- [[Appendix][Appendix]]
- [[Keybindings][Keybindings]]
- [[#prequisites][Prequisites]]
- [[#appendix][Appendix]]
- [[#keybindings][Keybindings]]
* Prequisites
This module has several optional dependencies:
+ [[https://github.com/jimhester/lintr][lintr]]: Enables R linting.
+ [[https://github.com/REditorSupport/languageserver][languageserver]]: Enables LSP support in an R buffer (with =+lsp= flag).
* Appendix
** Keybindings
*** :map ess-doc-map

View File

@@ -10,17 +10,19 @@
(use-package! ess
:commands stata SAS
:init
(setq ess-smart-S-assign-key nil)
(unless (featurep! :lang julia)
(add-to-list 'auto-mode-alist '("\\.jl\\'" . ess-julia-mode)))
:config
(setq ess-offset-continued 'straight
ess-expression-offset 2
ess-use-flymake (not (featurep! :tools flycheck))
ess-use-flymake (not (featurep! :checkers syntax))
ess-nuke-trailing-whitespace-p t
ess-default-style 'DEFAULT
ess-style 'DEFAULT
ess-history-directory (expand-file-name "ess-history/" doom-cache-dir))
(set-docsets! 'ess-r-mode "R")
(when (featurep! +lsp)
(add-hook 'ess-r-mode-local-vars-hook #'lsp!))
(set-repl-handler! 'ess-r-mode #'+ess/open-r-repl)
(set-repl-handler! 'ess-julia-mode #'+ess/open-julia-repl)
(set-lookup-handlers! '(ess-r-mode ess-julia-mode)
@@ -30,26 +32,32 @@
(set-eval-handler! 'ess-help-mode #'ess-eval-region-and-go)
(set-eval-handler! 'ess-r-help-mode #'ess-eval-region-and-go)
(map! (:after ess-help
:map ess-help-mode-map
:n "q" #'kill-current-buffer
:n "Q" #'ess-kill-buffer-and-go
:n "K" #'ess-display-help-on-object
:n "go" #'ess-display-help-in-browser
:n "gO" #'ess-display-help-apropos
:n "gv" #'ess-display-vignettes
:m "]]" #'ess-skip-to-next-section
:m "[[" #'ess-skip-to-previous-section
:map ess-doc-map
"h" #'ess-display-help-on-object
"p" #'ess-R-dv-pprint
"t" #'ess-R-dv-ctable
[C-return] #'ess-eval-line
[up] #'comint-next-input
[down] #'comint-previous-input)
(setq-hook! 'ess-r-mode-hook
;; HACK Fix #2233: Doom continues comments on RET, but ess-r-mode doesn't
;; have a sane `comment-line-break-function', so...
comment-line-break-function nil)
(map! (:after ess-help
(:map ess-help-mode-map
:n "q" #'kill-current-buffer
:n "Q" #'ess-kill-buffer-and-go
:n "K" #'ess-display-help-on-object
:n "go" #'ess-display-help-in-browser
:n "gO" #'ess-display-help-apropos
:n "gv" #'ess-display-vignettes
:m "]]" #'ess-skip-to-next-section
:m "[[" #'ess-skip-to-previous-section)
(:map ess-doc-map
"h" #'ess-display-help-on-object
"p" #'ess-R-dv-pprint
"t" #'ess-R-dv-ctable
[up] #'comint-next-input
[down] #'comint-previous-input
[C-return] #'ess-eval-line))
:localleader
:map ess-mode-map
:n [C-return] #'ess-eval-line
:localleader
"," #'ess-eval-region-or-function-or-paragraph-and-step
"'" #'R
[tab] #'ess-switch-to-inferior-or-script-buffer

View File

@@ -1,5 +1,7 @@
;; -*- no-byte-compile: t; -*-
;;; lang/ess/packages.el
(package! ess)
(package! ess-R-data-view)
(package! ess :pin "625041ad51")
(package! ess-R-data-view :pin "d6e98d3ae1")
(package! polymode :pin "44265e3516")
(package! poly-R :pin "51ffeb6ec4")

View File

@@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/factor/packages.el
(package! fuel)
(package! fuel :pin "497d6491e6")

View File

@@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/faust/packages.el
(package! faustine)
(package! faustine :pin "07a3896311")

View File

@@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/fsharp/packages.el
(package! fsharp-mode)
(package! fsharp-mode :pin "8c86e38b93")

View File

@@ -15,7 +15,8 @@
- [[#troubleshooting][Troubleshooting]]
* Description
This module adds [[https://golang.org][Go]] support.
This module adds [[https://golang.org][Go]] support, with optional (but recommended) LSP support via
[[https://github.com/golang/tools/blob/master/gopls/README.md][gopls]].
+ Code completion (~gocode~)
+ Documentation lookup (~godoc~)
@@ -30,7 +31,8 @@ This module adds [[https://golang.org][Go]] support.
+ Code checking (~flycheck-golangci-lint~)
** Module Flags
+ =+lsp= Enables integration for the gopls LSP server.
+ =+lsp= Enables integration for the gopls LSP server. It is highly recommended
you use this, as the non-LSP experience is deprecated (and poor).
** Plugins
+ [[https://github.com/dominikh/go-mode.el][go-mode]]
@@ -38,9 +40,9 @@ This module adds [[https://golang.org][Go]] support.
+ [[https://github.com/dominikh/go-mode.el][go-guru]]
+ [[https://github.com/manute/gorepl-mode][gorepl-mode]]
+ [[https://github.com/brantou/emacs-go-tag][go-tag]]
+ [[https://github.com/mdempsky/gocode][company-go]]*
+ [[https://github.com/mdempsky/gocode][company-go]]* =DEPRECATED=
+ [[https://github.com/s-kostyaev/go-gen-test][go-gen-test]]
+ [[https://github.com/weijiangan/flycheck-golangci-lint][flycheck-golangci-lint]] (if =:tools flycheck= is enabled)
+ [[https://github.com/weijiangan/flycheck-golangci-lint][flycheck-golangci-lint]] (if =:checkers syntax= is enabled)
* Prerequisites
** Go
@@ -77,7 +79,7 @@ This module requires a valid ~GOPATH~, and the following Go packages:
export GOPATH=~/work/go
go get -u github.com/motemen/gore/cmd/gore
go get -u github.com/mdempsky/gocode
go get -u github.com/stamblerre/gocode
go get -u golang.org/x/tools/cmd/godoc
go get -u golang.org/x/tools/cmd/goimports
go get -u golang.org/x/tools/cmd/gorename

View File

@@ -41,6 +41,21 @@
(+go--run-tests (concat "-run" "='" (match-string-no-properties 2) "'")))
(error "Must be in a _test.go file")))
;;;###autoload
(defun +go/bench-all ()
(interactive)
(+go--run-tests "-test.run=NONE -test.bench=\".*\""))
;;;###autoload
(defun +go/bench-single ()
(interactive)
(if (string-match "_test\\.go" buffer-file-name)
(save-excursion
(re-search-backward "^func[ ]+\\(([[:alnum:]]*?[ ]?[*]?[[:alnum:]]+)[ ]+\\)?\\(Benchmark[[:alnum:]_]+\\)(.*)")
(+go--run-tests (concat "-test.run=NONE -test.bench" "='" (match-string-no-properties 2) "'")))
(error "Must be in a _test.go file")))
;;;###autoload
(defun +go/play-buffer-or-region (&optional beg end)
"TODO"

View File

@@ -44,10 +44,10 @@
(:prefix ("ri" . "imports")
"a" #'go-import-add
"r" #'go-remove-unused-imports)
(:prefix ( "b" . "build")
:desc "go run ." "r" (λ! (compile "go run ."))
:desc "go build" "b" (λ! (compile "go build"))
:desc "go clean" "c" (λ! (compile "go clean")))
(:prefix ("b" . "build")
:desc "go run ." "r" (cmd! (compile "go run ."))
:desc "go build" "b" (cmd! (compile "go build"))
:desc "go clean" "c" (cmd! (compile "go clean")))
(:prefix ("t" . "test")
"t" #'+go/test-rerun
"a" #'+go/test-all
@@ -55,7 +55,10 @@
"n" #'+go/test-nested
"g" #'go-gen-test-dwim
"G" #'go-gen-test-all
"e" #'go-gen-test-exported)))
"e" #'go-gen-test-exported
(:prefix ("b" . "bench")
"s" #'+go/bench-single
"a" #'+go/bench-all))))
(use-package! gorepl-mode
@@ -71,5 +74,5 @@
(setq company-go-show-annotation t))
(use-package! flycheck-golangci-lint
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:hook (go-mode . flycheck-golangci-lint-setup))

View File

@@ -1,15 +1,15 @@
;; -*- no-byte-compile: t; -*-
;;; lang/go/packages.el
(package! go-eldoc)
(package! go-guru)
(package! go-mode)
(package! gorepl-mode)
(package! go-tag)
(package! go-gen-test)
(package! go-eldoc :pin "cbbd2ea1e94a36004432a9ac61414cb5a95a39bd")
(package! go-guru :pin "734d5232455ffde088021ea5908849ac570e890f")
(package! go-mode :pin "734d5232455ffde088021ea5908849ac570e890f")
(package! gorepl-mode :pin "6a73bf352e8d893f89cad36c958c4db2b5e35e07")
(package! go-tag :pin "59b243f2fa079d9de9d56f6e2d94397e9560310a")
(package! go-gen-test :pin "44c202ac97e728e93a35cee028a0ea8dd6e4292c")
(when (featurep! :completion company)
(package! company-go))
(package! company-go :pin "4acdcbdea79de6b3dee1c637eca5cbea0fdbe37c"))
(when (featurep! :tools flycheck)
(package! flycheck-golangci-lint))
(when (featurep! :checkers syntax)
(package! flycheck-golangci-lint :pin "8e446c68311048f0b87febf8ef0379e29d358851"))

View File

@@ -14,7 +14,7 @@
"-fdefer-typed-holes"
"-fdefer-type-errors"))
:config
(when (featurep! :tools flycheck)
(when (featurep! :checkers syntax)
(flycheck-add-next-checker 'haskell-dante '(warning . haskell-hlint)))
(set-company-backend! 'dante-mode #'dante-company)
@@ -36,6 +36,6 @@ reformatting)."
:localleader
"t" #'dante-type-at
"i" #'dante-info
"l" #'haskell-process-load-or-reload
"l" #'haskell-process-load-file
"e" #'dante-eval-block
"a" #'attrap-attrap))

View File

@@ -1,30 +0,0 @@
;;; lang/haskell/+intero.el -*- lexical-binding: t; -*-
;;;###if (featurep! +intero)
(use-package! intero
:commands intero-mode
:init
(add-hook! 'haskell-mode-local-vars-hook
(defun +haskell-init-intero-h ()
"Initializes `intero-mode' in haskell-mode, unless stack isn't installed.
This is necessary because `intero-mode' doesn't do its own error checks."
(when (derived-mode-p 'haskell-mode)
(if (executable-find "stack")
(intero-mode +1)
(message "Couldn't find stack. Refusing to enable intero-mode.")))))
:config
(setq haskell-compile-cabal-build-command "stack build --fast")
(set-lookup-handlers! 'intero-mode :definition #'intero-goto-definition)
(set-company-backend! 'intero-mode 'intero-company)
(when (featurep! :tools flycheck)
(flycheck-add-next-checker 'intero '(warning . haskell-hlint)))
(when (featurep 'evil)
(add-hook 'intero-mode-hook #'evil-normalize-keymaps))
(map! :localleader
:map intero-mode-map
"t" #'intero-type-at
"i" #'intero-info
"l" #'intero-repl-load
"e" #'intero-repl-eval-region
"a" #'intero-apply-suggestions))

View File

@@ -1,10 +1,13 @@
;;; lang/haskell/+lsp.el -*- lexical-binding: t; -*-
(use-package! lsp-haskell
:after haskell-mode
:init (add-hook 'haskell-mode-hook #'lsp!)
:after lsp-clients
:preface (add-hook 'haskell-mode-local-vars-hook #'lsp!)
:config
(when IS-MAC
(setq lsp-haskell-process-path-hie "hie-wrapper"))
(when (featurep! +ghcide)
(setq lsp-haskell-process-path-hie "ghcide"
lsp-haskell-process-args-hie nil))
;; Does some strange indentation if it pastes in the snippet
(setq-hook! 'haskell-mode-hook yas-indent-line 'fixed))

View File

@@ -10,7 +10,8 @@
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#cabal][Cabal]]
- [[#lsp][LSP]]
- [[#lsp-haskell-ide-engine][LSP (haskell-ide-engine)]]
- [[#lsp-ghcide][LSP (ghcide)]]
- [[#stack][Stack]]
- [[#haskell-packages][Haskell packages]]
- [[#configuration][Configuration]]
@@ -18,8 +19,8 @@
- [[#troubleshooting][Troubleshooting]]
* Description
This module adds [[https://www.haskell.org/][Haskell]] support, powered by either [[https://github.com/jyp/dante][dante]] (the default), LSP or
[[https://haskell-lang.org/intero][intero]].
This module adds [[https://www.haskell.org/][Haskell]] support, powered by either [[https://github.com/jyp/dante][dante]] (the default) or LSP
(haskell-language-server or ghcide).
+ Code completion (~company-ghc~)
+ Look up documentation (~hoogle~)
@@ -41,9 +42,9 @@ Here are a few resources I've found indispensable in my Haskell adventures:
+ =+dante= Enables dante; a fork of intero aimed at lightweightedness. It
doesn't depend on =stack=, supports both ~cabal~-only and ~stack~ projects,
but lacks eldoc support.
+ =+lsp= Enables lsp-haskell (this requires the ~:tools lsp~ to be enabled).
+ =+intero= (Deprecated) Enables intero; a comprehensive, stack-based
development environment for Haskell.
+ =+ghcide= Enables LSP support with ghcide (requires the ~:tools lsp~ module).
+ =+lsp= Enables LSP support with haskell-ide-engine (requires the ~:tools lsp~
module).
** Plugins
+ [[https://github.com/haskell/haskell-mode][haskell-mode]]
@@ -52,16 +53,13 @@ Here are a few resources I've found indispensable in my Haskell adventures:
+ [[https://github.com/jyp/attrap][attrap]]
+ =+lsp=
+ [[https://github.com/emacs-lsp/lsp-haskell][lsp-haskell]]
+ =+intero=
+ [[https://github.com/chrisdone/intero][intero]]
* Prerequisites
Depending on whether you use Intero, Dante or LSP, your dependencies will
differ:
Depending on whether you use Dante, haskell-language-server or ghcide, your
dependencies will differ:
+ Dante users need =cabal=, =ghc= and =ghc-mod=
+ LSP users need the =haskell-ide-engine= LSP server
+ Intero and LSP users need =stack=
+ LSP users need the =haskell-ide-engine= LSP server OR =ghcide=
+ All users will need the =hoogle= package
** Cabal
@@ -83,7 +81,7 @@ sudo pacman -S cabal-install ghc
sudo zypper install cabal-install ghc
#+END_SRC
** LSP
** LSP (haskell-ide-engine)
You will need =stack= and =git= installed.
You will find a comprehensive [[https://github.com/haskell/haskell-ide-engine#installation][install guide for haskell-ide-engine on its
@@ -92,7 +90,7 @@ project page]], but here's a TL;DR:
*** MacOS
haskell-ide-engine must be build and installed manually on MacOS, e.g.
#+BEGIN_SRC emacs-lisp
#+BEGIN_SRC bash
git clone https://github.com/haskell/haskell-ide-engine
cd haskell-ide-engine
make
@@ -101,12 +99,14 @@ make
*** Arch Linux
=haskell-ide-engine-git= is available on the AUR
#+BEGIN_SRC emacs-lisp
#+BEGIN_SRC bash
yay -S haskell-ide-engine-git
#+END_SRC
** LSP (ghcide)
See https://github.com/digital-asset/ghcide for install instructions.
** Stack
To use Intero or LSP, you need =stack=:
To use LSP, you need =stack=:
*** MacOS
#+BEGIN_SRC sh

View File

@@ -4,11 +4,25 @@
(defun +haskell/open-repl (&optional arg)
"Opens a Haskell REPL."
(interactive "P")
(if-let*
((window
(display-buffer
(if (featurep! +intero)
(intero-repl-buffer arg)
(haskell-session-interactive-buffer (haskell-session))))))
(if-let (window
(display-buffer
(haskell-session-interactive-buffer (haskell-session))))
(window-buffer window)
(error "Failed to display Haskell REPL")))
;;;###autoload
(defun +haskell/evil-open-above ()
"Opens a line above the current mode"
(interactive)
(evil-digit-argument-or-evil-beginning-of-line)
(haskell-indentation-newline-and-indent)
(evil-previous-line)
(haskell-indentation-indent-line)
(evil-append-line nil))
;;;###autoload
(defun +haskell/evil-open-below ()
"Opens a line below the current mode"
(interactive)
(evil-append-line nil)
(haskell-indentation-newline-and-indent))

View File

@@ -3,19 +3,14 @@
(after! projectile
(add-to-list 'projectile-project-root-files "stack.yaml"))
;; TODO ghcide?
(cond ((featurep! +intero) (load! "+intero")) ; DEPRECATED
((featurep! +dante) (load! "+dante"))
((featurep! +lsp) (load! "+lsp")))
;;
;; Common packages
;;; Common packages
(after! haskell-mode
(setq haskell-process-suggest-remove-import-lines t ; warnings for redundant imports etc
haskell-process-auto-import-loaded-modules t
haskell-process-show-overlays (not (featurep! :tools flycheck))) ; redundant with flycheck
haskell-process-show-overlays (not (featurep! :checkers syntax))) ; redundant with flycheck
(set-lookup-handlers! 'haskell-mode
:definition #'haskell-mode-jump-to-def-or-tag)
@@ -25,6 +20,8 @@
(set-repl-handler!
'(haskell-mode haskell-cabal-mode literate-haskell-mode)
#'+haskell/open-repl :persist t)
;; Don't kill REPL popup on ESC/C-g
(set-popup-rule! "^\\*haskell\\*" :quit nil)
(add-hook! 'haskell-mode-hook
#'haskell-collapse-mode ; support folding haskell code blocks
@@ -32,10 +29,24 @@
(add-to-list 'completion-ignored-extensions ".hi")
(map! :map haskell-mode-map
:n "o" #'+haskell/evil-open-below
:n "O" #'+haskell/evil-open-above
(:when (featurep! :tools lookup)
[remap haskell-mode-jump-to-def-or-tag] #'+lookup/definition))
(map! :localleader
:map haskell-mode-map
;; this is set to use cabal for dante users and stack for intero users:
"b" #'haskell-process-cabal-build
"c" #'haskell-cabal-visit-file
"h" #'haskell-hide-toggle
"H" #'haskell-hide-toggle-all))
;;
;;; Backends
(cond ((featurep! +dante) (load! "+dante"))
((or (featurep! +lsp)
(featurep! +ghcide))
(load! "+lsp")))

View File

@@ -7,12 +7,6 @@
(when (featurep! +dante)
(unless (executable-find "cabal")
(warn! "Couldn't find cabal, haskell-mode may have issues")))
(when (featurep! +intero)
(unless (executable-find "stack")
(warn! "Couldn't find stack. Intero will not work")))
(when (or (featurep! +dante) (featurep! +intero))
(warn! "Couldn't find cabal, haskell-mode may have issues"))
(unless (executable-find "hlint")
(warn! "Couldn't find hlint. Flycheck may have issues in haskell-mode")))

View File

@@ -1,12 +1,12 @@
;; -*- no-byte-compile: t; -*-
;;; lang/haskell/packages.el
(package! haskell-mode)
(package! haskell-mode :pin "41683c0e634bb3f54eac8747919a82132e1714fe")
(cond ((featurep! +dante)
(package! dante)
(package! attrap))
((featurep! +lsp)
(package! lsp-haskell))
((featurep! +intero) ; DEPRECATED
(package! intero)))
(when (featurep! +dante)
(package! dante :pin "7411904bfbde25cdb986e001ec682593dcb7c5e3")
(package! attrap :pin "4cf3e4a16255997e7c3c39682a72866a0a37dd4b"))
(when (or (and (featurep! +lsp)
(not (featurep! :tools lsp +eglot)))
(featurep! +ghcide))
(package! lsp-haskell :pin "17d7d4c6615b5e6c7442828720730bfeda644af8"))

View File

@@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/hy/packages.el
(package! hy-mode)
(package! hy-mode :pin "e2d5fecdae")

View File

@@ -4,8 +4,7 @@
(add-hook 'idris-mode-hook #'turn-on-idris-simple-indent)
(set-repl-handler! 'idris-mode 'idris-pop-to-repl)
(set-lookup-handlers! 'idris-mode
:documentation #'idris-docs-at-point
:file #'idris-load-file)
:documentation #'idris-docs-at-point)
(map! :localleader
:map idris-mode-map
"r" #'idris-load-file

View File

@@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; lang/idris/packages.el
(package! idris-mode)
(package! idris-mode :pin "acc8835449")

View File

@@ -2,11 +2,20 @@
;;;###if (featurep! +lsp)
(use-package! lsp-java
:after-call java-mode
:init
:after lsp-clients
:preface
(setq lsp-java-workspace-dir (concat doom-etc-dir "java-workspace"))
(add-hook 'java-mode-local-vars-hook #'lsp!)
(setq lsp-java-server-install-dir (concat doom-etc-dir "eclipse.jdt.ls/server/"))
(map! :when (featurep! :tools debugger +lsp)
:after cc-mode ; where `java-mode' is defined
:map java-mode-map
:localleader
(:prefix ("t" . "Test")
:desc "Run test class or method" "t" #'+java/run-test
:desc "Run all tests in class" "a" #'dap-java-run-test-class
:desc "Debug test class or method" "d" #'+java/debug-test
:desc "Debug all tests in class" "D" #'dap-java-debug-test-class))
:config
;; TODO keybinds
;; TODO treemacs integration (?)
)
(when (featurep! :tools debugger +lsp)
(setq lsp-jt-root (concat lsp-java-server-install-dir "java-test/server/")
dap-java-test-runner (concat lsp-java-server-install-dir "test-runner/junit-platform-console-standalone.jar"))))

View File

@@ -6,7 +6,7 @@
:init
(setq meghanada-server-install-dir (concat doom-etc-dir "meghanada-server/")
meghanada-use-company (featurep! :completion company)
meghanada-use-flycheck (featurep! :tools flycheck)
meghanada-use-flycheck (featurep! :checkers syntax)
meghanada-use-eldoc t
meghanada-use-auto-start t)
:config

View File

@@ -1,73 +0,0 @@
;;; lang/java/config.el -*- lexical-binding: t; -*-
;; yasnippet defuns
;;;###autoload
(defun +java-android-mode-is-layout-file ()
(and android-mode
(eq major-mode 'nxml-mode)
(string-equal (file-name-base (directory-file-name default-directory)) "layout")))
;;;###autoload
(defun +java-android-mode-in-tags (&rest tags)
(cl-find (android-mode-tag-name) tags))
;;;###autoload
(defun +java-android-mode-tag-name ()
(save-excursion
(let (beg end)
(nxml-backward-up-element)
(evil-forward-word-begin)
(setq beg (point))
(evil-forward-WORD-end)
(setq end (1+ (point)))
(buffer-substring-no-properties beg end))))
;;;###autoload
(defun +java-android-mode-maybe-h ()
"Enable `android-mode' if this looks like an android project.
It determines this by the existence of AndroidManifest.xml or
src/main/AndroidManifest.xml."
(when (project-file-exists-p! (or "AndroidManifest.xml"
"src/main/AndroidManifest.xml"))
(android-mode +1)))
;;;###autoload
(defun +java-current-package ()
"Converts the current file's path into a namespace.
For example: ~/some/project/src/net/lissner/game/MyClass.java
Is converted to: net.lissner.game
It does this by ignoring everything before the nearest package root (see
`+java-project-package-roots' to control what this function considers a package
root)."
(unless (eq major-mode 'java-mode)
(user-error "Not in a java-mode buffer"))
(let* ((project-root (file-truename (doom-project-root)))
(file-path (file-name-sans-extension
(file-truename (or buffer-file-name
default-directory))))
(src-root (cl-loop for root in +java-project-package-roots
if (and (stringp root)
(locate-dominating-file file-path root))
return (file-name-directory (file-relative-name file-path (expand-file-name root it)))
if (and (integerp root)
(> root 0)
(let* ((parts (split-string (file-relative-name file-path project-root) "/"))
(fixed-parts (reverse (nbutlast (reverse parts) root))))
(when fixed-parts
(string-join fixed-parts "/"))))
return it)))
(when src-root
(string-remove-suffix "." (replace-regexp-in-string "/" "." src-root)))))
;;;###autoload
(defun +java-current-class ()
"Get the class name for the current file."
(unless (eq major-mode 'java-mode)
(user-error "Not in a java-mode buffer"))
(unless buffer-file-name
(user-error "This buffer has no filepath; cannot guess its class name"))
(or (file-name-sans-extension (file-name-base (buffer-file-name)))
"ClassName"))

View File

@@ -22,7 +22,7 @@ If the depth is 2, the first two directories are removed: net.lissner.game.")
;;
;; java-mode
;;; java-mode
(add-hook 'java-mode-hook #'rainbow-delimiters-mode)
@@ -31,7 +31,7 @@ If the depth is 2, the first two directories are removed: net.lissner.game.")
;;
;; Common packages
;;; Common packages
(use-package! android-mode
:commands android-mode
@@ -45,4 +45,6 @@ If the depth is 2, the first two directories are removed: net.lissner.game.")
(use-package! groovy-mode
:mode "\\.g\\(?:radle\\|roovy\\)$"
:config
(set-eval-handler! 'groovy-mode "groovy"))
(set-docsets! 'groovy-mode "Groovy" "Groovy_JDK")
(set-eval-handler! 'groovy-mode "groovy")
(set-repl-handler! 'groovy-mode #'+java/groovy-open-repl))

View File

@@ -1,16 +1,16 @@
;; -*- no-byte-compile: t; -*-
;;; lang/java/packages.el
(package! android-mode)
(package! groovy-mode)
(package! android-mode :pin "d5332e339a")
(package! groovy-mode :pin "cafdd98e06")
(when (featurep! +meghanada)
(package! meghanada))
(package! meghanada :pin "70bfbf553c"))
(when (featurep! +eclim)
(package! eclim)
(package! eclim :pin "23f5b294f8")
(when (featurep! :completion company)
(package! company-emacs-eclim)))
(package! company-emacs-eclim :pin "23f5b294f8")))
(when (featurep! +lsp)
(package! lsp-java))
(package! lsp-java :pin "6efb741845"))

View File

@@ -11,6 +11,8 @@
- [[#macos][MacOS]]
- [[#arch-linux][Arch Linux]]
- [[#opensuse][openSUSE]]
- [[#troubleshooting][Troubleshooting]]
- [[#tide-sort-completions-by-kind-isnt-respected][~tide-sort-completions-by-kind~ isn't respected]]
- [[#appendix][Appendix]]
- [[#commands][Commands]]
@@ -35,7 +37,6 @@ This module adds JavaScript and TypeScript support.
+ [[https://github.com/mooz/js2-mode][js2-mode]]
+ [[https://github.com/felipeochoa/rjsx-mode][rjsx-mode]]
+ [[https://github.com/emacs-typescript/typescript.el][typescript-mode]]
+ [[https://github.com/aaronjensen/eslintd-fix][eslintd-fix]]
+ [[https://github.com/magnars/js2-refactor.el][js2-refactor]]
+ [[https://github.com/mojochao/npm-mode][npm-mode]]
+ [[https://github.com/abicky/nodejs-repl.el][nodejs-repl]]
@@ -62,6 +63,12 @@ sudo pacman --needed --noconfirm -S nodejs npm
sudo zypper install nodejs npm
#+END_SRC
* Troubleshooting
** ~tide-sort-completions-by-kind~ isn't respected
The =:completion company= module uses =company-prescient= to sort completion by
[[https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Places/Frecency_algorithm][frecency]], which overrules specialized sorting provided by some company backends
(like ~company-tide~).
* Appendix
** Commands
*** JS2-mode

View File

@@ -42,7 +42,9 @@ skewer-*-mode's are enabled, or `nodejs-repl' otherwise."
(interactive)
(call-interactively
(if (and (featurep 'skewer-mode)
(or skewer-mode skewer-css-mode skewer-html-mode))
(or (bound-and-true-p skewer-mode)
(bound-and-true-p skewer-css-mode)
(bound-and-true-p skewer-html-mode)))
#'skewer-repl
#'nodejs-repl))
(current-buffer))
@@ -60,12 +62,17 @@ Run this for any buffer you want to skewer."
(require 'skewer-mode)
(unless (process-status "httpd")
(run-skewer))
(unless (and skewer-mode skewer-css-mode skewer-html-mode)
(pcase major-mode
((or 'css-mode 'scss-mode 'less-css-mode) (skewer-css-mode +1))
((or 'web-mode 'html-mode) (skewer-html-mode +1))
('js2-mode (skewer-mode +1))
(_ (error "Invalid mode %s" major-mode)))))
(pcase major-mode
((or 'css-mode 'scss-mode 'less-css-mode)
(unless (bound-and-true-p skewer-css-mode)
(skewer-css-mode +1)))
((or 'web-mode 'html-mode)
(unless (bound-and-true-p skewer-html-mode)
(skewer-html-mode +1)))
('js2-mode
(unless (bound-and-true-p skewer-mode)
(skewer-mode +1)))
(_ (error "Invalid mode %s" major-mode))))
;;;###autoload
(defun +javascript/skewer-cleanup ()
@@ -75,26 +82,17 @@ Run this for any buffer you want to skewer."
(httpd-stop))
(dolist (buf (buffer-list))
(with-current-buffer buf
(if skewer-mode (skewer-mode -1))
(if skewer-css-mode (skewer-css-mode -1))
(if skewer-html-mode (skewer-html-mode -1)))))
(if (bound-and-true-p skewer-mode)
(skewer-mode -1))
(if (bound-and-true-p skewer-css-mode)
(skewer-css-mode -1))
(if (bound-and-true-p skewer-html-mode)
(skewer-html-mode -1)))))
;;
;; Hooks
;;;###autoload
(defun +javascript-add-node-modules-path-h ()
"Add current project's `node_modules/.bin` to `exec-path', so js tools
prioritize project-local packages over global ones."
(make-local-variable 'exec-path)
(cl-pushnew (expand-file-name "node_modules/.bin/"
(or (locate-dominating-file
(or (buffer-file-name) default-directory)
"node_modules")
(doom-project-root)))
exec-path :test #'string=))
;;;###autoload
(defun +javascript-cleanup-tide-processes-h ()
"Clean up dangling tsserver processes if there are no more buffers with

View File

@@ -58,11 +58,7 @@
mode-name "JS2")
(set-electric! 'js2-mode :chars '(?\} ?\) ?. ?:))
(set-repl-handler! 'js2-mode #'+javascript/open-repl)
(map! :map js2-mode-map
:localleader
"S" #'+javascript/skewer-this-buffer))
(set-repl-handler! 'js2-mode #'+javascript/open-repl))
(use-package! rjsx-mode
@@ -79,28 +75,26 @@
(add-to-list 'magic-mode-alist '(+javascript-jsx-file-p . rjsx-mode))
:config
(set-electric! 'rjsx-mode :chars '(?\} ?\) ?. ?>))
(when (featurep! :tools flycheck)
(when (featurep! :checkers syntax)
(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 tags to stay unclosed, so we force it to parse.
;; HACK `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. The parser doesn't run immediately however, so a fast typist
;; can outrun it, causing tags to stay unclosed, so force it to parse:
(defadvice! +javascript-reparse-a (n)
;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself
:before #'rjsx-electric-gt
(if (= n 1) (rjsx-maybe-reparse))))
(after! typescript-mode
(add-hook 'typescript-mode-hook #'rainbow-delimiters-mode)
(setq-hook! 'typescript-mode-hook
comment-line-break-function #'js2-line-break)
(use-package! typescript-mode
:hook (typescript-mode . rainbow-delimiters-mode)
:config
(set-electric! 'typescript-mode
:chars '(?\} ?\)) :words '("||" "&&"))
(set-docsets! 'typescript-mode "TypeScript" "AngularTS")
(set-pretty-symbols! 'typescript-mode
;; Functional
:def "function"
@@ -116,7 +110,29 @@
:not "!"
:and "&&" :or "||"
:for "for"
:return "return" :yield "import"))
:return "return" :yield "import")
;; HACK Fixes comment continuation on newline
(setq-hook! 'typescript-mode-hook
comment-line-break-function #'js2-line-break))
;; REVIEW We associate TSX files with `typescript-tsx-mode' derived from
;; `web-mode' because `typescript-mode' does not officially support
;; JSX/TSX. See
;; https://github.com/emacs-typescript/typescript.el/issues/4
(if (featurep! :lang web)
(progn
(define-derived-mode typescript-tsx-mode web-mode "TypeScript-tsx")
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-tsx-mode))
(add-hook 'typescript-tsx-mode-hook #'emmet-mode)
(after! flycheck
(flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)
(flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode)))
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode)))
(after! (:any typescript-mode web-mode)
(set-docsets! '(typescript-mode typescript-tsx-mode) "TypeScript" "AngularTS"))
;;;###package coffee-mode
@@ -128,7 +144,11 @@
;;
;;; Tools
(add-hook! '(js-mode-hook typescript-mode-hook web-mode-hook)
(add-hook! '(js2-mode-local-vars-hook
typescript-mode-local-vars-hook
typescript-tsx-mode-local-vars-hook
web-mode-local-vars-hook
rjsx-mode-local-vars-hook)
(defun +javascript-init-lsp-or-tide-maybe-h ()
"Start `lsp' or `tide' in the current buffer.
@@ -138,13 +158,11 @@ current buffer represents a file in a project.
If LSP fails to start (e.g. no available server or project), then we fall back
to tide."
(let ((buffer-file-name (buffer-file-name (buffer-base-buffer))))
(when (or (derived-mode-p 'js-mode 'typescript-mode)
(and (eq major-mode 'web-mode)
(string= "tsx" (file-name-extension buffer-file-name))))
(when (derived-mode-p 'js-mode 'typescript-mode 'typescript-tsx-mode)
(if (not buffer-file-name)
;; necessary because `tide-setup' and `lsp' will error if not a
;; file-visiting buffer
(add-hook 'after-save-hook #'+javascript-init-tide-or-lsp-maybe-h nil 'local)
(add-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h nil 'local)
(or (and (featurep! +lsp) (lsp!))
;; fall back to tide
(if (executable-find "node")
@@ -152,14 +170,18 @@ to tide."
(progn (tide-setup) tide-mode))
(ignore
(doom-log "Couldn't start tide because 'node' is missing"))))
(remove-hook 'after-save-hook #'+javascript-init-tide-or-lsp-maybe-h 'local))))))
(remove-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h 'local))))))
(use-package! tide
:defer t
:config
(setq tide-completion-detailed t
tide-always-show-documentation t)
tide-always-show-documentation t
;; Fix #1792: by default, tide ignores payloads larger than 100kb. This
;; is too small for larger projects that produce long completion lists,
;; so we up it to 512kb.
tide-server-max-response-length 524288)
;; code completion
(after! company
;; tide affects the global `company-backends', undo this so doom can handle
@@ -167,9 +189,11 @@ to tide."
(setq-default company-backends (delq 'company-tide (default-value 'company-backends))))
(set-company-backend! 'tide-mode 'company-tide)
;; navigation
(set-lookup-handlers! 'tide-mode
:definition '(tide-jump-to-definition :async t)
:references '(tide-references :async t))
(set-lookup-handlers! 'tide-mode :async t
:definition #'tide-jump-to-definition
:references #'tide-references
:documentation #'tide-documentation-at-point)
(set-popup-rule! "^\\*tide-documentation" :quit t)
;; resolve to `doom-project-root' if `tide-project-root' fails
(advice-add #'tide-project-root :override #'+javascript-tide-project-root-a)
;; cleanup tsserver when no tide buffers are left
@@ -182,8 +206,6 @@ to tide."
;; `tide-mode-hook' is too early, so...
(advice-add #'tide-setup :after #'eldoc-mode)
(define-key tide-mode-map [remap +lookup/documentation] #'tide-documentation-at-point)
(map! :localleader
:map tide-mode-map
"R" #'tide-restart-server
@@ -202,10 +224,7 @@ to tide."
(use-package! js2-refactor
:hook ((js2-mode rjsx-mode) . js2-refactor-mode)
:config
(when (featurep! :editor evil +everywhere)
(let ((js2-refactor-mode-map (evil-get-auxiliary-keymap js2-refactor-mode-map 'normal t t)))
(js2r-add-keybindings-with-prefix (format "%s r" doom-localleader-key))))
:init
(map! :after js2-mode
:map js2-mode-map
:localleader
@@ -224,20 +243,19 @@ to tide."
(:prefix ("u" . "unwrap"))
(:prefix ("v" . "var"))
(:prefix ("w" . "wrap"))
(:prefix ("3" . "ternary")))))
(use-package! eslintd-fix
:commands eslintd-fix
(:prefix ("3" . "ternary"))))
:config
(setq-hook! 'eslintd-fix-mode-hook
flycheck-javascript-eslint-executable eslintd-fix-executable))
(when (featurep! :editor evil +everywhere)
(add-hook 'js2-refactor-mode-hook #'evil-normalize-keymaps)
(let ((js2-refactor-mode-map (evil-get-auxiliary-keymap js2-refactor-mode-map 'normal t t)))
(js2r-add-keybindings-with-prefix (format "%s r" doom-localleader-key)))))
;;;###package skewer-mode
(map! :localleader
(:after js2-mode
:map js2-mode-map
"S" #'+javascript/skewer-this-buffer
:prefix ("s" . "skewer"))
:prefix "s"
(:after skewer-mode
@@ -262,22 +280,29 @@ to tide."
(use-package! npm-mode
:hook ((js-mode typescript-mode) . npm-mode)
:config
(map! (:localleader
:map npm-mode-keymap
(map! :localleader
(:map npm-mode-keymap
"n" npm-mode-command-keymap)
(:after js2-mode
:map js2-mode-map
:localleader
(:prefix ("n" . "npm")))))
:prefix ("n" . "npm"))))
;;
;;; Projects
(def-project-mode! +javascript-npm-mode
:modes '(html-mode css-mode web-mode markdown-mode js-mode typescript-mode)
:modes '(html-mode
css-mode
web-mode
markdown-mode
js-mode
json-mode
typescript-mode
typescript-tsx-mode
solidity-mode)
:when (locate-dominating-file default-directory "package.json")
:add-hooks '(+javascript-add-node-modules-path-h npm-mode))
:add-hooks '(add-node-modules-path npm-mode))
(def-project-mode! +javascript-gulp-mode
:when (locate-dominating-file default-directory "gulpfile.js"))

View File

@@ -2,21 +2,21 @@
;;; lang/javascript/packages.el
;; Major modes
(package! coffee-mode)
(package! js2-mode)
(package! rjsx-mode)
(package! typescript-mode)
(package! coffee-mode :pin "35a41c7d8233eac0b267d9593e67fb8b6235e134")
(package! js2-mode :pin "5049e543b52099e6ea3e9bc915fc023d5a9b2644")
(package! rjsx-mode :pin "0061587a06cdc2579a8d0e90863498d96bf982d8")
(package! typescript-mode :pin "0fc729787007b5111f3584034af0f3ef2389098f")
;; Tools
(package! eslintd-fix)
(package! js2-refactor)
(package! npm-mode)
(package! js2-refactor :pin "d4c40b5fc86d3edd7c6a7d83ac86483ee1cb7a28")
(package! npm-mode :pin "3ee7c0bad5b7a041d4739ef3aaa06a3dc764e5eb")
(package! add-node-modules-path :pin "f31e69ccb681f882aebb806ce6e9478e3ac39708")
;; Eval
(package! nodejs-repl)
(package! skewer-mode)
(package! nodejs-repl :pin "f5ce3d5b7b4e0d06f6e9d4930d9ecc417633586b")
(package! skewer-mode :pin "e5bed351939c92a1f788f78398583c2f83f1bb3c")
;; Programming environment
(package! tide)
(package! tide :pin "13e7af77b6867ffca6eecc5b3b3b5e315518f49c")
(when (featurep! :tools lookup)
(package! xref-js2))
(package! xref-js2 :pin "6f1ed5dae0c2485416196a51f2fa92f32e4b8262"))

View File

@@ -10,7 +10,8 @@
"Run an inferior instance of `julia' inside Emacs."
(interactive)
(if (require 'julia-repl nil t)
(julia-repl)
(prog1 (julia-repl)
(julia-repl-use-emacsclient))
(let ((buffer (get-buffer-create "*Julia*")))
(unless (comint-check-proc "*Julia*")
(apply #'make-comint-in-buffer "Julia" "*Julia*" julia-program julia-arguments))

View File

@@ -5,19 +5,19 @@
:config
(set-repl-handler! 'julia-mode #'+julia/open-repl)
;; Borrow matlab.el's fontification of math operators
;; From <https://ogbe.net/emacsconfig.html>
;; Borrow matlab.el's fontification of math operators. From
;; <https://ogbe.net/emacsconfig.html>
(dolist (mode '(julia-mode ess-julia-mode))
(font-lock-add-keywords
mode
`((,(let ((OR "\\|"))
(concat "\\(" ;; stolen `matlab.el' operators first
(concat "\\(" ; stolen `matlab.el' operators first
"[<>!]=?" OR
"\\.[/*^']" OR
"==" OR
"=>" OR
"\\<xor\\>" OR
"[-+*\\/^&|$]=?" OR ;; this has to come before next (updating operators)
"[-+*\\/^&|$]=?" OR ; this has to come before next (updating operators)
"[-!^&|*+\\/~:]" OR
;; more extra julia operators follow
"[%$]" OR
@@ -30,5 +30,35 @@
1 font-lock-type-face)))))
(after! julia-repl
(add-hook 'julia-repl-hook #'julia-repl-use-emacsclient))
(use-package! julia-repl
:preface (defvar +julia-repl-start-hook nil)
:hook (julia-mode . julia-repl-mode)
:hook (+julia-repl-start . +julia-override-repl-escape-char-h)
:hook (+julia-repl-start . julia-repl-use-emacsclient)
:config
(set-popup-rule! "^\\*julia.*\\*$" :ttl nil)
(when (featurep! :ui workspaces)
(defadvice! +julia--namespace-repl-buffer-to-workspace-a (&optional executable-key suffix)
"Name for a Julia REPL inferior buffer. Uses workspace name for doom emacs"
:override #'julia-repl--inferior-buffer-name
(concat julia-repl-inferior-buffer-name-base ":" (+workspace-current-name))))
(defadvice! +julia--run-start-hook-a (inferior-buffer)
"Run `+julia-repl-start-hook' before displaying the REPL."
:after #'julia-repl--setup-term
(with-current-buffer inferior-buffer
(run-hooks '+julia-repl-start-hook)))
(defun +julia-override-repl-escape-char-h ()
"Use C-c instead of C-x for escaping."
(term-set-escape-char ?\C-c)))
(use-package! lsp-julia
:when (featurep! +lsp)
:after lsp-clients
:preface
(setq lsp-julia-default-environment "~/.julia/environments/v1.0")
(when (featurep! +lsp)
(add-hook 'julia-mode-local-vars-hook #'lsp!)))

View File

@@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; lang/julia/packages.el
(package! julia-mode)
(package! julia-repl)
(package! julia-mode :pin "1c122f1dff")
(package! julia-repl :pin "5fa04de4e7")

View File

@@ -4,15 +4,16 @@
(when (featurep! +lsp)
(add-hook 'kotlin-mode-local-vars-hook #'lsp!))
(set-docsets! 'kotlin-mode "Kotlin")
(set-repl-handler! 'kotlin-mode #'kotlin-repl)
(map! :map kotlin-mode-map
:localleader
:prefix ("b" . "build")
:desc "gradlew assemble" "a" (λ! (+kotlin/run-gradlew "assemble"))
:desc "gradlew build" "b" (λ! (+kotlin/run-gradlew "build"))
:desc "gradlew test" "t" (λ! (+kotlin/run-gradlew "test"))))
:desc "gradlew assemble" "a" (cmd! (+kotlin/run-gradlew "assemble"))
:desc "gradlew build" "b" (cmd! (+kotlin/run-gradlew "build"))
:desc "gradlew test" "t" (cmd! (+kotlin/run-gradlew "test"))))
(use-package! flycheck-kotlin
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:hook (kotlin-mode . flycheck-kotlin-setup))

View File

@@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*-
;;; lang/kotlin/packages.el
(package! kotlin-mode)
(package! kotlin-mode :pin "ab61099682")
(when (featurep! :tools flycheck)
(package! flycheck-kotlin))
(when (featurep! :checkers syntax)
(package! flycheck-kotlin :pin "5104ee9a3f"))

View File

@@ -1,10 +1,5 @@
;;; lang/latex/+ref.el -*- lexical-binding: t; -*-
(when (stringp +latex-bibtex-file)
(setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file))
reftex-default-bibliography bibtex-completion-bibliography))
(use-package! reftex
:hook (LaTeX-mode . reftex-mode)
:config
@@ -23,6 +18,8 @@
(?t . "\\textcite[]{%l}"))
reftex-plug-into-AUCTeX t
reftex-toc-split-windows-fraction 0.3)
(when (featurep! :editor evil)
(add-hook 'reftex-mode-hook #'evil-normalize-keymaps))
(map! :map reftex-mode-map
:localleader
";" 'reftex-toc)

View File

@@ -53,4 +53,4 @@
(define-key! doc-view-mode-map
"ESC" #'delete-window
"q" #'delete-window
"k" (λ! (quit-window) (delete-window))))
"k" (cmd! (quit-window) (delete-window))))

View File

@@ -8,10 +8,15 @@
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#ubuntu][Ubuntu]]
- [[#arch-linux][Arch Linux]]
- [[#macos][macOS]]
- [[#nixos][NixOS]]
- [[#features][Features]]
- [[#customization][Customization]]
- [[#specifying-the-location-of-a-bibtex-file--corresponding-pdfs][Specifying the location of a bibtex file & corresponding PDFs]]
- [[#changing-the-pdfs-viewer][Changing the PDFs viewer]]
- [[#using-cdlatexs-snippets-despite-having-yasnippet][Using cdlatex's snippets despite having yasnippet]]
* Description
Provide a helping hand when working with LaTeX documents.
@@ -23,11 +28,15 @@ Provide a helping hand when working with LaTeX documents.
+ Change PDF viewer to Okular or ~latex-preview-pane~
+ Bibtex editor
+ Autocompletion using ~company-mode~
+ Ivy or Helm for selecting bibliography
+ Compile your .tex code only once using LatexMk
** Module Flags
+ ~+latexmk~ Use LatexMk instead of LaTeX to compile documents.
+ =+latexmk= Use LatexMk instead of LaTeX to compile documents.
+ =+cdlatex= Enable [[https://github.com/cdominik/cdlatex][cdlatex]] for fast math insertion.
+ =+lsp= Start LSP automatically in `tex-mode-hook`. This requires the =:tools
lsp= module. Supported servers are `digestif` and `TexLab`.
+ =+fold= Use TeX-fold (from auctex) to fold LaTeX macros to unicode, and make
folding hook-based and less manual.
** Plugins
+ [[http://www.gnu.org/software/auctex/][auctex]]
@@ -37,22 +46,51 @@ Provide a helping hand when working with LaTeX documents.
+ [[https://github.com/alexeyr/company-auctex][company-auctex]]*
+ [[https://github.com/TheBB/company-reftex][company-reftex]]*
+ [[https://github.com/vspinu/company-math][company-math]]*
+ [[https://github.com/tmalsburg/helm-bibtex][ivy-bibtex]]* or [[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]]*
+ [[https://github.com/cdominik/cdlatex][cdlatex]] (=+cdlatex=)
* TODO Prerequisites
* Prerequisites
You will need ghostscript and a latex compiler. All this is provided by
the =texlive= bundle, available through many OS package managers.
Ghostscript <= 9.27 is [[https://www.gnu.org/software/auctex/manual/preview-latex/No-images-are-displayed-with-gs-9_002e27-and-earlier.html][reported buggy]] and doesn't work with auctex's math
previews. (You can check you ghostscript version with ~gs --version~.) Most
package managers already have newer versions, but if not you might have to build
gs from source.
** Ubuntu
#+BEGIN_SRC sh
apt-get install texlive
#+END_SRC
** Arch Linux
#+BEGIN_SRC sh
pacman -S texlive
#+END_SRC
** TODO macOS
#+BEGIN_SRC sh
brew cask install basictex
# If the above doesn't work, then
brew cask install mactex # WARNING: large 4gb download!
#+END_SRC
#+begin_quote
This has not been verified.
#+end_quote
** NixOS
#+BEGIN_SRC nix
environment.systemPackages = [ pkgs.texlive.combined.scheme-medium ];
#+END_SRC
* TODO Features
* Customization
** Specifying the location of a bibtex file & corresponding PDFs
The reftex and bibtex-completion packages have two variables that allow you to
specify where it should find your bibliography file(s) and their corresponding
PDFs:
Reftex has a variable that allow you to
specify where it should find your bibliography file(s):
#+BEGIN_SRC emacs-lisp
(setq reftex-default-bibliography "/your/bib/file.bib")
;; Optionally specifying a location for the corresponding PDFs
(setq bibtex-completion-library-path (list "/your/bib/pdfs"))
#+END_SRC
** Changing the PDFs viewer
@@ -76,3 +114,17 @@ tool, for instance:
If none of these tools are found, ~latex-preview-pane~ (uses ~DocView~ in Emacs)
is used as a fallback. You can use this exclusively by setting ~+latex-viewers~
to ~nil~.
** Using cdlatex's snippets despite having yasnippet
cdlatex has a snippet insertion capability which is disabled in favor of
yasnippet when using ~:editor snippets~. If you still wanna use it, simply rebind
the ~TAB~ key for cdlatex, which takes care of snippet-related stuff:
#+BEGIN_SRC emacs-lisp
(map! :map cdlatex-mode-map
:i "TAB" #'cdlatex-tab)
#+END_SRC
This would favor yasnippet's expansion and cursor movement over cdlatex's
expansion and movement, but that shouldn't matter if you're not using yasnippet
in latex buffers.

View File

@@ -39,6 +39,18 @@ Continuation lines are indented either twice `LaTeX-indent-level', or
(+ offset indent))
((+ contin indent))))))
;;;###autoload
(defun +latex-fold-last-macro-a (&rest _)
"Advice to auto-fold LaTeX macros after functions that
typically insert macros."
;; A simpler approach would be to just fold the whole line, but if point was
;; inside a macro that would would kick it out. So instead we fold the last
;; macro before point, hoping its the one newly inserted.
(TeX-fold-region (save-excursion
(search-backward "\\" (line-beginning-position) t)
(point))
(1+ (point))))
;;;###autoload
(defun +latex-symbols-company-backend (command &optional arg &rest _ignored)
"A wrapper backend for `company-mode' that either uses

View File

@@ -3,9 +3,6 @@
(defvar +latex-indent-level-item-continuation 4
"Custom indentation level for items in enumeration-type environments")
(defvar +latex-bibtex-file nil
"File AUCTeX (specifically RefTeX) uses to search for citations.")
(defvar +latex-enable-unicode-math nil
"If non-nil, use `company-math-symbols-unicode' backend in LaTeX-mode,
enabling unicode symbols in math regions. This requires the unicode-math latex
@@ -39,6 +36,7 @@ If no viewers are found, `latex-preview-pane' is used.")
;; automatically insert braces after sub/superscript in math mode
TeX-electric-sub-and-superscript t)
(after! tex
;; fontify common latex commands
(load! "+fontification")
@@ -48,12 +46,13 @@ If no viewers are found, `latex-preview-pane' is used.")
(setq-default TeX-master t)
;; set-up chktex
(setcar (cdr (assoc "Check" TeX-command-list)) "chktex -v6 -H %s")
;; tell emacs how to parse tex files
(setq-hook! 'TeX-mode-hook ispell-parser 'tex)
(setq-hook! 'TeX-mode-hook
;; tell emacs how to parse tex files
ispell-parser 'tex
;; Don't auto-fill in math blocks
fill-nobreak-predicate (cons #'texmathp fill-nobreak-predicate))
;; Enable word wrapping
(add-hook 'TeX-mode-hook #'visual-line-mode)
;; Fold TeX macros
(add-hook 'TeX-mode-hook #'TeX-fold-mode)
;; Enable rainbow mode after applying styles to the buffer
(add-hook 'TeX-update-style-hook #'rainbow-delimiters-mode)
;; display output of latex commands in popup
@@ -71,7 +70,49 @@ If no viewers are found, `latex-preview-pane' is used.")
(sp-local-pair modes open nil :actions :rem))
;; And tweak these so that users can decide whether they want use latex
;; quotes or not, via `+latex-enable-plain-double-quotes'
(sp-local-pair modes "``" nil :unless '(:add sp-in-math-p)))))
(sp-local-pair modes "``" nil :unless '(:add sp-in-math-p))))
;; Hook lsp if enabled
(when (featurep! +lsp)
(add-hook! '(tex-mode-local-vars-hook
latex-mode-local-vars-hook)
#'lsp!)))
(use-package! tex-fold
:when (featurep! +fold)
:hook (TeX-mode . TeX-fold-buffer)
:hook (TeX-mode . TeX-fold-mode)
:config
;; Fold after all auctex macro insertions
(advice-add #'TeX-insert-macro :after #'+latex-fold-last-macro-a)
;; Fold after cdlatex macro insertions
(advice-add #'cdlatex-math-symbol :after #'+latex-fold-last-macro-a)
(advice-add #'cdlatex-math-modify :after #'+latex-fold-last-macro-a)
;; Fold after snippets
(when (featurep! :editor snippets)
(add-hook! 'TeX-fold-mode-hook
(defun +latex-fold-snippet-contents-h ()
(add-hook! 'yas-after-exit-snippet-hook :local
(TeX-fold-region yas-snippet-beg yas-snippet-end)))))
(add-hook! 'mixed-pitch-mode-hook
(defun +latex-fold-set-variable-pitch-h ()
"Fix folded things invariably getting fixed pitch when using mixed-pitch.
Math faces should stay fixed by the mixed-pitch blacklist, this is mostly for
\\section etc."
(when mixed-pitch-mode
;; Adding to this list makes mixed-pitch clean the face remaps after us
(add-to-list 'mixed-pitch-fixed-cookie
(face-remap-add-relative
'TeX-fold-folded-face
:family (face-attribute 'variable-pitch :family)
:height (face-attribute 'variable-pitch :height))))))
(map! :map TeX-fold-mode-map
:localleader
:desc "Fold paragraph" "f" #'TeX-fold-paragraph
:desc "Unfold paragraph" "F" #'TeX-fold-clearout-paragraph
:desc "Unfold buffer" "C-f" #'TeX-fold-clearout-buffer))
(after! latex
@@ -116,6 +157,35 @@ If no viewers are found, `latex-preview-pane' is used.")
(lambda () (* (/ 10.0 (preview-document-pt)) preview-scale))))
(use-package! cdlatex
:when (featurep! +cdlatex)
:hook (LaTeX-mode . cdlatex-mode)
:hook (org-mode . org-cdlatex-mode)
:config
;; Use \( ... \) instead of $ ... $
(setq cdlatex-use-dollar-to-ensure-math nil)
;; Disabling keys that have overlapping functionality with other parts of Doom
(map! :map cdlatex-mode-map
;; smartparens takes care of inserting closing delimiters, and if you
;; don't use smartparens you probably won't want these also.
"$" nil
"(" nil
"{" nil
"[" nil
"|" nil
"<" nil
;; TAB is used for cdlatex's snippets and navigation. But we have
;; yasnippet for that.
(:when (featurep! :editor snippets)
"TAB" nil)
;; AUCTeX takes care of auto-inserting {} on _^ if you want, with
;; `TeX-electric-sub-and-superscript'
"^" nil
"_" nil
;; AUCTeX already provides this with `LaTeX-insert-item'
[(control return)] nil))
;; Nicely indent lines that have wrapped when visual line mode is activated
(use-package! adaptive-wrap
:hook (LaTeX-mode . adaptive-wrap-prefix-mode)
@@ -142,6 +212,7 @@ If no viewers are found, `latex-preview-pane' is used.")
(add-to-list '+latex--company-backends #'company-auctex-environments nil #'eq)
(add-to-list '+latex--company-backends #'company-auctex-macros nil #'eq))
(use-package! company-math
:when (featurep! :completion company)
:defer t

View File

@@ -1,23 +1,21 @@
;; -*- no-byte-compile: t; -*-
;;; lang/latex/packages.el
(package! auctex)
(package! adaptive-wrap)
(package! latex-preview-pane)
(package! auctex :pin "6abf890a485b2ff734d8f87f38393f9b8f6bbbf6")
(package! adaptive-wrap :pin "1810c0ee8d827dd502ddeaae5bd759d4811fcbce")
(package! latex-preview-pane :pin "5297668a89996b50b2b62f99cba01cc544dbed2e")
;; Optional module features:
(when (featurep! +latexmk)
(package! auctex-latexmk))
(package! auctex-latexmk :pin "4d353522650d7685acbf1d38f7dbc504f734bd84"))
(when (featurep! +cdlatex)
(package! cdlatex :pin "480387b39f6ddd9cd2a9511ecee064ad8e1dd324"))
;; Features according to other user selected options
(when (featurep! :completion company)
(package! company-auctex)
(package! company-reftex)
(package! company-math))
(when (featurep! :completion ivy)
(package! ivy-bibtex))
(when (featurep! :completion helm)
(package! helm-bibtex))
(package! company-auctex :pin "9400a2ec7459dde8cbf1a5d50dfee4e300ed7e18")
(package! company-reftex :pin "275ef708f08d3bf0eb30632148e5c6184eeaacdb")
(package! company-math :pin "a796053590012e6a15c8b527b521ffc15d137bd0"))

View File

@@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*-
;;; lang/lean/packages.el
(package! lean-mode)
(package! lean-mode :pin "65b55b1711")
(when (featurep! :completion company)
(package! company-lean))
(package! company-lean :pin "65b55b1711"))

View File

@@ -1,27 +1,34 @@
;;; lang/ledger/config.el -*- lexical-binding: t; -*-
;;;###package ledger-mode
(setq ledger-clear-whole-transactions 1)
(use-package! ledger-mode
:defer t
:init
(setq ledger-clear-whole-transactions 1
ledger-mode-should-check-version nil)
(defadvice! +ledger--check-version-a (orig-fn)
"Fail gracefully if ledger binary isn't available."
:around #'ledger-check-version
(if (executable-find ledger-binary-path)
(funcall orig-fn)
(message "Couldn't find '%s' executable" ledger-binary-path)))
:config
(setq ledger-binary-path
(if (executable-find "hledger")
"hledger"
"ledger"))
;; Restore leader key in ledger reports
(map! :after ledger-mode
:map ledger-report-mode-map
"C-c C-c" #'ledger-report-edit-report
"C-c C-r" #'ledger-report-redo
"C-c C-s" #'ledger-report-save
:map ledger-reconcile-mode-map
[tab] #'ledger-reconcile-toggle)
(defadvice! +ledger--check-version-a (orig-fn)
"Fail gracefully if ledger binary isn't available."
:around #'ledger-check-version
(if (executable-find ledger-binary-path)
(funcall orig-fn)
(message "Couldn't find '%s' executable" ledger-binary-path)))
(map! :map ledger-report-mode-map
"C-c C-c" #'ledger-report-edit-report
"C-c C-r" #'ledger-report-redo
"C-c C-s" #'ledger-report-save
:map ledger-reconcile-mode-map
[tab] #'ledger-reconcile-toggle))
(use-package! flycheck-ledger
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after ledger-mode)

View File

@@ -1,10 +1,10 @@
;; -*- no-byte-compile: t; -*-
;;; lang/ledger/packages.el
(package! ledger-mode)
(package! ledger-mode :pin "7d78645479")
(when (featurep! :editor evil)
(package! evil-ledger))
(package! evil-ledger :pin "7a9f9f5d39"))
(when (featurep! :tools flycheck)
(package! flycheck-ledger))
(when (featurep! :checkers syntax)
(package! flycheck-ledger :pin "628e25ba66"))

View File

@@ -1,5 +1,11 @@
;;; lang/lua/config.el -*- lexical-binding: t; -*-
(defvar +lua-lsp-dir (concat doom-etc-dir "lsp/lua-language-server/")
"Absolute path to the directory of sumneko's lua-language-server.
This directory MUST contain the 'main.lua' file and be the in-source build of
lua-language-server.")
;; sp's default rules are obnoxious, so disable them
(provide 'smartparens-lua)
@@ -16,7 +22,23 @@
(set-lookup-handlers! 'lua-mode :documentation 'lua-search-documentation)
(set-electric! 'lua-mode :words '("else" "end"))
(set-repl-handler! 'lua-mode #'+lua/open-repl)
(set-company-backend! 'lua-mode '(company-lua company-yasnippet)))
(set-company-backend! 'lua-mode '(company-lua company-yasnippet))
(set-eglot-client!
'lua-mode
;; The absolute path to lua-language-server binary is necessary because the
;; bundled dependencies aren't found otherwise. The only reason this is a
;; function is to dynamically change when/if lua-lsp-dir variable changed
(list (doom-path lua-lsp-dir
(cond (IS-MAC "bin/macOS")
(IS-LINUX "bin/Linux")
(IS-WINDOWS "bin/Windows"))
"lua-language-server")
"-E" "-e" "LANG=en"
(doom-path lua-lsp-dir "main.lua")))
(when (featurep! +lsp)
(add-hook 'lua-mode-local-vars-hook #'lsp!)))
(use-package! moonscript
@@ -28,7 +50,7 @@
(add-hook! 'moonscript-mode-hook
#'+lua-moonscript-fix-single-quotes-h
#'+lua-moonscript-fontify-interpolation-h)
(when (featurep! :tools flycheck)
(when (featurep! :checkers syntax)
(require 'flycheck-moonscript nil t)))

View File

@@ -1,14 +1,13 @@
;; -*- no-byte-compile: t; -*-
;;; lang/lua/packages.el
(package! lua-mode)
(package! lua-mode :pin "1f596a93b3")
(when (featurep! +moonscript)
(package! moonscript)
(when (featurep! :tools flycheck)
(package! moonscript :pin "56f90471e2")
(when (featurep! :checkers syntax)
(package! flycheck-moonscript
:recipe (:host github :repo "hlissner/emacs-flycheck-moonscript"))))
:recipe (:host github :repo "hlissner/emacs-flycheck-moonscript") :pin "fcb99e5efc")))
(when (featurep! :completion company)
(package! company-lua))
(package! company-lua :pin "29f6819de4"))

View File

@@ -119,15 +119,14 @@ installed through your OS's package manager:
* Features
** Markdown preview
~markdown-preview~ is bound to =SPC m p= (for Evil users) and =C-c l p= (for
non-evil users). This will open a preview of your compiled markdown document in
your browser.
~markdown-preview~ is bound to =<localleader> p=. This will open a preview of
your compiled markdown document in your browser.
Alternatively, you can use ~grip-mode~ through =+grip=.
* Configuration
** Changing how markdown is compiled
When ~markdown-preview~ is invoked (=SPC m b= or =C-c l b=), it consults
When ~markdown-preview~ is invoked (=<localleader> p=) it consults
~markdown-command~. Its default value (~#'+markdown-compile~) will consult
~+markdown-compile-functions~: a list of functions that take three arguments: the
start and end point in the current buffer to use as input, and an output buffer
@@ -138,7 +137,8 @@ By default, the value of ~+markdown-compile-functions~ is:
#+BEGIN_SRC lisp
'(+markdown-compile-marked
+markdown-compile-pandoc
+markdown-compile-markdown)
+markdown-compile-markdown
+markdown-compile-multimarkdown)
#+END_SRC
These functions will attempt to use the marked, pandoc and markdown executables,

View File

@@ -32,7 +32,7 @@ Runs `+markdown-compile-functions' until the first function to return non-nil,
otherwise throws an error."
(or (run-hook-with-args-until-success '+markdown-compile-functions
beg end output-buffer)
(user-error "No markdown program could be found. Install marked, pandoc or markdown.")))
(user-error "No markdown program could be found. Install marked, pandoc, markdown or multimarkdown.")))
;;;###autoload
(defun +markdown-compile-marked (beg end output-buffer)

View File

@@ -27,11 +27,17 @@ capture, the end position, and the output buffer.")
markdown-gfm-additional-languages '("sh")
markdown-make-gfm-checkboxes-buttons t
;; Preview/compilation defaults
;; `+markdown-compile' offers support for many transpilers (see
;; `+markdown-compile-functions'), which it tries until one succeeds.
markdown-command #'+markdown-compile
;; This is set to `nil' by default, which causes a wrong-type-arg error
;; when you use `markdown-open'. These are more sensible defaults.
markdown-open-command
(cond (IS-MAC "open")
(IS-LINUX "xdg-open"))
;; A sensible and simple default preamble for markdown exports that
;; takes after the github asthetic (plus highlightjs syntax coloring).
markdown-content-type "application/xhtml+xml"
markdown-css-paths
'("https://cdn.jsdelivr.net/npm/github-markdown-css/github-markdown.min.css"
@@ -40,13 +46,27 @@ capture, the end position, and the output buffer.")
(concat "<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>"
"<style> body { box-sizing: border-box; max-width: 740px; width: 100%; margin: 40px auto; padding: 0 10px; } </style>"
"<script src='https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js'></script>"
"<script>document.addEventListener('DOMContentLoaded', () => { document.body.classList.add('markdown-body'); document.querySelectorAll('pre[lang] > code').forEach((code) => { code.classList.add(code.parentElement.lang); hljs.highlightBlock(code); }); }); </script>"))
"<script>document.addEventListener('DOMContentLoaded', () => { document.body.classList.add('markdown-body'); document.querySelectorAll('pre[lang] > code').forEach((code) => { code.classList.add(code.parentElement.lang); }); document.querySelectorAll('pre > code').forEach((code) => { hljs.highlightBlock(code); }); });</script>"))
;; A shorter alias for org src blocks than "markdown"
(after! org-src
(add-to-list 'org-src-lang-modes '("md" . markdown)))
:config
(set-flyspell-predicate! '(markdown-mode gfm-mode)
#'+markdown-flyspell-word-p)
(set-lookup-handlers! '(markdown-mode gfm-mode)
:file #'markdown-follow-thing-at-point)
;; `markdown-follow-thing-at-point' may open an external program or a
;; buffer. No good way to tell, so pretend it's async.
:file '(markdown-follow-thing-at-point :async t))
(sp-local-pair '(markdown-mode gfm-mode) "`" "`"
:unless '(:add sp-point-before-word-p sp-point-before-same-p))
;; Don't trigger autofill in code blocks (see `auto-fill-mode')
(setq-hook! 'markdown-mode-hook
fill-nobreak-predicate (cons #'markdown-code-block-at-point-p
fill-nobreak-predicate))
;; HACK Prevent mis-fontification of YAML metadata blocks in `markdown-mode'
;; which occurs when the first line contains a colon in it. See
@@ -57,6 +77,7 @@ capture, the end position, and the output buffer.")
(map! :map markdown-mode-map
:localleader
"'" #'markdown-edit-code-block
"o" #'markdown-open
"p" #'markdown-preview
"e" #'markdown-export

View File

@@ -1,13 +1,14 @@
;; -*- no-byte-compile: t; -*-
;;; lang/markdown/packages.el
(package! markdown-mode)
(package! markdown-toc)
(package! edit-indirect)
(package! markdown-mode :pin "770e3aa7cdfc9d731119b9425e8a7c8ac6dd5f93")
(package! markdown-toc :pin "9565eeaa1d26bc0ab83eb65bd30470888f724044")
(package! edit-indirect :pin "935ded353b9ed3da67bc61abf245c21b58d88864")
(when (featurep! +grip)
(package! grip-mode))
(package! grip-mode :pin "9615c4774727a719d38313a679d70f2a2c6aca68"))
(when (featurep! :editor evil +everywhere)
(package! evil-markdown
:recipe (:host github :repo "Somelauw/evil-markdown")))
:recipe (:host github :repo "Somelauw/evil-markdown")
:pin "064fe9b4767470472356d20bdd08e2f30ebbc9ac"))

View File

@@ -25,6 +25,6 @@ windows."
(use-package! flycheck-nim
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:after nim-mode)

View File

@@ -3,7 +3,7 @@
;;; requires nim nimsuggest nimble
(package! nim-mode)
(package! nim-mode :pin "16a245e497")
(when (featurep! :tools flycheck)
(package! flycheck-nim))
(when (featurep! :checkers syntax)
(package! flycheck-nim :pin "ddfade5100"))

View File

@@ -39,3 +39,25 @@
((user-error "No search engine is enabled. Enable helm or ivy!")))
;; Tell lookup module to let us handle things from here
'deferred)
;;;###autoload
(defun +nix-shell-init-mode ()
"Resolve a (cached-)?nix-shell shebang to the correct major mode."
(save-excursion
(goto-char (point-min))
(save-match-data
(if (not (re-search-forward "#! *\\(?:cached-\\)?nix-shell +-i +\\([^ \n]+\\)" 256 t))
(message "Couldn't determine mode for this script")
(let* ((interp (match-string 1))
(mode
(assoc-default
interp
(mapcar (lambda (e)
(cons (format "\\`%s\\'" (car e))
(cdr e)))
interpreter-mode-alist)
#'string-match-p)))
(when mode
(prog1 (set-auto-mode-0 mode)
(when (eq major-mode 'sh-mode)
(sh-set-shell interp)))))))))

View File

@@ -1,6 +1,7 @@
;;; lang/nix/config.el -*- lexical-binding: t; -*-
(use-package! nix-mode
:interpreter ("\\(?:cached-\\)?nix-shell" . +nix-shell-init-mode)
:mode "\\.nix\\'"
:config
(set-company-backend! 'nix-mode 'company-nixos-options)

View File

@@ -1,11 +1,11 @@
;; -*- no-byte-compile: t; -*-
;;; lang/nix/packages.el
(package! nix-mode)
(package! nix-update)
(package! nix-mode :pin "5b5961780f3b1c1b62453d2087f775298980f10d")
(package! nix-update :pin "fc6c39c2da3fcfa62f4796816c084a6389c8b6e7")
(when (featurep! :completion company)
(package! company-nixos-options))
(package! company-nixos-options :pin "977b9a505ffc8b33b70ec7742f90e469b3168297"))
(when (featurep! :completion helm)
(package! helm-nixos-options))
(package! helm-nixos-options :pin "977b9a505ffc8b33b70ec7742f90e469b3168297"))

View File

@@ -55,10 +55,10 @@ opam install merlin utop ocp-indent dune ocamlformat
* Configuration
+ If =:completion company= is enabled then autocomplete is provided by =merlin=
+ When =:tools flycheck= is enabled then =flycheck-ocaml= is activated to do
+ When =:checkers syntax= is enabled then =flycheck-ocaml= is activated to do
on-the-fly syntax/type checking via =merlin=, otherwise this is only done when
the file is saved.
+ Spell checking is activated in comments if =:tools flyspell= is active
+ Spell checking is activated in comments if =:checkers spell= is active
+ A REPL is provided if =utop= is installed and =:tools eval= is active
+ If =:editor format= is enabled, the =ocamlformat= executable is available and
there is an =.ocamlformat= file present then =format-all-buffer= is bound to
@@ -69,8 +69,8 @@ opam install merlin utop ocp-indent dune ocamlformat
+ If =:emacs imenu= is enabled then top level symbols (modules, type, functions,
etc.) can be looked up using =SPC / i=
Run =bin/doom refresh= to install all packages and =make doctor= to diagnose
missing tools.
Run =doom sync= to install all packages and =doom doctor= to diagnose missing
tools.
* Appendix
** Commands

View File

@@ -6,4 +6,6 @@
(interactive)
(comment-indent-new-line)
(when (eq (char-before) ?*)
(just-one-space)))
(just-one-space))
(unless (eq (char-after) 32)
(save-excursion (insert " "))))

View File

@@ -1,5 +1,8 @@
;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
;;
;;; Packages
(when (featurep! +lsp)
(add-hook! '(tuareg-mode-local-vars-hook reason-mode-local-vars-hook)
#'lsp!))
@@ -18,10 +21,9 @@
(tuareg-opam-update-env (tuareg-opam-current-compiler))
;; Spell-check comments
(when (featurep! :tools flyspell)
(when (featurep! :checkers spell)
(add-hook 'tuareg-mode-local-vars-hook #'flyspell-prog-mode))
;; Ensure asterixes in block comments have at least one space of indentation
(setq-hook! 'tuareg-mode-hook
comment-line-break-function #'+ocaml/comment-indent-new-line)
@@ -31,7 +33,7 @@
(use-package! utop
:when (featurep! :tools eval)
:hook (tuareg-mode . +ocaml-init-utop-h)
:hook (tuareg-mode-local-vars . +ocaml-init-utop-h)
:init
(set-repl-handler! 'tuareg-mode #'utop)
(set-eval-handler! 'tuareg-mode #'utop-eval-region)
@@ -44,7 +46,7 @@
(use-package! merlin
:unless (featurep! +lsp)
:hook (tuareg-mode . +ocaml-init-merlin-h)
:hook (tuareg-mode-local-vars . +ocaml-init-merlin-h)
:init
(defun +ocaml-init-merlin-h ()
"Activate `merlin-mode' if the ocamlmerlin executable exists."
@@ -53,7 +55,7 @@
(after! tuareg
(set-company-backend! 'tuareg-mode 'merlin-company-backend)
(set-lookup-handlers! 'tuareg-mode
(set-lookup-handlers! 'tuareg-mode :async t
:definition #'merlin-locate
:references #'merlin-occurrences
:documentation #'merlin-document))
@@ -65,7 +67,7 @@
"t" #'merlin-type-enclosing)
(use-package! flycheck-ocaml
:when (featurep! :tools flycheck)
:when (featurep! :checkers syntax)
:hook (merlin-mode . +ocaml-init-flycheck-h)
:config
(defun +ocaml-init-flycheck-h ()
@@ -93,7 +95,7 @@
(use-package! ocp-indent
;; must be careful to always defer this, it has autoloads that adds hooks
;; which we do not want if the executable can't be found
:hook (tuareg-mode . +ocaml-init-ocp-indent-h)
:hook (tuareg-mode-local-vars . +ocaml-init-ocp-indent-h)
:config
(defun +ocaml-init-ocp-indent-h ()
"Run `ocp-setup-indent', so long as the ocp-indent binary exists."
@@ -104,7 +106,7 @@
(use-package! ocamlformat
:when (featurep! :editor format)
:commands ocamlformat
:hook (tuareg-mode . +ocaml-init-ocamlformat-h)
:hook (tuareg-mode-local-vars . +ocaml-init-ocamlformat-h)
:config
(set-formatter! 'ocamlformat #'ocamlformat
:modes '(caml-mode tuareg-mode))
@@ -113,4 +115,9 @@
(setq +format-with 'ocp-indent)
(when (and (executable-find "ocamlformat")
(locate-dominating-file default-directory ".ocamlformat"))
(let ((ext (file-name-extension buffer-file-name t)))
(cond ((equal ext ".eliom")
(setq-local ocamlformat-file-kind 'implementation))
((equal ext ".eliomi")
(setq-local ocamlformat-file-kind 'interface))))
(setq +format-with 'ocamlformat))))

View File

@@ -1,25 +1,25 @@
;; -*- no-byte-compile: t; -*-
;;; lang/ocaml/packages.el
(package! tuareg)
(package! tuareg :pin "c12061eb80")
(unless (featurep! +lsp)
(package! merlin)
(package! merlin-eldoc)
(when (featurep! :tools flycheck)
(package! flycheck-ocaml)))
(package! merlin :pin "37e38e44f5")
(package! merlin-eldoc :pin "db7fab1edd")
(when (featurep! :checkers syntax)
(package! flycheck-ocaml :pin "8707a7bf54")))
(package! ocp-indent)
(package! ocp-indent :pin "9e26c0a269")
(when (featurep! :tools eval)
(package! utop))
(package! utop :pin "30c77ce4d7"))
(when (featurep! :editor format)
;; by default quelpa generated a version 0pre0.20180929.192844, which got
;; parsed into (0 -1 0 ...), which when compared with version nil (0) in
;; package-installed-p always yielded false
(package! ocamlformat :recipe
(:host github :repo "ocaml-ppx/ocamlformat" :files ("emacs/*.el"))))
(:host github :repo "ocaml-ppx/ocamlformat" :files ("emacs/*.el")) :pin "5282e047bb"))
(package! dune :recipe
(:host github :repo "ocaml/dune" :files ("editor-integration/emacs/*.el")))
(:host github :repo "ocaml/dune" :files ("editor-integration/emacs/*.el")) :pin "1944d0fb52")

View File

@@ -18,15 +18,16 @@
- [[#built-in-custom-link-types][Built-in custom link types]]
- [[#configuration][Configuration]]
- [[#changing-org-directory][Changing ~org-directory~]]
- [[#changing-org-noter-notes-search-path][Changing ~org-noter-notes-search-path~]]
* Description
This module adds org-mode support to Doom Emacs, along with a number of
adjustments, extensions and reasonable defaults to make it more performant and
intuitive out of the box:
+ A custom, centralized attachment and export system that stores files in one
place, rather than in the same directory as the input file(s) (only applies to
attachments/exporting from files in/under =org-directory=).
+ A custom, centralized attachment system that stores files in one place, rather
than in the same directory as the input file(s) (only applies to attachments
from files in/under =org-directory=).
+ Executable code blocks with support for a variety of languages and tools
(depending on what :lang modules are enabled).
+ Supports an external org-capture workflow through the =bin/org-capture= shell
@@ -35,8 +36,8 @@ intuitive out of the box:
org files to reveal.js slideshows.
+ Drag-and-drop support for images (with inline preview) and media files (drops
a file icon and a short link) (requires =+dragndrop= flag).
+ Integration with pandoc, ipython, reveal.js, beamer, and others (requires
flags).
+ Integration with pandoc, ipython, jupyter, reveal.js, beamer, and others
(requires flags).
+ Export-to-clipboard functionality, for copying text into formatted html,
markdown or rich text to the clipboard (see ~+org/export-to-clipboard~ and
~+org/export-to-clipboard-as-rich-text~).
@@ -52,27 +53,35 @@ https://www.mfoot.com/blog/2015/11/22/literate-emacs-configuration-with-org-mode
#+end_quote
** Module Flags
+ =+brain= Enables [[https://github.com/Kungsgeten/org-brain][org-brain]] integration.
+ =+dragndrop= Enables drag-and-drop support for images and files; inserts
inline previews for images and an icon+link for other media types.
+ =+gnuplot= Installs gnuplot & gnuplot-mode, which enables rendering images
from gnuplot src blocks or plotting tables with ~org-plot/gnuplot~ (bound to
=SPC m b p=, by default).
+ =+ipython= Enables ipython+babel integration.
+ =+hugo= Enables integration with [[https://gohugo.io][hugo]] to export from Emacs well-formed
([[https://github.com/russross/blackfriday][blackfriday]]) markdown.
+ =+ipython= (**DEPRECATED**) Enables ipython integration for babel.
+ =+journal= Enables [[https://github.com/bastibe/org-journal][org-journal]] integration.
+ =+jupyter= Enables Jupyter integration for babel.
+ =+noter= Enables org-noter integration. Keeps notes in sync with a document.
Requires [[https://github.com/politza/pdf-tools][pdf-tools]] (=:tools pdf=) or [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Document-View.html][DocView]] or [[https://github.com/wasamasa/nov.el][nov.el]] to be enabled.
+ =+pandoc= Enables pandoc integration into the Org exporter.
+ =+pomodoro= Enables a pomodoro timer for clocking time on tasks.
+ =+present= Enables integration with reveal.js, beamer and org-tree-slide, so
Emacs can be used for presentations.
+ =+hugo= Enables integration with [[https://gohugo.io][hugo]] to export from Emacs well-formed
([[https://github.com/russross/blackfriday][blackfriday]]) markdown.
+ =+roam= Enables org-roam integration.
** Plugins
+ [[https://orgmode.org/][org-plus-contrib]]
+ [[https://github.com/sabof/org-bullets][org-bullets]]
+ [[https://github.com/TobiasZawada/org-yt][org-yt]]
+ [[https://github.com/snosov1/toc-org][toc-org]]
+ [[https://github.com/jkitchin/ox-clip][ox-clip]]
+ [[https://github.com/hniksic/emacs-htmlize][htmlize]]
+ [[https://github.com/astahlman/ob-async][ob-async]]
+ [[https://github.com/integral-dw/org-superstar-mode][org-superstar]]
+ [[https://github.com/rexim/org-cliplink][org-cliplink]]
+ [[https://github.com/magit/orgit][orgit]]
+ [[https://orgmode.org/][org-plus-contrib]]
+ [[https://github.com/TobiasZawada/org-yt][org-yt]]
+ [[https://github.com/jkitchin/ox-clip][ox-clip]]
+ [[https://github.com/snosov1/toc-org][toc-org]]
+ =:lang crystal=
+ [[https://github.com/brantou/ob-crystal][ob-crystal]]
+ =:lang go=
@@ -83,19 +92,27 @@ https://www.mfoot.com/blog/2015/11/22/literate-emacs-configuration-with-org-mode
+ [[https://github.com/DEADB17/ob-racket][ob-racket]]
+ =:lang rest=
+ [[https://github.com/alf/ob-restclient.el][ob-restclient]]
+ =:lang rst=
+ [[https://github.com/msnoigrs/ox-rst][ox-rst]]
+ =:lang rust=
+ [[https://github.com/micanzhang/ob-rust][ob-rust]]
+ =:lang scala=
+ [[https://github.com/zwild/ob-ammonite][ob-ammonite]]
+ =:editor evil=
+ [[https://github.com/Somelauw/evil-org-mode][evil-org]]
+ =:tools pdf=
+ [[https://github.com/markus1189/org-pdfview/tree/09ef4bf8ff8319c1ac78046c7e6b89f6a0beb82c][org-pdfview]]
+ [[https://github.com/fuxialexander/org-pdftools][org-pdftools]]
+ =+dragndrop=
+ [[https://github.com/abo-abo/org-download][org-download]]
+ =+gnuplot=
+ [[https://github.com/mkmcc/gnuplot-mode][gnuplot]]
+ [[https://github.com/bruceravel/gnuplot-mode][gnuplot-mode]]
+ =+hugo=
+ [[https://github.com/kaushalmodi/ox-hugo][ox-hugo]]
+ =+ipython=
+ [[https://github.com/gregsexton/ob-ipython][ob-ipython]]
+ =+jupyter=
+ [[https://github.com/dzop/emacs-jupyter][jupyter]]
+ =+pandoc=
+ [[https://github.com/kawabata/ox-pandoc][ox-pandoc]]
+ =+pomodoro=
@@ -104,8 +121,12 @@ https://www.mfoot.com/blog/2015/11/22/literate-emacs-configuration-with-org-mode
+ [[https://github.com/anler/centered-window-mode][centered-window]]
+ [[https://github.com/takaxp/org-tree-slide][org-tree-slide]]
+ [[https://gitlab.com/oer/org-re-reveal][org-re-reveal]]
+ =+hugo=
+ [[https://github.com/kaushalmodi/ox-hugo][ox-hugo]]
+ =+roam=
+ [[https://github.com/org-roam/org-roam][org-roam]]
+ [[https://github.com/org-roam/company-org-roam][company-org-roam]]
+ =+noter=
+ [[https://github.com/weirdNox/org-noter][org-noter]]
** Hacks
+ The window is recentered when following links.
@@ -197,6 +218,7 @@ They are (with examples):
+ ~google:search terms~
+ ~org:todo.org~ (={org-directory}/%s=)
+ ~wolfram:sin(x^3)~
+ ~wikipedia:Emacs~
+ ~youtube:P196hEuA_Xc~ (link only)
+ ~yt:P196hEuA_Xc~ (like =youtube=, but includes an inline preview of the video)
@@ -208,3 +230,10 @@ To modify ~org-directory~ it must be set /before/ =org= has loaded:
;; ~/.doom.d/config.el
(setq org-directory "~/new/org/location/")
#+END_SRC
** Changing ~org-noter-notes-search-path~
To modify ~org-noter-notes-search-path~ set:
#+BEGIN_SRC emacs-lisp
;; ~/.doom.d/config.el
(setq org-noter-notes-search-path '("~/notes/path/"))
#+END_SRC

View File

@@ -1,12 +0,0 @@
;;; lang/org/autoload/contrib-dragndrop.el -*- lexical-binding: t; -*-
;;;###if (featurep! +dragndrop)
;;;###autoload
(defun +org-dragndrop-download-dnd-fn (uri action)
"Handle file links and base64 data uris."
(if (eq major-mode 'org-mode)
(+org-attach/uri uri)
(let ((dnd-protocol-alist
(rassq-delete-all '+org-attach-download-dnd
(copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action uri))))

View File

@@ -1,6 +1,9 @@
;;; lang/org/autoload/contrib-present.el -*- lexical-binding: t; -*-
;;;###if (featurep! +present)
(defvar +org-present--overlays nil)
;;
;;; Helpers
@@ -9,10 +12,13 @@
if (buffer-local-value 'org-tree-slide-mode buf)
return t)
(org-tree-slide-mode -1)
(remove-hook 'kill-buffer-hook #'+org-present--cleanup-org-tree-slides-mode)))
(remove-hook 'kill-buffer-hook #'+org-present--cleanup-org-tree-slides-mode
'local)))
(defun +org-present--make-invisible (beg end)
(let ((overlay (make-overlay beg end)))
(unless (assq '+org-present buffer-invisibility-spec)
(add-to-invisibility-spec '(+org-present)))
(let ((overlay (make-overlay beg (1+ end))))
(push overlay +org-present--overlays)
(overlay-put overlay 'invisible '+org-present)))
@@ -21,19 +27,21 @@
;;; Hooks
;;;###autoload
(defun +org-present-add-overlays-h ()
"TODO"
(add-to-invisibility-spec '(+org-present))
(defun +org-present-hide-blocks-h ()
"Hide org #+ constructs."
(save-excursion
;; hide org-mode options starting with #+
(goto-char (point-min))
(while (re-search-forward "^[[:space:]]*\\(#\\+\\)\\(\\(?:BEGIN\\|END\\|ATTR\\)[^[:space:]]+\\).*" nil t)
(+org-present--make-invisible
(match-beginning 1)
(match-end 0)))
;; hide stars in headings
(match-end 0)))))
;;;###autoload
(defun +org-present-hide-leading-stars-h ()
"Hide leading stars in headings."
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^\\(\\*+\\s-\\)" nil t)
(while (re-search-forward "^\\(\\*+\\)" nil t)
(+org-present--make-invisible (match-beginning 1) (match-end 1)))))
;;;###autoload
@@ -55,43 +63,35 @@
(defvar cwm-left-fringe-ratio)
(defvar cwm-centered-window-width)
;;;###autoload
(defun +org-present-init-org-tree-window-h ()
(defun +org-present-prettify-slide-h ()
"TODO"
"Set up the org window for presentation."
(doom/window-maximize-buffer)
(let ((arg (if org-tree-slide-mode +1 -1)))
(when (fboundp 'centered-window-mode)
(let ((cwm-use-vertical-padding t)
(cwm-frame-internal-border 110)
(cwm-left-fringe-ratio -10)
(cwm-centered-window-width 240))
(centered-window-mode arg)))
(window-divider-mode (* arg -1))
(setq-local cwm-use-vertical-padding t)
(setq-local cwm-frame-internal-border 100)
(setq-local cwm-left-fringe-ratio -10)
(setq-local cwm-centered-window-width 300)
(centered-window-mode arg))
(hide-mode-line-mode arg)
(+org-pretty-mode arg)
(cond (org-tree-slide-mode
(org-indent-mode -1)
(set-window-fringes nil 0 0)
(when (bound-and-true-p solaire-mode)
(solaire-mode -1)
(fringe-mode 0))
(when (bound-and-true-p flyspell-mode)
(flyspell-mode -1))
(add-hook 'kill-buffer-hook #'+org-present--cleanup-org-tree-slides-mode
nil 'local)
(text-scale-set +org-present-text-scale)
(ignore-errors (org-latex-preview '(4)))
(set-face-attribute 'org-level-2 nil :height 1.4))
(ignore-errors (org-latex-preview '(4))))
(t
(org-indent-mode +1)
(text-scale-set 0)
(set-window-fringes nil fringe-mode fringe-mode)
(org-clear-latex-preview)
(set-face-attribute 'org-level-2 nil :height 1.0)
(+org-present-remove-overlays-h)
(org-remove-inline-images)))))
;;
;;; Commands
(defvar +org-present--overlays nil)
;;;###autoload
(defun +org-present/start ()
"TODO"
(interactive)
(unless (derived-mode-p 'org-mode)
(error "Not in an org buffer"))
(call-interactively #'org-tree-slide-mode)
(add-hook 'kill-buffer-hook #'+org-present--cleanup-org-tree-slides-mode))
(org-remove-inline-images)
(org-mode)))
(redraw-display)))

View File

@@ -1,30 +1,5 @@
;;; lang/org/autoload/org-attach.el -*- lexical-binding: t; -*-
;;
(defvar +org-attachments nil
"A list of all indexed attachments in `org-directory'.")
(defvar +org-attachments-files nil
"A list of all attachments in `org-attach-id-dir'.")
(defun +org-list-attachments (&optional beg end)
"Return a list of all attachment file names in the current buffer between BEG
and END (defaults to `point-min' and `point-max')."
(let ((case-fold-search t)
attachments)
(or end (setq end (point-max)))
(org-save-outline-visibility nil
(org-with-wide-buffer
(goto-char (or beg (point-min)))
(while (search-forward "[[attach:" end t)
(let* ((context (save-match-data (org-element-context)))
(link (expand-file-name (org-link-unescape (org-element-property :path context))
org-attach-id-dir)))
(when (and (equal "file" (org-element-property :type context))
(file-in-directory-p link org-attach-id-dir))
(push (file-name-nondirectory link) attachments))))))
(cl-delete-duplicates attachments :test #'string=)))
;;;###autoload
(defun +org-attach-icon-for (path)
(char-to-string
@@ -39,63 +14,46 @@ and END (defaults to `point-min' and `point-max')."
((or "zip" "gz" "tar" "7z" "rar") ?)
(_ ?))))
;;;###autoload
(defun +org/open-gallery-from-attachments ()
"TODO"
(interactive)
(require 'org-attach)
(if-let (dir (org-attach-dir))
(pop-to-buffer
;; Rather than opening dired *and* image-dired windows, suppress them
;; both and open only the image-dired window.
(save-window-excursion
(image-dired dir)
(current-buffer)))
(user-error "No attachments for this node")))
;;;###autoload
(defun +org-attach/sync (arg)
"Reindex all attachments in `org-directory' and delete orphaned attachments in
`org-attach-id-dir'. If ARG (universal arg), conduct a dry run."
(declare (interactive-only t))
(interactive "P")
(message "Reloading")
(setq +org-attachments-files (directory-files org-attach-id-dir nil "^[^.]" t))
(with-temp-buffer
(delay-mode-hooks (org-mode))
(dolist (org-file (directory-files-recursively org-directory "\\.org$"))
(insert-file-contents-literally org-file))
(setq +org-attachments (+org-list-attachments)))
;; clean up
(let ((deleted 0))
(dolist (file (cl-set-difference +org-attachments-files +org-attachments
:test #'string=))
(message "Deleting orphaned attachment: %s" file)
(cl-incf deleted)
(unless arg
(delete-file (expand-file-name file org-attach-id-dir))))
(message "Buffer's attachments synced (%d deleted)" deleted)))
;;;###autoload
(defun +org-attach/find-file ()
(defun +org/find-file-in-attachments ()
"Open a file from `org-attach-id-dir'."
(interactive)
(doom-project-browse org-attach-id-dir))
;;;###autoload
(defun +org-attach/file (path)
"Copies the file at PATH to `+org-attach-dir' and places an org link to it at
the cursor."
(interactive "fAttach file: ")
(+org-attach/uri path))
;;;###autoload
(defun +org-attach/uri (uri)
"Downloads the file at URL and place an org link to it at the cursor."
(defun +org/attach-file-and-insert-link (path)
"Downloads the file at PATH and insert an org link at point.
PATH (a string) can be an url, a local file path, or a base64 encoded datauri."
(interactive "sUri/file: ")
(unless (eq major-mode 'org-mode)
(user-error "Not in an org buffer"))
(require 'org-download)
(let ((raw-uri (url-unhex-string uri)))
(condition-case ex
(cond ((string-match-p "^data:image/png;base64," uri)
(org-download-dnd-base64 uri nil))
(condition-case-unless-debug e
(let ((raw-uri (url-unhex-string path)))
(cond ((string-match-p "^data:image/png;base64," path)
(org-download-dnd-base64 path nil))
((image-type-from-file-name raw-uri)
(org-download-image raw-uri))
(t
(let ((new-path (expand-file-name (org-download--fullname raw-uri))))
((let ((new-path (expand-file-name (org-download--fullname raw-uri))))
;; Download the file
(if (string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") uri)
(if (string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") path)
(url-copy-file raw-uri new-path)
(copy-file uri new-path))
(copy-file path new-path))
;; insert the link
(org-download-insert-link raw-uri new-path))))
(error
(user-error "Failed to attach file: %s" (error-message-string ex))))))
(org-download-insert-link raw-uri new-path)))))
(error
(user-error "Failed to attach file: %s" (error-message-string e)))))

View File

@@ -3,6 +3,7 @@
;;;###autoload
(defun +org-headline-avy ()
"TODO"
(require 'avy)
(save-excursion
(when-let* ((org-reverse-note-order t)
(pos (avy-with avy-goto-line (avy-jump (rx bol (1+ "*") (1+ blank))))))

View File

@@ -6,26 +6,33 @@
;;
;;; External frame
(defvar +org-capture-fn #'org-capture
"Command to use to initiate org-capture.")
;;;###autoload
(defvar +org-capture-frame-parameters
`((name . "org-capture")
`((name . "doom-capture")
(width . 70)
(height . 25)
(transient . t)
,(if IS-LINUX '(display . ":0")))
,(when (and IS-LINUX (not (getenv "DISPLAY")))
`(display . ":0"))
,(if IS-MAC '(menu-bar-lines . 1)))
"TODO")
;;;###autoload
(defun +org-capture-cleanup-frame-h ()
"Closes the org-capture frame once done adding an entry."
(when (+org-capture-frame-p)
(when (and (+org-capture-frame-p)
(not org-capture-is-refiling))
(delete-frame nil t)))
;;;###autoload
(defun +org-capture-frame-p (&rest _)
"Return t if the current frame is an org-capture frame opened by
`+org-capture/open-frame'."
(and (equal "org-capture" (frame-parameter nil 'name))
(and (equal (alist-get 'name +org-capture-frame-parameters)
(frame-parameter nil 'name))
(frame-parameter nil 'transient)))
;;;###autoload
@@ -45,23 +52,13 @@ you're done. This can be called from an external shell script."
(with-selected-frame frame
(require 'org-capture)
(condition-case ex
(cl-letf (((symbol-function #'pop-to-buffer)
(symbol-function #'switch-to-buffer)))
(letf! ((#'pop-to-buffer #'switch-to-buffer))
(switch-to-buffer (doom-fallback-buffer))
(let ((org-capture-initial initial-input)
org-capture-entry)
(when (and key (not (string-empty-p key)))
(setq org-capture-entry (org-capture-select-template key)))
(if (or org-capture-entry
(not (fboundp 'counsel-org-capture)))
(org-capture)
(unwind-protect
(counsel-org-capture)
(if-let (buf (cl-find-if (doom-partial #'buffer-local-value 'org-capture-mode)
(buffer-list)))
(with-current-buffer buf
(add-hook 'kill-buffer-hook #'+org-capture-cleanup-frame-h nil t))
(delete-frame frame))))))
(funcall +org-capture-fn)))
('error
(message "org-capture: %s" (error-message-string ex))
(delete-frame frame))))))
@@ -148,16 +145,16 @@ project."
(defun +org-capture-central-project-todo-file ()
"TODO"
(+org--capture-central-file
+org-capture-todo-file (projectile-project-name)))
+org-capture-projects-file (projectile-project-name)))
;;;###autoload
(defun +org-capture-central-project-notes-file ()
"TODO"
(+org--capture-central-file
+org-capture-notes-file (projectile-project-name)))
+org-capture-projects-file (projectile-project-name)))
;;;###autoload
(defun +org-capture-central-project-changelog-file ()
"TODO"
(+org--capture-central-file
+org-capture-changelog-file (projectile-project-name)))
+org-capture-projects-file (projectile-project-name)))

View File

@@ -1,27 +1,79 @@
;;; lang/org/autoload/org-link.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +org-link-read-file (key dir)
(let ((file (read-file-name (format "%s: " (capitalize key)) dir)))
(format "%s:%s"
key
(file-relative-name file dir))))
(defun +org--relative-path (path root)
(if (and buffer-file-name (file-in-directory-p buffer-file-name root))
(file-relative-name path)
path))
(defun +org--read-link-path (key dir &optional fn)
(let ((file (funcall (or fn #'read-file-name) (format "%s: " (capitalize key)) dir)))
(format "%s:%s" key (file-relative-name file dir))))
;;;###autoload
(defun +org-link-read-directory (key dir)
(let ((file (read-directory-name (format "%s: " (capitalize key)) dir)))
(format "%s:%s"
key
(file-relative-name file dir))))
(defun +org-define-basic-link (key dir-var &rest plist)
"Define a link with some basic completion & fontification.
KEY is the name of the link type. DIR-VAR is the directory variable to resolve
links relative to. PLIST is passed to `org-link-set-parameters' verbatim.
Links defined with this will be rendered in the `error' face if the file doesn't
exist, and `org-link' otherwise."
(declare (indent 2))
(let ((requires (plist-get plist :requires))
(dir-fn (if (functionp dir-var)
dir-var
(lambda () (symbol-value dir-var)))))
(apply #'org-link-set-parameters
key
:complete (lambda ()
(if requires (mapc #'require (doom-enlist requires)))
(+org--relative-path (+org--read-link-path key (funcall dir-fn))
(funcall dir-fn)))
:follow (lambda (link)
(org-link-open-as-file (expand-file-name link (funcall dir-fn)) nil))
:face (lambda (link)
(let* ((path (expand-file-name link (funcall dir-fn)))
(option-index (string-match-p "::\\(.*\\)\\'" path))
(file-name (substring path 0 option-index)))
(if (file-exists-p file-name)
'org-link
'error)))
(doom-plist-delete plist :requires))))
;;
;;; Image data functions (for custom inline images)
;;;###autoload
(defun +org-inline-data-image (_protocol link _description)
(defun +org-image-file-data-fn (protocol link _description)
"Intepret LINK as an image file path and return its data."
(setq
link (expand-file-name
link (pcase protocol
("download"
(or (if (require 'org-download nil t) org-download-image-dir)
(if (require 'org-attach) org-attach-id-dir)
default-directory))
("attachment"
(require 'org-attach)
org-attach-id-dir)
(_ default-directory))))
(when (and (file-exists-p link)
(image-type-from-file-name link))
(with-temp-buffer
(set-buffer-multibyte nil)
(setq buffer-file-coding-system 'binary)
(insert-file-contents-literally link)
(buffer-substring-no-properties (point-min) (point-max)))))
;;;###autoload
(defun +org-inline-image-data-fn (_protocol link _description)
"Interpret LINK as base64-encoded image data."
(base64-decode-string link))
;;;###autoload
(defun +org-image-link (protocol link _description)
"Interpret LINK as base64-encoded image data."
(defun +org-http-image-data-fn (protocol link _description)
"Interpret LINK as an URL to an image file."
(when (image-type-from-file-name link)
(if-let* ((buf (url-retrieve-synchronously (concat protocol ":" link))))
(with-current-buffer buf

View File

@@ -3,15 +3,27 @@
;; REVIEW These are all proof-of-concept. Refactor me!
;;;###autoload
(defun +org/refile-to-current-file (arg)
(defun +org/refile-to-current-file (arg &optional file)
"TODO"
(interactive "P")
(let ((org-refile-targets `((nil :maxlevel . 10)))
(let ((org-refile-targets `((,file :maxlevel . 10)))
(org-refile-use-outline-path nil)
(org-refile-keep arg)
current-prefix-arg)
(call-interactively #'org-refile)))
;;;###autoload
(defun +org/refile-to-file (arg file)
"Refile current heading to a particular org file."
(interactive
(list current-prefix-arg
(read-file-name "Select file to refile to: "
default-directory
buffer-file-name
t nil
(lambda (f) (string-match-p "\\.org$" f)))))
(+org/refile-to-current-file arg file))
;;;###autoload
(defun +org/refile-to-other-window (arg)
"TODO"

View File

@@ -46,11 +46,10 @@ re-align the table if necessary. (Necessary because org-mode has a
;;;###autoload
(defun +org-realign-table-maybe-h ()
"Auto-align table under cursor and re-calculate formulas."
"Auto-align table under cursor."
(when (and (org-at-table-p) org-table-may-need-update)
(let ((pt (point))
(inhibit-message t))
(org-table-recalculate)
(if org-table-may-need-update (org-table-align))
(goto-char pt))))

Some files were not shown because too many files have changed in this diff Show More