Skip to content

frgomes/.emacs.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Emacs configuration

Emacs is a programmable text editor.

This video demonstrates some of Emacs’ powerful editing capabilities

screenshot.png

Installation

Just clone this repository onto your $HOME directory and start Emacs, like this:

#!/bin/bash
cd $HOME
if [ -d .emacs.d ] ;then mv .emacs.d .emacs.d.SAVE ;fi
git clone http://github.com/frgomes/.emacs.d
emacs &

That’s it!

If everything goes according to plan, Emacs will download a lot of stuff from the Internet, compile everything and configure itself without presenting any error. Then you type C-x t t (Ctrl-X t t) and a sidebar will be presented on the left side, which allows you to manage projects.

Features

Support for programming languages

Emacs has builtin support for Language Server Protocol. However, the range of languages which work out of the box is limited and, for this reason …

We provide shell scripts in a separate project which helps installing language servers.

More information about Language Server Protocol:

The current support matrix is shown below, where:

  • builtin - LSP client natively supported by Emacs; it may require external additional software for full support.
  • pending - LSP server is known to exist and an issue was raised for creation of an installation script.
  • missing - LSP server is known to exist but the author is not committed on implementing an installation script for it.
  • unknown - The author does not know whether or not additional software is required for full support.
Languagemajor modeLSP clientLSP server
ActionScriptlsp-mode
Adalsp-mode
Angularlsp-mode
Bashbuiltinlsp-modeinstall_lsp_bash
C/C++emacs-ccls(pending)
C#csharp-modelsp-mode
Closureclojure-modelsp-mode
Cmakecmake-modelsp-modeinstall_lsp_cmake
Crystallsp-mode
CSS/LessCSS/SASS/SCSSlsp-modeinstall_lsp_css
Dlsp-mode
Dartlsp-dart
Dockerfilelsp-modeinstall_lsp_dockerfile
Elixirlsp-mode
Elmelm-modelsp-modeinstall_lsp_elm
Erlanglsp-mode
ESlintlsp-mode
F#lsp-mode
Fishfish-mode
Fortranbuiltinlsp-modeinstall_lsp_fortran
GDScriptlsp-mode
Gogo-modelsp-modemissing
Groovygroovy-modelsp-mode
Hacklsp-mode
Haskellhaskell-modelsp-haskellinstall_haskell
Haxelsp-mode
Lispbuiltin
Lualsp-mode
Javalsp-javainstall_java
Javascriptlsp-modeinstall_lsp_typescript
Julialsp-julia
Kotlinlsp-mode
Nimlsp-mode
Nixlsp-mode
OCamlcaml-modelsp-mode
Perllsp-mode
ObjectiveCemacs-ccls(pending)
PHPphp-actorlsp-modeinstall_lsp_php
Prologlsp-mode
PureScriptpurescript-modelsp-modeinstall_lsp_purescript
Powershellbuiltinlsp-mode
Pythonpython-modelsp-modeinstall_lsp_python
Rlsp-mode(pending)
Racketlsp-mode
Rubyruby-modemissing
RFlsp-mode
Rustrust-moderusticinstall_rust
SolarGraphlsp-mode
Sorbetlsp-mode
SQLlsp-mode
Steeplsp-mode
Sveltelsp-mode
Saltsalt-modemissing
Scalascala-modelsp-metalsinstall_scala
SBTsbt-modeinstall_sbt
Swiftswift-mode(pending)
Typescripttypescript-modeinstall_lsp_typescript
TOMLtoml-modeinstall_rust
Vlsp-mode
Valalsp-mode
Veriloglsp-modeinstall_lsp_hdl
Veturvue-modeinstall_lsp_vue
VIMscriptvimrc-modelsp-modeinstall_lsp_vimrc
WASMwat-modemissing
Ziglsp-mode

Support for data languages

Languagemajor modeLSP clientLSP server
Dhalldhall-modelsp-modeinstall_dhall
GraphQLgraphql-modelsp-modeinstall_lsp_graphql
JSONjson-modelsp-modeinstall_lsp_json
Terraformhcl-modelsp-modeinstall_terraform
VHDLlsp-mode
YAMLyaml-modelsp-modeinstall_lsp_yaml
XMLbuiltinlsp-mode

Support for markup languages

LanguagemodeLSP clientLSP server
HTMLbuiltinlsp-modeinstall_lsp_html
LaTeXbuiltinlsp-latexinstall_rust
Markdownmarkdown-modelsp-modeinstall_lsp_markdown
RSTbuiltin
Sphinxsphinx-mode
TeXbuiltinlsp-modeinstall_rust

Source code management

PackagePurposeStatus
magita powerful frontend for Gitdone
monkya powerful frontend for Mercurial/Hgdone
find-file-in-repositoryfind files in the source controldone

Ivy, an excellent completion framework

PackagePurposeStatus
ivyEasy completion from a listdone
ivy-treemacstree navigation sidebardone
swiperIsearch with an overview. Oh, man!done
counsel-jqLive preview of “jq” queries using counseldone
counsel-etagsComplete Ctags/Etags solution using ivydone
counsel-projectileIvy integration for Projectiledone

Additional extensions

PackagePurposeStatus
undo-treerecovers any past state of a bufferdone
move-dupEclipse-like move and duplicate linesdone
highlight-symbolhighlight and navigate between symbolsdone
goto-chggoto last change in current bufferdone
yasnippettemplate systemdone
yatemplateexpand abbreviations into function templatesdone
smartparensdeals with parens pairs in smart waysdone
gistshare snippets and pastesdone
restclientREST REPLdone
rgripgrepdone
multiple-cursorsedit multiple places of a buffer at oncedone
window-numberingassign numbers to windows for quick accessdone
expand-regionincrease selected region by semantic unitsdone

Additional custom functions

  • move-region-to-file
  • save-latest-defined-macro

—-

About this configuration file

This file you are reading right now is also a Emacs configuration file.

You can skip reading the remainder of this file, unless you’d like to learn how to configure Emacs or you’d like to learn a bit of “org-mode“.

Disable menus

;; Dark screen as soon as possible
(add-to-list 'default-frame-alist '(background-color . "#000000"))
;; No splash screen please
(setq inhibit-startup-message t)
;; Turn off mouse interface early in startup to avoid momentary display
(if (fboundp 'menu-bar-mode)   (menu-bar-mode -1))
(if (fboundp 'tool-bar-mode)   (tool-bar-mode -1))
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(if (fboundp 'tooltip-mode)    (tooltip-mode -1))

Bootstrap straight.el

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/master/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))
;;;;  Effectively replace use-package with straight-use-package
;;; https://github.com/raxod502/straight.el/blob/develop/README.md#integration-with-use-package
(straight-use-package 'use-package)
(setq straight-use-package-by-default t)

Automatic package updates

The auto-package-update package helps us keep our Emacs packages up to date! It will prompt you after a certain number of days either at startup or at a specific time of day to remind you to update your packages.

You can also use M-x auto-package-update-now to update right now!

(use-package auto-package-update
  :custom
  (auto-package-update-interval 7)
  (auto-package-update-prompt-before-update t)
  (auto-package-update-hide-results t)
  :config
  (auto-package-update-maybe)
  (auto-package-update-at-time "09:00"))

Keep Folders Clean

We use the no-littering package to keep folders where we edit files and the Emacs configuration folder clean! It knows about a wide variety of variables for built in Emacs features as well as those from community packages so it can be much easier than finding and setting these variables yourself.

;; NOTE: If you want to move everything out of the ~/.emacs.d folder
;; reliably, set `user-emacs-directory` before loading no-littering!
;(setq user-emacs-directory "~/.cache/emacs")
(use-package no-littering)

;; no-littering doesn't set this by default so we must place
;; auto save files in the same path as it uses for sessions
(setq auto-save-file-name-transforms
      `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))

Color theme and mode line

doom-themes is a great set of themes with a lot of variety and support for many different Emacs modes. Taking a look at the screenshots might help you decide which one you like best. You can also run M-x counsel-load-theme to choose between them easily.

(use-package doom-themes
  :init (load-theme 'doom-molokai t))

(use-package doom-modeline
      :ensure t
      :defer t
      :hook (after-init . doom-modeline-mode))

Helpful Help Commands

Helpful adds a lot of very helpful (get it?) information to Emacs’ describe- command buffers. For example, if you use describe-function, you will not only get the documentation about the function, you will also see the source code of the function and where it gets used in other places in the Emacs configuration. It is very useful for figuring out how things work in Emacs.

(use-package helpful
  :commands (helpful-callable helpful-variable helpful-command helpful-key)
  :custom
  (counsel-describe-function-function #'helpful-callable)
  (counsel-describe-variable-function #'helpful-variable)
  :bind
  ([remap describe-function] . counsel-describe-function)
  ([remap describe-command] . helpful-command)
  ([remap describe-variable] . counsel-describe-variable)
  ([remap describe-key] . helpful-key))

Hydra has several arms

(use-package hydra)

(use-package hydra-posframe
  :after hydra
  :straight (:host github :repo "Ladicle/hydra-posframe")
  :hook (after-init . hydra-posframe-enable)
  :init
  (setq hydra-posframe-poshandler 'posframe-poshandler-frame-bottom-center)
  (setq hydra-posframe-border-width 1)
  (setq hydra-posframe-parameters '((left-fringe . 5)(right-fringe . 5)))
  :custom-face (hydra-posframe-border-face ((t (:background "#bf616a"))))
  :custom-face (hydra-posframe-face ((t (:background "#3b4252")))))

(use-package major-mode-hydra
  :after hydra-postframe
  :preface
  (defun with-alltheicon (icon str &optional height v-adjust)
    "Displays an icon from all-the-icon."
    (s-concat (all-the-icons-alltheicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str))

  (defun with-faicon (icon str &optional height v-adjust)
    "Displays an icon from Font Awesome icon."
    (s-concat (all-the-icons-faicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str))

  (defun with-fileicon (icon str &optional height v-adjust)
    "Displays an icon from the Atom File Icons package."
    (s-concat (all-the-icons-fileicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str))

  (defun with-octicon (icon str &optional height v-adjust)
    "Displays an icon from the GitHub Octicons."
    (s-concat (all-the-icons-octicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)))

Jump fast with Avy

Avy is a GNU Emacs package for jumping to visible text using a char-based decision tree.

https://github.com/abo-abo/avy

(use-package avy
  :bind (("C-:"   . avy-goto-char-timer)
         ("M-g g" . avy-goto-line)  ;; replaces goto-line
         ("M-g w" . avy-goto-word-1))
  :config (avy-setup-default)
  :init (setq avy-all-windows nil))

(defhydra hydra-avy (:exit t :hint nil)
  "
 Line^^       Region^^        Goto
----------------------------------------------------------
 [_y_] yank   [_Y_] yank      [_j_] timed char  [_c_] char          [_C_] char-2
 [_m_] move   [_M_] move      [_w_] word        [_W_] any word
 [_k_] kill   [_K_] kill      [_l_] line        [_L_] end of line"
  ("j" avy-goto-char-timer)
  ("c" avy-goto-char)
  ("C" avy-goto-char-2)
  ("w" avy-goto-word-1)
  ("W" avy-goto-word-0)
  ("l" avy-goto-line)
  ("L" avy-goto-end-of-line)
  ("m" avy-move-line)
  ("M" avy-move-region)
  ("k" avy-kill-whole-line)
  ("K" avy-kill-region)
  ("y" avy-copy-line)
  ("Y" avy-copy-region))

Ivy, an excellent completion framework

(use-package counsel
  :bind (("M-x"     . counsel-M-x)
         ("M-y"     . counsel-yank-pop)
         ("C-c s B" . counsel-switch-buffer)
         ("C-c s c" . counsel-compile)
         ("C-c s g" . counsel-git)
         ("C-c s j" . counsel-git-grep)
         ("C-c s L" . counsel-git-log)
         ("C-c s k" . counsel-rg)
         ("C-c s m" . counsel-linux-app)
         ("C-c s n" . counsel-fzf)
         ("C-c s l" . counsel-locate)
         ("C-c s J" . counsel-file-jump)
         ("C-c s b" . counsel-bookmark)
         ("C-c s D" . counsel-descbinds)
         ("C-c s o" . counsel-outline)
         ("C-c s t" . counsel-load-theme)
         ("C-c s f" . counsel-org-file)
         ("C-c s u" . counsel-unicode-char)
         ("C-c s v" . counsel-set-variable)
         ("C-c s p" . counsel-package)
         ("C-c s i" . counsel-info-lookup-symbol)
         ("C-h f"   . counsel-describe-function)
         ("C-h v"   . counsel-describe-variable)
         ("C-h l"   . counsel-find-library)
         ("C-x C-f" . counsel-find-file)
         :map minibuffer-local-map
         ("C-r" . 'counsel-minibuffer-history))
  :custom
  (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only)
  :config
  (counsel-mode t))

;; (use-package posframe)
;; (use-package flx)
;; (use-package wgrep)
;; (use-package wgrep-ag)

(use-package ivy
  :diminish
  :bind (("C-c C-r" . ivy-resume)
         ("C-x b"   . ivy-switch-buffer)
         ("C-x B"   . ivy-switch-buffer-other-window)
         ("C-c v"   . ivy-push-view)
         ("C-c V"   . ivy-pop-view)
         (:map ivy-minibuffer-map ("C-:" . ivy-avy))
         (:map ivy-minibuffer-map ("C-;" . hydra-avy/body)))
  :custom
  (ivy-count-format "(%d/%d) ")
  (ivy-use-virtual-buffers t)
  :config
  (ivy-mode)
  (setq ivy-re-builders-alist
        '(
          (ivy-switch-buffer . ivy--regex-fuzzy)
          (counsel-ag        . ivy--regex-plus)
          (counsel-git-grep  . ivy--regex-plus)
          (swiper            . ivy--regex) 
          (t                 . ivy--regex-fuzzy))))

(use-package ivy-hydra
  :after ivy)

(use-package all-the-icons-ivy-rich
  :requires ivy avy
  :init (all-the-icons-ivy-rich-mode t))

(use-package ivy-rich
  :after counsel
  :custom
  (ivy-virtual-abbreviate 'full
                          ivy-rich-switch-buffer-align-virtual-buffer t
                          ivy-rich-path-style 'abbrev)
  :config
  (ivy-rich-mode t))

(use-package ivy-prescient
  :after counsel
  :custom
  (ivy-prescient-enable-filtering nil)
  :config
  ;; Uncomment the following line to have sorting remembered across sessions!
  (prescient-persist-mode t)
  (ivy-prescient-mode t))

;;XXX (use-package ivy-postframe :demand :after counsel)

(use-package counsel-projectile :demand)
;;FIXME: (use-package ag :demand 'lisp-indent-function)
;;FIXME: (use-package wgrep-ag :demand)

(use-package smartparens
  :demand
  :diminish smartparens-mode
  :commands
  smartparens-strict-mode
  smartparens-mode
  sp-restrict-to-pairs-interactive
  sp-local-pair
  :hook (common-lisp-modes-mode . smartparens-strict-mode)
  :hook (prog-mode              . smartparens-strict-mode)
  :hook (common-lisp-mode       . smartparens-strict-mode)
  :hook (emacs-lisp-mode        . smartparens-strict-mode)
  :hook (reb-mode               . smartparens-strict-mode)
  :hook (reb-lisp-mode          . smartparens-strict-mode)
  :hook (closure-mode           . smartparens-strict-mode)
  ;;:init (setq sp-interactive-dwim t)
  :config
  (require 'smartparens-config)
  (sp-use-smartparens-bindings)
  (sp-pair "(" ")" :wrap "C-(") ;; how do people live without this?
  (sp-pair "[" "]" :wrap "s-[") ;; C-[ sends ESC
  (sp-pair "{" "}" :wrap "C-{")
  ;; WORKAROUND https://github.com/Fuco1/smartparens/issues/543
  (bind-key "C-<left>"  nil smartparens-mode-map)
  (bind-key "C-<right>" nil smartparens-mode-map)
  (bind-key "s-<delete>"    'sp-kill-sexp smartparens-mode-map)
  (bind-key "s-<backspace>" 'sp-backward-kill-sexp smartparens-mode-map))

Hydra has several arms (experimental)

(major-mode-hydra-define emacs-lisp-mode nil
  ("Eval"
   (("b" eval-buffer "buffer")
    ("e" eval-defun "defun")
    ("r" eval-region "region"))
   "REPL"
   (("I" ielm "ielm"))
   "Test"
   (("t" ert "prompt")
    ("T" (ert t) "all")
    ("F" (ert :failed) "failed"))
   "Doc"
   (("d" describe-foo-at-point "thing-at-pt")
    ("f" describe-function "function")
    ("v" describe-variable "variable")
    ("i" info-lookup-symbol "info lookup"))))

;;Hydra / BToggle
;;Group a lot of commands.
(pretty-hydra-define hydra-btoggle
  (:hint nil :quit-key "q" :title (with-faicon "toggle-on" "Toggle" 1 -0.05))
  ("Basic"
   (("a" abbrev-mode "abbrev" :toggle t)
    ("n" auto-insert-mode "auto-insert" :toggle t)
    ("h" global-hungry-delete-mode "hungry delete" :toggle t))
   "Coding"
   (("e" electric-operator-mode "electric operator" :toggle t)
    ("f" flycheck-mode "flycheck" :toggle t)
    ("l" lsp-mode "lsp" :toggle t)
    ("H" hl-todo-mode "hl-todo" :toggle t)
    ("o" origami-mode "origami" :toggle t)
    ("s" smartparens-mode "smartparens" :toggle t))
   "Debug"
   (("de" toggle-debug-on-error "debug on error" :toggle debug-on-error)
    ("dq" toggle-debug-on-quit "debug on C-g" :toggle debug-on-quit))
   "UI"
   (("i" ivy-rich-mode "ivy-rich" :toggle t))))

(pretty-hydra-define hydra-flycheck
  (:hint nil :quit-key "q" :title (with-faicon "plane" "Flycheck" 1 -0.05))
  ("Checker"
   (("?" flycheck-describe-checker "describe")
    ("d" flycheck-disable-checker "disable")
    ("m" flycheck-mode "mode")
    ("s" flycheck-select-checker "select"))
   "Errors"
   (("k" flycheck-previous-error "previous")
    ("j" flycheck-next-error "next")
    ("f" flycheck-buffer "check")
    ("l" flycheck-list-errors "list"))
   "Other"
   (("M" flycheck-manual "manual")
    ("v" flycheck-verify-setup "verify setup"))))

(defhydra hydra-yasnippet (:hint nil)
  "
              ^YASnippets^
--------------------------------------------
  Modes:    Load/Visit:    Actions:
 _g_lobal  _d_irectory    _i_nsert
 _m_inor   _f_ile         _t_ryout
 _e_xtra   _l_ist         _n_ew
         _a_ll
"
  ("d" yas-load-directory)
  ("e" yas-activate-extra-mode)
  ("i" yas-insert-snippet)
  ("f" yas-visit-snippet-file)
  ("n" yas-new-snippet)
  ("t" yas-tryout-snippet)
  ("l" yas-describe-tables)
  ("g" yas/global-mode)
  ("m" yas/minor-mode)
  ("a" yas-reload-all))

(defhydra hydra-smartparens (:hint nil)
  "
 Moving^^^^                       Slurp & Barf^^   Wrapping^^            Sexp juggling^^^^               Destructive
------------------------------------------------------------------------------------------------------------------------
 [_a_] beginning  [_n_] down      [_h_] bw slurp   [_R_]   rewrap        [_S_] split   [_t_] transpose   [_c_] change inner  [_w_] copy
 [_e_] end        [_N_] bw down   [_H_] bw barf    [_u_]   unwrap        [_s_] splice  [_A_] absorb      [_C_] change outer
 [_f_] forward    [_p_] up        [_l_] slurp      [_U_]   bw unwrap     [_r_] raise   [_E_] emit        [_k_] kill          [_g_] quit
 [_b_] backward   [_P_] bw up     [_L_] barf       [_(__{__[_] wrap (){}[]   [_j_] join    [_o_] convolute   [_K_] bw kill       [_q_] quit"
  ;; Moving
  ("a" sp-beginning-of-sexp)
  ("e" sp-end-of-sexp)
  ("f" sp-forward-sexp)
  ("b" sp-backward-sexp)
  ("n" sp-down-sexp)
  ("N" sp-backward-down-sexp)
  ("p" sp-up-sexp)
  ("P" sp-backward-up-sexp)

  ;; Slurping & barfing
  ("h" sp-backward-slurp-sexp)
  ("H" sp-backward-barf-sexp)
  ("l" sp-forward-slurp-sexp)
  ("L" sp-forward-barf-sexp)

  ;; Wrapping
  ("R" sp-rewrap-sexp)
  ("u" sp-unwrap-sexp)
  ("U" sp-backward-unwrap-sexp)
  ("(" sp-wrap-round)
  ("{" sp-wrap-curly)
  ("[" sp-wrap-square)

  ;; Sexp juggling
  ("S" sp-split-sexp)
  ("s" sp-splice-sexp)
  ("r" sp-raise-sexp)
  ("j" sp-join-sexp)
  ("t" sp-transpose-sexp)
  ("A" sp-absorb-sexp)
  ("E" sp-emit-sexp)
  ("o" sp-convolute-sexp)

  ;; Destructive editing
  ("c" sp-change-inner :exit t)
  ("C" sp-change-enclosing :exit t)
  ("k" sp-kill-sexp)
  ("K" sp-backward-kill-sexp)
  ("w" sp-copy-sexp)

  ("q" nil)
  ("g" nil))

;; TODO this doesn't work
(pretty-hydra-define hydra-s
  (:hint t :quit-key "RET" :title "String manipulation")
  ("Pertaining to words"
   (("w" (lambda()(interactive)(s-split-words (buffer-substring-no-properties (region-beginning) (region-end)))) "split words")
    ("c" (lambda()(interactive)(s-lower-camel-case (buffer-substring-no-properties (region-beginning) (region-end)))) "lower camel")
    ("C" (lambda()(interactive)(s-upper-camel-case (buffer-substring-no-properties (region-beginning) (region-end)))) "upper camel")
    ("s" (lambda()(interactive)(s-snake-case (buffer-substring-no-properties (region-beginning) (region-end)))) "snake")
    ("d" (lambda()(interactive)(s-dashed-words (buffer-substring-no-properties (region-beginning) (region-end)))) "dashed")
    ("W" (lambda()(interactive)(s-capitalized-words (buffer-substring-no-properties (region-beginning) (region-end)))) "capital")
    ("t" (lambda()(interactive)(s-titleized-words (buffer-substring-no-properties (region-beginning) (region-end)))) "titleize")
    ("i" (lambda()(interactive)(s-word-initials (buffer-substring-no-properties (region-beginning) (region-end)))) "initials"))))

(defhydra hydra-avy (:exit t :hint nil)
  "
 Line^^       Region^^        Goto
----------------------------------------------------------
 [_y_] yank   [_Y_] yank      [_j_] timed char  [_c_] char          [_C_] char-2
 [_m_] move   [_M_] move      [_w_] word        [_W_] any word
 [_k_] kill   [_K_] kill      [_l_] line        [_L_] end of line"
  ("j" avy-goto-char-timer)
  ("c" avy-goto-char)
  ("C" avy-goto-char-2)
  ("w" avy-goto-word-1)
  ("W" avy-goto-word-0)
  ("l" avy-goto-line)
  ("L" avy-goto-end-of-line)
  ("m" avy-move-line)
  ("M" avy-move-region)
  ("k" avy-kill-whole-line)
  ("K" avy-kill-region)
  ("y" avy-copy-line)
  ("Y" avy-copy-region))

(defhydra hydra-smerge
  (:hint nil
          :pre (smerge-mode 1))
  "
^Move^ ^Keep^ ^Diff^ ^Pair^
------------------------------------------------------
_n_ext _b_ase  _R_efine _<_: base-upper
_p_rev _u_pper _E_diff _=_: upper-lower
^ ^ _l_ower _C_ombine _>_: base-lower
^ ^ _a_ll _r_esolve
_q_uit _RET_: current
"
  ("RET" smerge-keep-current)
  ("C" smerge-combine-with-next)
  ("E" smerge-ediff)
  ("R" smerge-refine)
  ("a" smerge-keep-all)
  ("b" smerge-keep-base)
  ("u" smerge-keep-upper)
  ("n" smerge-next)
  ("l" smerge-keep-lower)
  ("p" smerge-prev)
  ("r" smerge-resolve)
  ("<" smerge-diff-base-upper)
  ("=" smerge-diff-upper-lower)
  (">" smerge-diff-base-lower)
  ("q" nil))

(pretty-hydra-define hydra-projectile
  (:hint nil :quit-key "q" :title (with-faicon "rocket" "Projectile" 1 -0.05))
  ("Buffers"
   (("b" counsel-projectile-switch-to-buffer "list")
    ("k" projectile-kill-buffers "kill all")
    ("S" projectile-save-project-buffers "save all"))
   "Find"
   (("d" counsel-projectile-find-dir "directory")
    ("F" projectile-recentf "recent files")
    ("D" projectile-dired "dired")
    ("g" counsel-projectile-find-file-dwim "file dwim")
    ("f" counsel-projectile-find-file "file")
    ("p" counsel-projectile-switch-project "project"))
   "Other"
   (("i" projectile-invalidate-cache "reset cache")
    ("x" projectile-remove-known-project "remove known project")
    ("z" projectile-cache-current-file "cache current file")
    ("X" projectile-cleanup-known-projects "cleanup known projects"))
   "Search"
   (("r" projectile-replace "replace")
    ("o" projectile-multi-occur "occur")
    ("R" projectile-replace-regexp "regexp replace")
    ("sg" counsel-projectile-grep "grep")
    ("ss" counsel-projectile-ag "ag")
    ("sr" counsel-projectile-rg "rg")
    ("ss" counsel-rg "search")
    )))

(defhydra hydra-next-error (:hint nil)
    "
Compilation errors:
_k_: next error        _j_: first error    _q_uit
_i_: previous error    _l_: last error
"
    ("`" next-error     nil)
    ("k" next-error     nil :bind nil)
    ("i" previous-error nil :bind nil)
    ("j" first-error    nil :bind nil)
    ("l" (condition-case err
             (while t
               (next-error))
           (user-error nil))
     nil :bind nil)
    ("q" nil            nil))

(pretty-hydra-define hydra-lsp-metals
  (:hint nil :quit-key "q" :exit t :title (with-faicon "rocket" "LSP"))
    ("Find"
     (("fD"  lsp-find-declaration "declaration")
      ("fd"  lsp-find-definition "definition")
      ("fr"  lsp-find-references "references")
      ("fi"  lsp-find-implementation "implementation")
      ("ft"  lsp-find-type-definition "type")
      ("fs"  lsp-ivy-workspace-symbol "symbol")
      ("fS"  lsp-ivy-global-workspace-symbol "global symbol")
      ("fw"  lsp-ui-find-workspace-symbol "ui symbol")
      ("fe"  lsp-treemacs-errors-list "errors list")
      ("fh"  lsp-treemacs-call-hierarchy "call hierarchy")
      ("pd"  lsp-ui-peek-find-definitions "peek definitions")
      ("pr"  lsp-ui-peek-find-references "peek references")
      ("pf"  lsp-ui-peek-find-workspace-symbol "peek symbol")
      ("pi"  lsp-ui-peek-find-implementation "peek implementation"))
     "Toggle"
     (("td"  lsp-ui-doc-mode "doc" :toggle t)
      ("tS"  lsp-ui-sideline-mode "sideline mode" :toggle t)
      ("ts"  lsp-ui-sideline-toggle-symbols-info "sideline symbols" :toggle t)
      ("tl"  lsp-lens-mode "lens" :toggle t)
      ("ti"  lsp-toggle-trace-io "trace-io" :toggle t)
      ("th"  lsp-toggle-symbol-highlight "symbol highlight")
      ("tf"  lsp-toggle-on-type-formatting "format" :toggle t)
      ("tF"  lsp-ui-flycheck-list "flycheck")
      ("tT"  lsp-treemacs-sync-mode "treemacs sync" :toggle t)
      ("tD"  lsp-diagnostics-modeline-mode "diag line" :toggle t)
      ("tnf" lsp-signature-toggle-full-docs "sign docs full")
      ("tna" lsp-signature-activate "sign activate help")
      ("tns" lsp-toggle-signature-auto-activate "sign auto activate"))
     "Code"
     (("cr"  lsp-rename "rename")
      ("co"  lsp-organize-imports "org imports")
      ("cm"  lsp-ui-imenu "imenu")
      ("cx"  lsp-execute-code-action "action")
      ("cd"  lsp-ui-doc-glance "doc glance")
      ("c."  lsp-describe-thing-at-point "describe")
      ("=f"  lsp-format-buffer "format")
      ("=r"  lsp-format-region "region")
      ("=l"  lsp-avy-lens "avy lens")
      ("=f"  lsp-ui-flycheck-list "flycheck list")
      ("=x"  xref-find-apropos "xref-apropos"))
     "Metals"
     (("Lb"  lsp-metals-build-import "build import")
      ("Ls"  lsp-metals-sources-scan "sources rescan")
      ("Lr"  lsp-metals-build-connect "bloop reconnect"))
     "Session"
     (("S?"  lsp-describe-session "describe")
      ("Ss"  lsp "start")
      ("Sd"  lsp-disconnect "disconnect")
      ("Sr"  lsp-workspace-restart "restart")
      ("Sq"  lsp-workspace-shutdown "shutdown")
      ("Sl"  lsp-workspace-show-log "log")
      ("Sfa" lsp-workspace-folders-add "folders +")
      ("Sfo" lsp-workspace-folders-open "folder")
      ("Sfr" lsp-workspace-folders-remove "folders -")
      ("Sfb" lsp-workspace-blacklist-remove "blacklist -"))))

(pretty-hydra-define hydra-magit
  (:hint nil :quit-key "q" :title (with-alltheicon "git" "Magit" 1 -0.05))
  ("Action"
   (("b" magit-blame-addition "blame")
    ("c" magit-clone "clone")
    ("i" magit-init "init")
    ("f" magit-file-popup "file popup")
    ("t" git-timemachine "time machine")
    ("l" magit-log-buffer-file "commit log (current file)")
    ("L" magit-log-current "commit log (project)")
    ("g" magit-status "status"))))

(pretty-hydra-define hydra-windows
  (:hint nil :forein-keys warn :quit-key "q" :title (with-faicon "windows" "Windows" 1 -0.05))
  ("Window"
   (("d" delete-window "delete window")
    ("o" delete-other-windows "delete others" :exit t)
    ("s" split-window-below "split below")
    ("h" split-window-horizontally "split horizontally")
    ("v" split-window-vertically "split vertically")
    ("w" other-window "other window" :exit t)
    ("r" rename-buffer "rename buffer" :exit t)
    ("a" ace-window "ace" :exit t)
    ("k" kill-buffer-and-window "kill buffer and window" :exit t))
   "Frame"
   (("fk" delete-frame "delete frame")
    ("fo" delete-other-frames "delete others")
    ("fn" make-frame-command "make frame"))
   "Size"
   (("b" balance-windows "balance")
    ("L" shrink-window-horizontally "narrow")
    ("H" enlarge-window-horizontally "widen")
    ("J" shrink-window "lower")
    ("K" enlarge-window "heighten")
    ("S" switch-window-then-swap-buffer "swap"))
   "Zoom"
   (("-" zoom-out "out");text-scale-decrease "out")
    ("+" zoom-in "in");text-scale-increase "in")
    ("=" zoom-frm-unzoom "reset"))));(text-scale-increase 0) "reset"))))

(defhydra hydra-buffer-menu (:hint nil)
  "
^Mark^             ^Unmark^           ^Actions^          ^Search
^^^^^^^^-----------------------------------------------------------------
_m_: mark          _u_: unmark        _x_: execute       _R_: re-isearch
_s_: save          _U_: unmark up     _b_: bury          _I_: isearch
_d_: delete        ^ ^                _g_: refresh       _O_: multi-occur
_D_: delete up     ^ ^                _T_: files only: % -28`Buffer-menu-files-only
_~_: modified
"
  ("m" Buffer-menu-mark)
  ("u" Buffer-menu-unmark)
  ("U" Buffer-menu-backup-unmark)
  ("d" Buffer-menu-delete)
  ("D" Buffer-menu-delete-backwards)
  ("s" Buffer-menu-save)
  ("~" Buffer-menu-not-modified)
  ("x" Buffer-menu-execute)
  ("b" Buffer-menu-bury)
  ("g" revert-buffer)
  ("T" Buffer-menu-toggle-files-only)
  ("O" Buffer-menu-multi-occur)
  ("I" Buffer-menu-isearch-buffers)
  ("R" Buffer-menu-isearch-buffers-regexp)
  ("c" nil "cancel")
  ("v" Buffer-menu-select "select")
  ("o" Buffer-menu-other-window "other-window")
  ("q" quit-window "quit"))

(defhydra hydra-folding (:hint nil)
   "
  _o_pen node    _n_ext fold       toggle _f_orward  _s_how current only
  _c_lose node   _p_revious fold   toggle _a_ll
  "
   ("o" origami-open-node)
   ("c" origami-close-node)
   ("n" origami-next-fold)
   ("p" origami-previous-fold)
   ("f" origami-forward-toggle-node)
   ("a" origami-toggle-all-nodes)
   ("s" origami-show-only-node))

(pretty-hydra-define hydra-accessibility
  (:hint nil :quit-key "q" :title (with-faicon "universal-access" "Accessibility" 1 -0.05))
  ("TTS" (
    ("b" festival-say-buffer "festival bufer")
    ("r" festival-say-region "festival region")
    ("k" festival-kill-process "festival kill"))))

(pretty-hydra-define hydra-org
  (:hint nil :quit-key "q" :title (with-fileicon "org" "Org" 1 -0.05))
  ("Action"
   (
    ("a" org-agenda "agenda")
    ("j" hydra-org-clock/body "clock")
    ("O" hydra-org-agenda/body "agenda hydra")
    ("C" cfw:open-org-calendar "calfw-org")
    ("s" my/org-ql-goals "goals")
    ("c" org-capture "capture")
    ("g" org-gcal-fetch "gcal fetch")
    ("G" org-gcal-sync "gcal sync")
    ("L" org-store-link "store-link")
    ("l" org-insert-link-global "insert-link")
    ("A" org-archive-done-in-file "archive done in file")
    ("d" org-decrypt-entry "decrypt")
    ("I" org-info-find-node "org info find")
    ("k" org-cut-subtree "cut-subtree")
    ("o" org-open-at-point-global "open-link")
    ("r" org-refile "refile")
    ("t" org-show-todo-tree "todo-tree"))))


(pretty-hydra-define hydra-org-clock
  (:hint nil :quit-key "q" :exit t :title (with-faicon "clock-o" "Clock"))
  ("Clock"
   (("i" org-mru-clock-in "pick in")
    ("I" org-clock-in "in")
    ("o" org-clock-out "out")
    ("c" org-clock-in-last "in last")
    ("j" org-mru-clock-select-recent-task "select recent")
    ("J" org-clock-goto "goto")
    ("e" org-clock-modify-effort-estimate "edit")
    ("q" org-clock-cancel "quit")
    ("?" (org-info "Clocking commands") "info"))
   "Clock report"
   (("d" org-clock-display "display")
    ("r" org-clock-report "report"))
   "Pomodoro"
   (("pp" (org-pomodoro '(16)) "start") ;; (4) - will ask for task interactively
    ("pr" (org-pomodoro-reset) "reset"))
   "Timer"
   (("ts" org-timer-start "start")
    ("tt" org-timer-set-timer "set")
    ("tp" org-timer-pause-or-continue "pause")
    ("tq" org-timer-stop "stop")
    ("t?" (org-info "Timers") "info"))
   "Timer insert"
   (("tm" org-timer "time")
    ("ti" org-timer-item "item"))))

(defhydra hydra-org-agenda (:pre (setq which-key-inhibit t)
                                 :post (setq which-key-inhibit nil)
                                 :hint none)
  "
Org agenda (_q_uit)
^Clock^      ^Visit entry^              ^Date^             ^Other^
^-----^----  ^-----------^------------  ^----^-----------  ^-----^---------
_ci_ in      _SPC_ in other window      _ds_ schedule      _gr_ reload
_co_ out     _TAB_ & go to location     _dd_ set deadline  _._  go to today
_cq_ cancel  _RET_ & del other windows  _dt_ timestamp     _gd_ go to date
_cj_ jump    _o_   link                 _+_  do later      ^^
^^           ^^                         _-_  do earlier    ^^
^^           ^^                         ^^                 ^^
^View^          ^Filter^                 ^Headline^         ^Toggle mode^
^----^--------  ^------^---------------  ^--------^-------  ^-----------^----
_vd_ day        _ft_ by tag              _ht_ set status    _tf_ follow
_vw_ week       _fr_ refine by tag       _hk_ kill          _tl_ log
_vt_ fortnight  _fc_ by category         _hr_ refile        _ta_ archive trees
_vm_ month      _fh_ by top headline     _hA_ archive       _tA_ archive files
_vy_ year       _fx_ by regexp           _h:_ set tags      _tr_ clock report
_vn_ next span  _fd_ delete all filters  _hp_ set priority  _td_ diaries
_vp_ prev span  ^^                       ^^                 ^^
_vr_ reset      ^^                       ^^                 ^^
^^              ^^                       ^^                 ^^
"
  ;; Entry
  ("hA" org-agenda-archive-default)
  ("hk" org-agenda-kill)
  ("hp" org-agenda-priority)
  ("hr" org-agenda-refile)
  ("h:" org-agenda-set-tags)
  ("ht" org-agenda-todo)
  ;; Visit entry
  ("o"   link-hint-open-link :exit t)
  ("<tab>" org-agenda-goto :exit t)
  ("TAB" org-agenda-goto :exit t)
  ("SPC" org-agenda-show-and-scroll-up)
  ("RET" org-agenda-switch-to :exit t)
  ;; Date
  ("dt" org-agenda-date-prompt)
  ("dd" org-agenda-deadline)
  ("+" org-agenda-do-date-later)
  ("-" org-agenda-do-date-earlier)
  ("ds" org-agenda-schedule)
  ;; View
  ("vd" org-agenda-day-view)
  ("vw" org-agenda-week-view)
  ("vt" org-agenda-fortnight-view)
  ("vm" org-agenda-month-view)
  ("vy" org-agenda-year-view)
  ("vn" org-agenda-later)
  ("vp" org-agenda-earlier)
  ("vr" org-agenda-reset-view)
  ;; Toggle mode
  ("ta" org-agenda-archives-mode)
  ("tA" (org-agenda-archives-mode 'files))
  ("tr" org-agenda-clockreport-mode)
  ("tf" org-agenda-follow-mode)
  ("tl" org-agenda-log-mode)
  ("td" org-agenda-toggle-diary)
  ;; Filter
  ("fc" org-agenda-filter-by-category)
  ("fx" org-agenda-filter-by-regexp)
  ("ft" org-agenda-filter-by-tag)
  ("fr" org-agenda-filter-by-tag-refine)
  ("fh" org-agenda-filter-by-top-headline)
  ("fd" org-agenda-filter-remove-all)
  ;; Clock
  ("cq" org-agenda-clock-cancel)
  ("cj" org-agenda-clock-goto :exit t)
  ("ci" org-agenda-clock-in :exit t)
  ("co" org-agenda-clock-out)
  ;; Other
  ("q" nil :exit t)
  ("gd" org-agenda-goto-date)
  ("." org-agenda-goto-today)
  ("gr" org-agenda-redo))

;; came from here - https://github.com/kaushalmodi/.emacs.d/blob/master/setup-files/setup-elisp.el
(defhydra hydra-edebug (:hint  none)
  "
    EDEBUG MODE
^^_<SPC>_ step             ^^_f_ forward sexp         _b_reakpoint set                previous _r_esult      _w_here                    ^^_d_ebug backtrace
^^_n_ext                   ^^goto _h_ere              _u_nset breakpoint              _e_val expression      bounce _p_oint             _q_ top level (_Q_ nonstop)
_g_o (_G_ nonstop)         ^^_I_nstrument callee      next _B_reakpoint               _E_val list            _v_iew outside             ^^_a_bort recursive edit
_t_race (_T_ fast)         step _i_n/_o_ut            _x_ conditional breakpoint      eval _l_ast sexp       toggle save _W_indows      ^^_S_top
_c_ontinue (_C_ fast)      ^^^^                       _X_ global breakpoint
"
  ("<SPC>" edebug-step-mode)
  ("n"     edebug-next-mode)
  ("g"     edebug-go-mode)
  ("G"     edebug-Go-nonstop-mode)
  ("t"     edebug-trace-mode)
  ("T"     edebug-Trace-fast-mode)
  ("c"     edebug-continue-mode)
  ("C"     edebug-Continue-fast-mode)

  ("f"     edebug-forward-sexp)
  ("h"     edebug-goto-here)
  ("I"     edebug-instrument-callee)
  ("i"     edebug-step-in)
  ("o"     edebug-step-out)

  ;; breakpoints
  ("b"     edebug-set-breakpoint)
  ("u"     edebug-unset-breakpoint)
  ("B"     edebug-next-breakpoint)
  ("x"     edebug-set-conditional-breakpoint)
  ("X"     edebug-set-global-break-condition)

  ;; evaluation
  ("r"     edebug-previous-result)
  ("e"     edebug-eval-expression)
  ("l"     edebug-eval-last-sexp)
  ("E"     edebug-visit-eval-list)

  ;; views
  ("w"     edebug-where)
  ("p"     edebug-bounce-point)
  ("v"     edebug-view-outside) ; maybe obsolete??
  ("P"     edebug-view-outside) ; same as v
  ("W"     edebug-toggle-save-windows)

  ("d"     edebug-backtrace)

  ;; quitting and stopping
  ("q"     top-level)
  ("Q"     edebug-top-level-nonstop)
  ("a"     abort-recursive-edit)
  ("S"     edebug-stop))

(with-eval-after-load 'edebug
  (bind-key "?" #'hydra-edebug/body edebug-mode-map))

Programming languages

Support for code snippets

(use-package yasnippet
  :demand
  :diminish yas-minor-mode
  :commands yas-minor-mode
  :config (yas-global-mode))

(use-package yasnippet-snippets
  :demand
  :requires (yasnippet))

(use-package ivy-yasnippet
  :demand
  :requires (yasnippet yasnippet-snippets))

Support for Language Server Protocol

LSP provides builtin support for a vast range of programming languages. See: https://github.com/emacs-lsp/lsp-mode#supported-languages

(use-package flycheck
  :init (global-flycheck-mode t))

;; see: https://emacs-lsp.github.io/lsp-mode/lsp-mode.html
(use-package lsp-mode
  :commands (lsp lsp-deferred)
  :hook
  (csharp-mode      . lsp)
  (css-mode         . lsp)
  (closure-mode     . lsp)
  (cmake-mode       . lsp)
  (fish-mode        . lsp)
  (groovy-mode      . lsp)
  (haskell-mode     . lsp)
  (emacs-lisp-mode  . lsp)
  ;;(ocaml-mode     . lsp)
  ;; (php-mode      . lsp)
  (purescript-mode  . lsp)
  ;; (pwsh-mode     . lsp)
  (python-mode      . lsp)
  ;; (ruby-mode     . lsp)
  (rust-mode        . lsp)
  (salt-mode        . lsp)
  (scala-mode       . lsp)
  (sh-mode          . lsp)
  ;;(swift-mode     . lsp)
  (js-mode          . lsp)
  (typescript-mode  . lsp)
  (vue-mode         . lsp)
  (vimrc-mode       . lsp)
  (wasm-mode        . lsp)
  (dhall-mode       . lsp)
  (graphql-mode     . lsp)
  (json-mode        . lsp)
  (hcl-mode         . lsp)
  (yaml-mode        . lsp)
  (xml-mode         . lsp)
  (html-mode        . lsp)
  (markdown-mode    . lsp)
  (rst-mode         . lsp)
  ;;(sphinx-mode    . lsp)
  ;;(tex-mode       . lsp)
  ;;(latex-mode     . lsp)
  (prog-mode        . lsp)
  (lsp-managed-mode . lsp-modeline-diagnostics-mode)
  (lsp-mode         . (lsp-lens-mode
                       lsp-enable-which-key-integration
                       lsp-headerline-breadcrumb-mode
                       lsp-modeline-code-actions-mode))
  :init
    (setq gc-cons-threshold (* 100 1024 1024)     ;; 100Mb
          read-process-output-max (* 8 1024 1024) ;;   8Mb
          max-lisp-eval-depth (* 10 1024)
          max-specpdl-size    (*  4 1024)
          lsp-idle-delay 0.500
          lsp-log-io nil
          lsp-prefer-flymake nil
          lsp-auto-guess-root nil ;; https://github.com/hlissner/doom-emacs/issues/1928
          lsp-keymap-prefix "C-c l"
          lsp-completion-show-detail t
          lsp-completion-show-kind t
          lsp-eldoc-enable-hover t
          lsp-lens-enable t
          lsp-enable-imenu t
          lsp-enable-symbol-highlighting t
          lsp-headerline-breadcrumb-enable t
          lsp-enable-indentation t
          lsp-enable-completion-at-point t
          lsp-headerline-breadcrumb-enable-diagnostics t
          lsp-modeline-code-actions-enable t
          lsp-modeline-diagnostics-enable t
          lsp-signature-auto-activate t
          lsp-signature-render-documentation t))

(use-package which-key
  :config
    (which-key-mode))

(use-package projectile :demand)

(use-package treemacs
  :requires (ivy)
  :defer t
  :init
    (with-eval-after-load 'winum
      (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :bind (:map global-map ("C-x t t" . treemacs))
  :commands treemacs-modify-theme
  :config
    (require 'treemacs-themes)
    (require 'treemacs-icons)
    (require 'treemacs-icons-dired)
    (require 'treemacs-projectile)
    (require 'treemacs-magit)
    (progn
      (setq treemacs-collapse-dirs                 (if treemacs-python-executable 3 0)
            treemacs-deferred-git-apply-delay      0.5
            treemacs-directory-name-transformer    #'identity
            treemacs-display-in-side-window        t
            treemacs-eldoc-display                 t
            treemacs-file-event-delay              5000
            treemacs-file-extension-regex          treemacs-last-period-regex-value
            treemacs-file-follow-delay             0.2
            treemacs-file-name-transformer         #'identity
            treemacs-follow-after-init             t
            treemacs-git-command-pipe              ""
            treemacs-goto-tag-strategy             'refetch-index
            treemacs-indentation                   2
            treemacs-indentation-string            " "
            treemacs-is-never-other-window         nil
            treemacs-max-git-entries               5000
            treemacs-missing-project-action        'ask
            treemacs-no-png-images                 nil
            treemacs-no-delete-other-windows       t
            treemacs-project-follow-cleanup        nil
            treemacs-persist-file                  (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
            treemacs-position                      'left
            treemacs-recenter-distance             0.1
            treemacs-recenter-after-file-follow    nil
            treemacs-recenter-after-tag-follow     nil
            treemacs-recenter-after-project-jump   'always
            treemacs-recenter-after-project-expand 'on-distance
            treemacs-show-cursor                   nil
            treemacs-show-hidden-files             t
            treemacs-silent-filewatch              nil
            treemacs-silent-refresh                nil
            treemacs-sorting                       'alphabetic-asc
            treemacs-space-between-root-nodes      nil
            treemacs-tag-follow-cleanup            t
            treemacs-tag-follow-delay              1.5
            treemacs-width                         35)))

(use-package treemacs-projectile
  :after treemacs projectile)

(use-package treemacs-icons-dired
  :after treemacs dired
  :config (treemacs-icons-dired-mode))

(use-package treemacs-magit
  :after treemacs magit)

(use-package lsp-treemacs
  :after lsp
  :requires (lsp-mode treemacs)
  :commands lsp-treemacs-errors-list
  :config
    (lsp-treemacs-symbols t)
    (lsp-treemacs-references t)
    (lsp-treemacs-error-list t)
    (lsp-treemacs-sync-mode t))

(use-package lsp-ivy 
  :requires (ivy))

;; https://emacs-lsp.github.io/lsp-ui
(use-package lsp-ui
  :after lsp-mode
  ;;XXX :diminish
  ;;XXX :commands lsp-ui-mode
  :hook (lsp-mode . lsp-ui-mode)
  :bind (:map lsp-ui-mode-map
              ;;XXX ("C-c u" . lsp-ui-imenu)
              ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
              ([remap xref-find-references]  . lsp-ui-peek-find-references))
  :custom-face
    (lsp-ui-doc-background ((t (:background nil))))
    (lsp-ui-doc-header ((t (:inherit (font-lock-string-face italic)))))
  :init
    (setq lsp-ui-doc-enable t
          lsp-ui-doc-delay 4.0
          lsp-ui-doc-header t
          lsp-ui-doc-include-signature t
          lsp-ui-doc-max-height 25
          lsp-ui-doc-max-width 180
          lsp-ui-doc-position 'at-point
          lsp-ui-doc-show-with-cursor t
          lsp-ui-doc-show-with-mouse t
          lsp-ui-doc-use-childframe t
          lsp-ui-doc-use-webkit nil
          lsp-ui-doc-border (face-foreground 'default)
          lsp-ui-flycheck-enable t
          lsp-ui-flycheck-list-position 'right
          lsp-ui-flycheck-live-reporting t
          lsp-ui-imenu-enable t
          lsp-ui-imenu-kind-position 'right
          lsp-ui-imenu-window-width 30
          lsp-ui-imenu-auto-refresh t
          lsp-ui-imenu-refresh-delay 5.0
          lsp-ui-peek-always-show t
          lsp-ui-peek-enable t
          lsp-ui-peek-list-width 60
          lsp-ui-peek-peek-height 25
          lsp-ui-sideline-enable nil
          lsp-ui-sideline-code-actions-prefix ""
          lsp-ui-sideline-delay 4.0
          lsp-ui-sideline-ignore-duplicate t
          lsp-ui-sideline-show-code-actions t
          lsp-ui-sideline-show-diagnostics t
          lsp-ui-sideline-show-hover t
          lsp-ui-sideline-show-symbol t))

Support for Debugging Application Protocol

(use-package dap-mode
  :demand
  :after lsp-mode posframe
  :config
    (dap-auto-configure-mode)
    (add-hook 'dap-stopped-hook
      (lambda (arg) (call-interactively #'dap-hydra)))
  :hook
    (lsp-mode . dap-mode)
    (lsp-mode . dap-ui-mode))

Support for programming languages

C/C++/ObjectiveC

(use-package ccls :demand)

CSharp

(use-package csharp-mode :demand)

Clojure

(use-package clojure-mode :demand)

Elm

(use-package elm-mode :demand)

Fish

(use-package fish-mode :demand)

Groovy

(use-package groovy-mode :demand)

Haskell

(use-package haskell-mode :demand)
(use-package lsp-haskell
  :demand
  :requires (haskell-mode))

Java

(use-package lsp-java
  :demand
  :config
    (require 'dap-java)
  :after (lsp lsp-mode dap-mode jmi-init-platform-paths))

Ocaml

;;TODO: (use-package caml-mode :demand)

Python

We use lsp-mode and dap-mode to provide a more complete development environment for Python in Emacs. Check out the pyls configuration in the lsp-mode documentation for more details.

(use-package python-mode
  :ensure t
  :hook (python-mode . lsp-deferred)
  :custom
  ;; NOTE: Set these if Python 3 is called "python3" on your system!
  ;; (python-shell-interpreter "python3")
  ;; (dap-python-executable "python3")
  (dap-python-debugger 'debugpy)
  :config
  (require 'dap-python))

You can use the pyvenv package to use virtualenv environments in Emacs. The pyvenv-activate command should configure Emacs to cause lsp-mode and dap-mode to use the virtual environment when they are loaded, just select the path to your virtual environment before loading your project.

(use-package pyvenv
  :after python-mode
  :config
  (pyvenv-mode 1))

Ruby

;;(use-package enh-ruby-mode :demand)

Rust

(use-package rustic :demand)

Salt

(use-package salt-mode
  :demand
  :config
  :hook (salt-mode . (lambda () (flyspell-mode t))))
  ;;XXX (add-hook 'salt-mode-hook
  ;;XXX           (lambda ()
  ;;XXX             (flyspell-mode t))))

Scala

;; Enable scala-mode and sbt-mode
(use-package scala-mode
  :demand
  :requires (lsp)
  :interpreter
    ("scala" . scala-mode))

(use-package sbt-mode
  :demand
  :after scala-mode
  :commands sbt-start sbt-command
  :mode "\\.sbt\\'"
  :config
  ;; WORKAROUND: https://github.com/ensime/emacs-sbt-mode/issues/31
  ;; Allows using space when in the minibuffer
  (substitute-key-definition
    'minibuffer-complete-word
    'self-insert-command
     minibuffer-local-completion-map)
   ;; sbt-supershell kills sbt-mode:  https://github.com/hvesalai/emacs-sbt-mode/issues/152
   (setq sbt:program-options '("-Dsbt.supershell=false"))
  :bind (:map sbt-mode-map
              ("<space>"  . sbt-hydra)) ;; FIXME
)

(use-package company
  :hook
    (scala-mode . company-mode)
  :config
    (setq company-idle-delay 0)
    (setq company-minimum-prefix-length 1)
    (setq lsp-completion-provider :capf)
    (global-company-mode t))

;; Add metals backend for lsp-mode
(use-package lsp-metals
  :demand
  :after scala-mode
  :bind
  :bind
    ("s-k" . hydra-lsp-metals/body)
  :config (setq lsp-metals-treeview-show-when-views-received t))

Swift

;;(use-package swift-mode :demand)

TypeScript

This is a basic configuration for the TypeScript language so that .ts files activate typescript-mode when opened. We’re also adding a hook to typescript-mode-hook to call lsp-deferred so that we activate lsp-mode to get LSP features every time we edit TypeScript code.

(use-package typescript-mode
  :demand
  :mode "\\.ts\\'"
  :hook (typescript-mode . lsp-deferred)
  :config
  (setq typescript-indent-level 2))

VIM Script

;;(use-package vimrc-mode :demand)

VUE

;;(use-package vue-mode :demand)

WASM

;;TODO:  (straight-use-package
;;TODO:   `(wasm-mode :type git :host github :repo "devonsparks/wat-mode"
;;TODO:               :build nil :files ("wat-mode.el")
;;TODO:               :demand
;;TODO:               :mode ("\\.wasm\\'" . wasm-mode)
;;TODO:               :mode ("\\.wast\\'" . wasm-mode)
;;TODO:               :mode ("\\.wat\\'"  . wasm-mode)))

Data languages

Dhall

(use-package dhall-mode
  :demand
  :requires (lsp)
  :mode "\\.dhall$"
  :config
  (setq
    dhall-format-at-save t ;; FIXME: formatting option is hardcoded
    dhall-format-arguments (\` ("--ascii")) ;;FIXME: unicode syntax is hardcoded
    ;; header-line is obsoleted by lsp-mode
    dhall-use-header-line nil))

GraphQL

(use-package graphql-mode :demand)

JSON

(use-package json-mode :demand)

Terraform HCL

(use-package hcl-mode :demand)

YAML

(use-package yaml-mode :demand)

Markup languages

Markdown

(use-package markdown-mode
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :hook (markdown-mode . auto-fill-mode)
  :config (setq markdown-command "pandoc")) ;;FIXME: pandoc is hardcoded

HTML

(use-package sgml-mode
  :demand
  ;;XXX :hook (sgml-mode . lsp-deferred)
  ;;XXX :hook (html-mode . lsp-deferred)
  :mode ("\\.html\\'" . html-mode)
  :config (add-hook 'html-mode-hook 'turn-off-auto-fill))

Sphinx

(use-package sphinx-mode :demand)

Advanced syntax tree parsing

tree-sitter, an incremental parsing system.

It aims to be the foundation for a new breed of Emacs packages that understand code structurally. For example:

  • Faster, fine-grained code highlighting.
  • More flexible code folding.
  • Structural editing (like Paredit, or even better) for non-Lisp code.
  • More informative indexing for imenu.

The author of Tree-sitter articulated its merits a lot better in this StrangeLoop talk.

tree-sitter must be installed after all language modes were installed.
(use-package tree-sitter)
(use-package tree-sitter-langs)
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)

Source code management

magit: a powerful frontend for Git

(use-package magit
  :demand
  :init
    (progn
      (bind-key "C-x g" 'magit-status))
    (setq magit-status-margin '(t "%Y-%m-%d %H:%M " magit-log-margin-width t 18)))

(use-package git-timemachine
  :demand
  :requires (magit))

(use-package git-gutter
  :demand
  :requires (magit)
  :init
    (global-git-gutter-mode +1))

(use-package smerge-mode
  :demand
  :after hydra
  :config
    (defhydra unpackaged/smerge-hydra
      (:hint nil :post (smerge-auto-leave))
"
^Move^       ^Keep^               ^Diff^                 ^Other^
^^-----------^^-------------------^^---------------------^^-------
_n_ext       _b_ase               _<_: upper/base        _C_ombine
_p_rev       _u_pper              _=_: upper/lower       _r_esolve
^^           _l_ower              _>_: base/lower        _k_ill current
^^           _a_ll                _R_efine               _s_ave
^^           _RET_: current       _E_diff                _q_uit
"
    ("n" smerge-next)
    ("p" smerge-prev)
    ("b" smerge-keep-base)
    ("u" smerge-keep-upper)
    ("l" smerge-keep-lower)
    ("a" smerge-keep-all)
    ("RET" smerge-keep-current)
    ("<" smerge-diff-base-upper)
    ("=" smerge-diff-upper-lower)
    (">" smerge-diff-base-lower)
    ("R" smerge-refine)
    ("E" smerge-ediff)
    ("C" smerge-combine-with-next)
    ("r" smerge-resolve)
    ("k" smerge-kill-current)
    ("s" (lambda ()
            (interactive)
            (save-buffer)
            (bury-buffer))
     "Save and bury buffer")
    ("q" nil "cancel"))
  :hook (magit-diff-visit-file . (lambda ()
                                   (when smerge-mode
                                     (unpackaged/smerge-hydra/body)))))


;; (use-package forge :demand) ;;FIXME Does not work on Windoze

monky: a powerful frontend for Mercurial/Hg

(use-package monky
  :demand
  :diminish monky-status
  :commands monky-status
  :init (setq monky-process-type 'cmdserver)
  :bind ("M-s M-m" . monky-status))

find-file-in-repository find files in the source control

(use-package find-file-in-repository
  :diminish find-file-in-repository
  :commands find-file-in-repository
  :bind ("M-s M-f" . find-file-in-repository))

Org Mode modules

Install org-roam

Explaining video here: https://www.youtube.com/watch?v=AyhPmypHDEw

(if (eq system-type "gnu/linux")
  (defvar user-org-roam-directory "~/Documents/Emacs/RoamNotes"
    "Directory for OrgRoam notes")
  (if (not (file-directory-p user-org-roam-directory))(make-directory user-org-roam-directory))
  (if (not (file-directory-p (concat user-org-roam-directory "/daily")))(make-directory (concat user-org-roam-directory "/daily")))
  (use-package org-roam
    :demand
    :init (setq org-roam-v2-ack t)
    :custom
    (org-roam-directory user-org-roam-directory)
    (org-roam-completion-everywhere t)
    :bind (("C-c r l" . org-roam-buffer-toggle)
           ("C-c r f" . org-roam-node-find)
           ("C-c r i" . org-roam-node-insert)
           :map org-mode-map
           ("C-M-i"   . completion-at-point))

    :config (org-roam-setup))
)

Install org-roam-ui

(if (eq system-type "gnu/linux")
  (use-package org-roam-ui
    :straight
    (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
    :after org-roam
  ;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
  ;;         a hookable mode anymore, you're advised to pick something yourself
  ;;         if you don't care about startup time, use
  ;;  :hook (after-init . org-roam-ui-mode)
    :config
    (setq org-roam-ui-sync-theme t
          org-roam-ui-follow t
          org-roam-ui-update-on-save t
          org-roam-ui-open-on-start t))
)

Install org-roam-bibtex

(if (eq system-type "gnu/linux")
  (use-package org-ref)
  (use-package ivy-bibtex)
  (use-package org-roam-bibtex)
)

Install org-gtd

(defvar user-org-gtd-directory "~/Documents/Emacs/GTD"
  "Directory for org-gtd files")
(if (not (file-directory-p user-org-gtd-directory))(make-directory user-org-gtd-directory))
(use-package org-gtd
  :after org
  ;;:quelpa (org-gtd :fetcher github :repo "trevoke/org-gtd.el"
  ;;                 :branch "2.0.0" :upgrade t)
  :demand t
  :custom
  (org-gtd-directory user-org-gtd-directory)
  (org-edna-use-inheritance t)
  :config
  (org-edna-mode)
  :bind
  (("C-c d c" . org-gtd-capture)
   ("C-c d e" . org-gtd-engage)
   ("C-c d p" . org-gtd-process-inbox)
   ("C-c d n" . org-gtd-show-all-next)
   ("C-c d s" . org-gtd-show-stuck-projects)
   :map org-gtd-process-map
   ("C-c c" . org-gtd-choose)))

Install org-sidebar

(use-package org-sidebar)

Install org-auto-tangle

(use-package org-auto-tangle
  :hook (org-mode . org-auto-tangle-mode)
  :config
  (setq org-auto-tangle-default t))

Install org-gcal

(use-package org-gcal)

Install org-caldav

(use-package org-caldav)

Additional extensions

undo-tree: recovers any past state of a buffer

(use-package undo-tree
  :demand
  :diminish undo-tree-mode
  :config (global-undo-tree-mode)
  :bind ("s-/" . undo-tree-visualize))

move-dup: Eclipse-like move and duplicate lines

(use-package move-dup
  :demand
  :config (global-move-dup-mode)
  :bind (("S-M-<up>"     . move-dup-move-lines-up)
         ("S-M-<down>"   . move-dup-move-lines-down)
         ("C-M-<up>"     . move-dup-duplicate-up)
         ("C-M-<down>"   . move-dup-duplicate-down)))

highlight-symbol: highlight and navigate between symbols

(use-package highlight-symbol
  :diminish highlight-symbol-mode
  :commands highlight-symbol
  :bind ("s-h" . highlight-symbol))

goto-chg: goto last change in current buffer

(use-package goto-chg
  :demand
  :commands goto-last-change
  ;; complementary to
  ;; C-x r m / C-x r l
  ;; and C-<space> C-<space> / C-u C-<space>
  :bind (("C-." . goto-last-change)
         ("C-," . goto-last-change-reverse)))

multiple-cursors: edit multiple places of a buffer at once

(use-package multiple-cursors
  :demand
  :commands(edit-lines))

window-numbering: assign numbers to windows for quick access

(use-package window-numbering
  :init (window-numbering-mode 1))

expand-region: increase selected region by semantic units

(use-package expand-region
  :demand
  :bind ("C-=" . er/expand-region))

gist shares snippets and pastes

(use-package gist
  :demand
  :diminish gist-list
  :commands (gist-list gist-region-or-buffer)
  :bind (("M-s M-o" . gist-list)
	 ("M-s M-s" . gist-region-or-buffer)))

restclient: provides a REST REPL

(use-package restclient
  :demand
  :mode (("\\.http\\'" . restclient-mode)))

rg: ripgrep

(use-package rg
  :demand
  :init (rg-enable-default-bindings))

command-log-mode: display key bindings as you type

command-log-mode is useful for displaying a panel showing each key binding you use in a panel on the right side of the frame. Great for live streams and screencasts!

(use-package command-log-mode
  :commands command-log-mode)

editorconfig: Support for Editor Config

EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.

More info at:

(use-package editorconfig
  :config
  (editorconfig-mode 1))

Configure global settings and keybindings

; general defaults
(setq-default indent-tabs-mode nil)
;;(global-auto-complete-mode t)

;; CUA selection mode is handy for highlighting rectangular regions properly.
(cua-selection-mode t)

;; keybinding for multiple-cursors
(global-set-key (kbd "C-M-<return>") 'mc/edit-lines)
(global-set-key (kbd "C-` <right>")  'mc/mark-next-like-this)
(global-set-key (kbd "C-` <left>")   'mc/mark-previous-like-this)
(global-set-key (kbd "C-` <return>") 'mc/mark-all-like-this)
(global-set-key (kbd "C-` /")        'mc/mark-sgml-tag-pair)
(global-set-key (kbd "C-` <SPC>")    'mc/vertical-align-with-spaces)

;; editing very long lines... 
(global-set-key (kbd "C-|")  'toggle-truncate-lines)

;; reassign negative-argument
(global-set-key (kbd "C-_") 'negative-argument)

;; make sure we can increase and decrease font size
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "C-+") 'text-scale-increase)

;; display line numbers
(global-set-key (kbd "C-c n")   'display-line-numbers-mode)
(global-set-key (kbd "C-c C-n") 'global-display-line-numbers-mode)

;; ivy, swiper and counsel integration with standard commands
(ivy-mode 1)
(counsel-projectile-mode t)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(global-set-key (kbd "C-s") 'swiper-isearch)
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "M-y") 'counsel-yank-pop)
(global-set-key (kbd "C-x b") 'ivy-switch-buffer)
(global-set-key (kbd "C-c v") 'ivy-push-view)
(global-set-key (kbd "C-c V") 'ivy-pop-view)
;(global-set-key (kbd "<f1> f") 'counsel-describe-function)
;(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
;(global-set-key (kbd "<f1> l") 'counsel-find-library)
;(global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
;(global-set-key (kbd "<f2> u") 'counsel-unicode-char)
;(global-set-key (kbd "<f2> j") 'counsel-set-variable)

Additional custom functions

(defun move-region-to-file(start end filename)
  "function takes current region, and writes it to specified file"
  (interactive "r\nsSave region as file name: ")
  (write-region start end filename t)
  (kill-region start end))

(defun save-latest-defined-macro (name)
  "Save the last defined macro into file associated to variable macros-file"
  (interactive "SSave macro as file name: ")
  (kmacro-name-last-macro name)
  (find-file macros-file)      
  (goto-char (point-max))   
  (newline)                 
  (insert-kbd-macro name)   
  (newline)                 
  (switch-to-buffer nil))

(defun eval-region-or-sexp()
"Evaluates a region or an expression"
  (interactive)
  (if (region-active-p)
    (eval-region region-beginning region-end)
    (call-interactively #'eval-last-sexp)))
(global-set-key (kbd "C-x C-e") 'eval-region-or-sexp)

Epilogue

(message "Initialization complete.")

About

This is my .emacs.d folder

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published