This is my literate Emacs configuration file
The first part of the configuration is to prepare the package management. I am using use-package
as
the central tool to deal with configuration of the packages.
In this section, we are configuring the repositories and Emacs internal package management. The only specificity here is that the TLS algorithm is specific for 26.2.1.
(require 'package)
;;
(when (and (= emacs-major-version 26)
(= emacs-minor-version 2)
(= emacs-build-number 1))
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))
(setq package-enable-at-startup nil
package-check-signature nil
package-archives '(("GNU ELPA" . "https://elpa.gnu.org/packages/")
("MELPA" . "https://melpa.org/packages/")
("ORGMODE" . "http://orgmode.org/elpa/"))
package-archive-priorities '(("ORGMODE" . 15)
("MELPA" . 10)
("GNU ELPA" . 5))
package-check-signature nil)
(package-initialize)
The use-package macro allows you to isolate package configuration in your .emacs file in a way that is both performance-oriented and, well, tidy.
(when (not package-archive-contents)
(package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-install 'use-package))
By default all packages should be installed from package manager as that’s the usual path. This is equivalent to setting :ensure t on each call to use-package. To disable set :ensure nil (this is done automatically for any packages using :load-path so shouldn’t generally be needed).
(setq use-package-always-ensure t)
This section is dedicated to deal with backups. The main logic is to exclude some specific files (either because of they are sensitive, either because they are just results of a process). For the other ones, I want to have an easy way to navigate in it.
(defconst private-dir (expand-file-name "private" user-emacs-directory))
(defconst temp-dir (format "%s/cache" private-dir)
"Hostname-based elisp temp directories")
;; If you don’t want to clutter up your file tree with Emacs’ backup files, you can save them to the system’s “temp” directory:
;; Default Backup directory
(defvar backup-directory "~/.emacs.d/backups/")
(setq backup-directory-alist `((".*" . ,backup-directory)))
(when (not (file-exists-p backup-directory))
(make-directory backup-directory t))
;; Auto-save
(defvar auto-save-directory "~/.emacs.d/auto-save/")
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
(when (not (file-exists-p auto-save-directory))
(make-directory auto-save-directory t))
;; Core settings
;; UTF-8 please
(set-charset-priority 'unicode)
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top
(setq default-process-coding-system '(utf-8-unix . utf-8-unix))
;; Mouse scroll
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1) ((control) . nil))) ;; one line at a time
(setq scroll-conservatively 10000)
;; (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling
(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse
(setq scroll-step 1) ;; keyboard scroll one line at a time
;;Mac key mode
(setq ns-right-alternate-modifier nil)
Show full path of the buffer on the buffer’s title
(setq frame-title-format
(list (format "%s %%S: %%j " (system-name))
'(buffer-file-name "%f" (dired-directory dired-directory "%b"))))
Ignore ring bell
(setq ring-bell-function 'ignore)
Make the yes or no
prompts shorter.
(defalias 'yes-or-no-p 'y-or-n-p)
(use-package exec-path-from-shell
:ensure t
:init (exec-path-from-shell-initialize))
Material theme
(use-package material-theme
:defer t
:init
;; (load-theme 'material t)
)
(use-package doom-themes
:config
;; Global settings (defaults)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
(load-theme 'doom-dark+ t)
;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config)
;; Enable custom neotree theme (all-the-icons must be installed!)
;; (doom-themes-neotree-config)
;; or for treemacs users
;; (setq doom-themes-treemacs-theme "doom-colors") ; use the colorful treemacs theme
;; (doom-themes-treemacs-config)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config))
(use-package emojify
:hook (erc-mode . emojify-mode)
:commands emojify-mode)
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
Load a dashboard buffer when Emacs starts
(use-package all-the-icons)
(use-package dashboard
:config
(setq dashboard-items '((recents . 10)
(bookmarks . 5)
(projects . 5)))
(dashboard-setup-startup-hook))
(defgroup font-size nil
"Change font size.")
(defcustom font-size--default-size 16
"Default font size (default 16)."
:type 'number
:group 'font-size)
(defcustom font-size--current-size nil
"Current font size."
:type 'number
:group 'font-size)
(defun font-size--adjust-current (size)
"Adjust current font size."
(custom-set-variables '(font-size--current-size size))
(set-face-attribute 'default nil :height (* size 10)))
(defun font-size-decrease ()
"Decrease font size."
(interactive)
(font-size--adjust-current (- font-size--current-size 1))
(message "%dpt" font-size--current-size)
)
(defun font-size-increase ()
"Increase font size."
(interactive)
(font-size--adjust-current (+ font-size--current-size 1))
(message "%dpt" font-size--current-size)
)
(defun font-size-default ()
"Adjust default font size."
(interactive)
(font-size--adjust-current font-size--default-size)
(message "%dpt" font-size--current-size)
)
(defun font-size-change ()
"Change font size interactive."
(interactive)
(catch 'end-flag
(while t
(setq action
(read-key-sequence-vector (format "Change font size[%dpt] (+,-,0) "
font-size--current-size)))
(setq c (aref action 0))
(cond ((= c ?+)
(setq size (+ font-size--current-size 1)))
((= c ?-)
(setq size (- font-size--current-size 1)))
((= c ?0)
(setq size font-size--default-size))
(t
(message "Quit")
(throw 'end-flag t)))
(font-size--adjust-current size)
)))
(defun font-size-init (default-size)
"Initialize font-size module."
(custom-set-variables '(font-size--default-size default-size))
(font-size--adjust-current default-size))
(provide 'font-size)
Suggest next keys to me based on currently entered key combination.
(use-package which-key
:config
(which-key-mode))
(use-package windmove
:bind
("C-c <up>" . windmove-up)
("C-c <down>" . windmove-down)
("C-c <left>" . windmove-left)
("C-c <right>" . windmove-right))
Enhance the powerline
(use-package minions
:hook (doom-modeline-mode . minions-mode)
:custom
(minions-mode-line-lighter ""))
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1))
Opening recent files is always an easy and fast shortcut. Some files should be ignored though. That leads to this configuration
(use-package recentf
:config
(setq recentf-max-menu-items 100)
(setq recentf-save-file (recentf-expand-file-name "~/.emacs.d/private/cache/recentf"))
(recentf-mode 1))
Copy text with format to easily paste it in different applications
(use-package copy-as-format
:bind (:map mode-specific-map
:prefix-map copy-as-format-prefix-map
:prefix "w"
("w" . copy-as-format)
("g" . copy-as-format-github)
("h" . copy-as-format-hipchat-pidgin)
("j" . copy-as-format-jira)
("m" . copy-as-format-markdown)
("o" . copy-as-format-org-mode)
("r" . copy-as-format-rst)
("s" . copy-as-format-slack)
("v" . org-copy-visible))
:config
;; (setq copy-as-format-default "slack")
;; Define own format since pidgin doesn't allow to begin a message with `/code'
(defun copy-as-format--hipchat-pidgin (text _multiline)
(format "/say /code %s" text))
(add-to-list 'copy-as-format-format-alist '("hipchat-pidgin" copy-as-format--hipchat-pidgin))
(defun copy-as-format-hipchat-pidgin ()
(interactive)
(setq copy-as-format-default "hipchat-pidgin")
(copy-as-format)))
This part focuses on completion configuration. Language specific configurations are not done here but in the dedicate language configuration part. This section is just for global configuration.
(use-package helm
:bind (("M-x" . helm-M-x)
("C-x C-m" . helm-M-x)
("C-x C-f" . helm-find-files)
("C-x C-d" . helm-browse-project)
("C-x v" . helm-projectile)
("C-s" . helm-occur)
("C-r" . helm-occur)
("C-x c p" . helm-projectile-ag)
("C-x c k" . helm-show-kill-ring)
("C-x f" . helm-recentf)
("C-SPC" . helm-dabbrev)
("M-y" . helm-show-kill-ring)
("C-x b" . helm-buffers-list)
:map helm-map
("<tab>" . helm-execute-persistent-action))
:config
;; open helm buffer inside current window, don't occupy the entire other window
(setq helm-split-window-in-side-p t)
(setq helm-recentf-fuzzy-match t
helm-locate-fuzzy-match nil ;; locate fuzzy is worthless
helm-M-x-fuzzy-match t
helm-buffers-fuzzy-matching t
helm-semantic-fuzzy-match t
helm-apropos-fuzzy-match t
helm-imenu-fuzzy-match t
helm-lisp-fuzzy-completion t
helm-completion-in-region-fuzzy-match t)
)
In order to have inline completion, really important for coding, I use company. However I adapted some facing attributes. Each language is also adding its backend when needed. Therefore, only global configuration here.
(use-package company
:config
;; Global
(setq company-idle-delay 1
company-minimum-prefix-length 1
company-show-numbers t
company-tooltip-limit 20)
;; Facing
(unless (face-attribute 'company-tooltip :background)
(set-face-attribute 'company-tooltip nil :background "black" :foreground "gray40")
(set-face-attribute 'company-tooltip-selection nil :inherit 'company-tooltip :background "gray15")
(set-face-attribute 'company-preview nil :background "black")
(set-face-attribute 'company-preview-common nil :inherit 'company-preview :foreground "gray40")
(set-face-attribute 'company-scrollbar-bg nil :inherit 'company-tooltip :background "gray20")
(set-face-attribute 'company-scrollbar-fg nil :background "gray40"))
;; Activating globally
(global-company-mode t))
;; Add yasnippet support for all company backends
;; https://github.com/syl20bnr/spacemacs/pull/179
(defvar company-mode/enable-yas t
"Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
(if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
backend
(append (if (consp backend) backend (list backend))
'(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(use-package rainbow-delimiters
:config
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
(delete-selection-mode 1)
(defun duplicate-current-line-or-region (arg)
"Duplicates the current line or region ARG times.
If there's no region, the current line will be duplicated. However, if
there's a region, all lines that region covers will be duplicated."
(interactive "p")
(let (beg end (origin (point)))
(if (and mark-active (> (point) (mark)))
(exchange-point-and-mark))
(setq beg (line-beginning-position))
(if mark-active
(exchange-point-and-mark))
(setq end (line-end-position))
(let ((region (buffer-substring-no-properties beg end)))
(dotimes (i arg)
(goto-char end)
(newline)
(insert region)
(setq end (point)))
(goto-char (+ origin (* (length region) arg) arg)))))
(global-set-key (kbd "C-c d") 'duplicate-current-line-or-region)
(use-package undo-tree
:config
;; Remember undo history
(setq
undo-tree-auto-save-history t
undo-tree-history-directory-alist `(("." . ,(concat temp-dir "/undo/"))))
(global-undo-tree-mode 1))
(global-set-key (kbd "C-z") 'undo)
;; make ctrl-Z redo
(defalias 'redo 'undo-tree-redo)
(global-set-key (kbd "C-S-z") 'redo)
(global-set-key (kbd "M-TAB") 'helm-recentf)
(global-set-key (kbd "M-TAB") 'helm-recentf)
(line-number-mode t)
(global-display-line-numbers-mode t)
(column-number-mode t)
(setq-default fill-column 120)
(column-number-mode t)
(use-package multiple-cursors
:bind
("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C->" . mc/mark-all-like-this))
Minor mode for Emacs that deals with parens pairs and tries to be smart about it.
(use-package smartparens)
(use-package smex)
(use-package move-text
:bind (([(meta shift up)] . move-text-up)
([(meta shift down)] . move-text-down)))
(defun json-to-single-line (beg end)
"Collapse prettified json in region between BEG and END to a single line"
(interactive "r")
(if (use-region-p)
(save-excursion
(save-restriction
(narrow-to-region beg end)
(goto-char (point-min))
(while (re-search-forward "[[:space:]\n]+" nil t)
(replace-match " "))))
(print "This function operates on a region")))
(use-package yasnippet
:config
;; Adding yasnippet support to company
(eval-after-load 'company
'(lambda ()
(add-to-list 'company-backends 'company-yasnippet)))
(yas-global-mode 1))
(use-package yasnippet-snippets)
(use-package restclient)
(use-package restclient-helm
:disabled t
:after (restclient helm))
A Docker client for emacs
(use-package docker)
;; Dockerfile file major mode
(use-package dockerfile-mode
:mode ("Dockerfile\\'" . dockerfile-mode)
:config
(setq-default indent-tabs-mode nil))
A Kubernetes client for emacs
(use-package kubernetes
:ensure t
:commands (kubernetes-overview))
;; kubernetes file major mode
(use-package k8s-mode
:ensure t
:hook (k8s-mode . yas-minor-mode))
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))
(use-package yaml-mode
:mode ("\\.ya?ml\\'" . yaml-mode)
:init
(add-hook 'yaml-mode-hook 'flycheck-mode))
(use-package flycheck-yamllint
:ensure t
:after yaml-mode
:commands (yaml-mode)
:init
(add-hook 'flycheck-mode-hook 'flycheck-yamllint-setup))
Use flychek on for sintax checking on Javascriprt
(use-package flycheck)
(use-package web-mode
:bind (("C-c ]" . emmet-next-edit-point)
("C-c [" . emmet-prev-edit-point)
("C-c o b" . browse-url-of-file))
:mode
(("\\.html?\\'" . web-mode)
("\\.phtml?\\'" . web-mode)
("\\.tpl\\.php\\'" . web-mode)
("\\.[agj]sp\\'" . web-mode)
("\\.as[cp]x\\'" . web-mode)
("\\.erb\\'" . web-mode)
("\\.mustache\\'" . web-mode)
("\\.djhtml\\'" . web-mode)
("\\.handlebars\\'" . web-mode))
:config
(setq web-mode-markup-indent-offset 4
web-mode-css-indent-offset 4
web-mode-code-indent-offset 4)
(progn (setq web-mode-engines-alist
'(("handlebars" . "\\.handlebars\\'")
("mako" . "\\.html?\\'"))
))
(add-hook 'web-mode-hook 'jsx-flycheck)
;; highlight enclosing tags of the element under cursor
(setq web-mode-enable-current-element-highlight t)
(defadvice web-mode-highlight-part (around tweak-jsx activate)
(if (equal web-mode-content-type "jsx")
(let ((web-mode-enable-part-face nil))
ad-do-it)
ad-do-it))
(defun jsx-flycheck ()
(when (equal web-mode-content-type "jsx")
;; enable flycheck
(flycheck-select-checker 'jsxhint-checker)
(flycheck-mode)))
;; editing enhancements for web-mode
;; https://github.com/jtkDvlp/web-mode-edit-element
(use-package web-mode-edit-element
:config (add-hook 'web-mode-hook 'web-mode-edit-element-minor-mode))
;; snippets for HTML
;; https://github.com/smihica/emmet-mode
(use-package emmet-mode
:init (setq emmet-move-cursor-between-quotes t) ;; default nil
:diminish (emmet-mode . " e"))
(defun my-web-mode-hook ()
"Hook for `web-mode' config for company-backends."
(set (make-local-variable 'company-backends)
'((company-tern company-css company-web-html company-files))))
(add-hook 'web-mode-hook 'my-web-mode-hook)
;; Enable JavaScript completion between <script>...</script> etc.
(defadvice company-tern (before web-mode-set-up-ac-sources activate)
"Set `tern-mode' based on current language before running company-tern."
(message "advice")
(if (equal major-mode 'web-mode)
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (or (string= web-mode-cur-language "javascript")
(string= web-mode-cur-language "jsx"))
(unless tern-mode (tern-mode))
(if tern-mode (tern-mode -1))))))
(add-hook 'web-mode-hook 'company-mode)
;; to get completion data for angularJS
(use-package ac-html-angular :defer t)
;; to get completion for twitter bootstrap
(use-package ac-html-bootstrap :defer t)
;; to get completion for HTML stuff
;; https://github.com/osv/company-web
(use-package company-web)
(add-hook 'web-mode-hook 'company-mode))
;; configure CSS mode company backends
(use-package css-mode
:config
(defun my-css-mode-hook ()
(set (make-local-variable 'company-backends)
'((company-css company-dabbrev-code company-files))))
(add-hook 'css-mode-hook 'my-css-mode-hook)
(add-hook 'css-mode-hook 'company-mode))
I use elpy plugin for python
(use-package pyenv-mode
:ensure t
:after python
:config
(defun projectile-pyenv-mode-set ()
"Set pyenv version matching project name."
(let ((project (projectile-project-name)))
(if (member project (pyenv-mode-versions))
(pyenv-mode-set project)
(pyenv-mode-unset))))
(when (executable-find "pyenv")
(add-to-list 'exec-path (expand-file-name "shims" (or (getenv "PYENV_ROOT") "~/.pyenv"))))
:hook((python-mode)
(projectile-switch-project . projectile-pyenv-mode-set)))
;; (use-package python
;; :mode ("\\.py" . python-mode)
;; :config
;; (use-package elpy
;; :init
;; (add-to-list 'auto-mode-alist '("\\.py$" . python-mode))
;; :config
;; (setenv "IPY_TEST_SIMPLE_PROMPT" "1")
;; (setq elpy-rpc-backend "jedi")
;; (setq elpy-rpc-python-command "python3")
;; (setq python-shell-interpreter "python3")
;; (setq python-shell-interpreter "ipython3"
;; python-shell-interpreter-args "-i")
;; (add-to-list 'company-backends 'company-jedi)
;; ;; (add-hook 'python-mode-hook
;; ;; (lambda ()
;; ;; (set (make-local-variable 'company-backends)
;; ;; '((company-anaconda company-dabbrev-code company-yasnippet)))))
;; ;; (add-hook 'python-mode-hook #'lsp)
;; ;; use flymake on emacs 26.1
;; ;; use flycheck not flymake with elpy
;; ;; (when (require 'flycheck nil t)
;; ;; (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
;; ;; (add-hook 'elpy-mode-hook 'flycheck-mode))
;; ;; (setq python-shell-interpreter "jupyter"
;; ;; python-shell-interpreter-args "console --simple-prompt"
;; ;; python-shell-prompt-detect-failure-warning nil)
;; ;; (add-to-list 'python-shell-completion-native-disabled-interpreters
;; ;; "jupyter")
;; ;; (add-hook 'python-mode-hook 'py-autopep8-enable-on-save)
;; ;;flycheck-python-flake8-executable "/usr/local/bin/flake8"
;; :bind (:map elpy-mode-map
;; ("M-." . elpy-goto-definition)
;; ("M-," . pop-tag-mark)))
;; (elpy-enable))
add support for mypy on flymake
(require 'flymake)
(defun flymake-mypy-init ()
"Init mypy."
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(list "mypy" (list local-file "-s"))))
(when (load "flymake" t)
(add-to-list 'flymake-allowed-file-name-masks '("\\.py\\'" flymake-mypy-init)))
Sort imports plugins
(use-package py-isort
:config
(add-hook 'before-save-hook 'py-isort-before-save))
Use rjsx-mode over js2-mode
;; (use-package indium)
(use-package rjsx-mode)
(use-package js2-mode
:bind (:map js2-mode-map
(("C-x C-e" . js-send-last-sexp)
("C-M-x" . js-send-last-sexp-and-go)
("C-c C-b" . js-send-buffer-and-go)
("C-c C-l" . js-load-file-and-go)))
:mode
("\\.js$" . rjsx-mode)
:config
(custom-set-variables '(js2-strict-inconsistent-return-warning nil))
(custom-set-variables '(js2-strict-missing-semi-warning nil))
;; (require 'indium)
;; (add-hook 'js-mode-hook #'indium-interaction-mode)
(require 'flycheck)
;; (require 'find-local-executable)
(setq js-indent-level 2)
(setq js2-indent-level 2)
(setq js2-basic-offset 2)
(setq sgml-basic-offset 2)
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers
'(javascript-jshint)))
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers
'(json-jsonlist)))
(add-hook 'js2-mode-hook 'flycheck-mode)
;; use eslint with web-mode for jsx files
(flycheck-add-mode 'javascript-eslint 'js2-mode)
;; customize flycheck temp file prefix
(setq-default flycheck-temp-prefix ".flycheck")
;; disable json-jsonlist checking for json files
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
;; (find-local-executable-nodejs-setup-eslint)
;; tern :- IDE like features for javascript and completion
;; http://ternjs.net/doc/manual.html#emacs
(use-package tern
:config
(defun my-js-mode-hook ()
"Hook for `js-mode'."
(set (make-local-variable 'company-backends)
'((company-tern company-files))))
(add-hook 'js2-mode-hook 'my-js-mode-hook)
(add-hook 'js2-mode-hook 'company-mode))
(add-hook 'js2-mode-hook 'tern-mode)
(add-hook 'js2-mode-hook 'whitespace-mode)
(setq whitespace-line-column 121)
;; company backend for tern
;; http://ternjs.net/doc/manual.html#emacs
;; (use-package company-tern)
;; Run a JavaScript interpreter in an inferior process window
;; https://github.com/redguardtoo/js-comint
(use-package js-comint
:config
(setq inferior-js-program-command "node"))
;; js2-refactor :- refactoring options for emacs
;; https://github.com/magnars/js2-refactor.el
(use-package js2-refactor
:diminish js2-refactor-mode
:config
(js2r-add-keybindings-with-prefix "C-c j r"))
(add-hook 'js2-mode-hook 'js2-refactor-mode))
(use-package typescript-mode
:mode "\\.tsx\\'"
:hook (typescript-mode . lsp-deferred)
)
;; (defun setup-tide-mode ()
;; (interactive)
;; (tide-setup)
;; (flycheck-mode +1)
;; (setq flycheck-check-syntax-automatically '(save mode-enabled))
;; (eldoc-mode +1)
;; (tide-hl-identifier-mode +1)
;; ;; company is an optional dependency. You have to
;; ;; install it separately via package-install
;; ;; `M-x package-install [ret] company`
;; (company-mode +1))
;; ;; aligns annotation to the right hand side
;; (setq company-tooltip-align-annotations t)
;; ;; formats the buffer before saving
;; ;; (add-hook 'before-save-hook 'tide-format-before-save)
;; (add-hook 'typescript-mode-hook #'setup-tide-mode)
;; (add-hook 'rjsx-mode-hook #'setup-tide-mode)
;; (add-hook 'typescript-mode-hook 'prettier-js-mode)
;; (add-hook 'typescript-mode-local-vars-hook (lambda ()
;; (flycheck-add-next-checker 'typescript-tide 'javascript-eslint 'append)))
;; (add-hook 'typescript-mode-local-vars-hook (lambda ()
;; (flycheck-add-next-checker 'tsx-tide 'javascript-eslint 'append)))
;; (defun my/use-eslint-from-node-modules ()
;; (let* ((root (locate-dominating-file
;; (or (buffer-file-name) default-directory)
;; "node_modules"))
;; (eslint
;; (and root
;; (expand-file-name "node_modules/.bin/eslint"
;; root))))
;; (when (and eslint (file-executable-p eslint))
;; (setq-local flycheck-javascript-eslint-executable eslint))))
;; (add-hook 'flycheck-mode-hook #'my/use-eslint-from-node-modules)
;; (use-package tide
;; :ensure t
;; :after (typescript-mode company flycheck)
;; :hook ((typescript-mode . tide-setup)
;; (typescript-mode . tide-hl-identifier-mode)
;; ;; (before-save . tide-format-before-save)
;; ))
;; (require 'web-mode)
;; (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode))
;; (add-hook 'web-mode-hook
;; (lambda ()
;; (when (string-equal "tsx" (file-name-extension buffer-file-name))
;; (setup-tide-mode))))
;; ;; enable typescript-tslint checker
;; (flycheck-add-mode 'typescript-tslint 'web-mode)
(use-package csv-mode
:config (setq-default csv-align-padding 2))
(use-package lsp-mode
:ensure t
:commands (lsp lsp-deferred)
:hook (
(lsp-mode . lsp-enable-which-key-integration)
;; (python-mode . lsp-deferred)
(c-mode . lsp-deferred)
(go-mode . lsp-deferred)
(java-mode . lsp-deferred)
(js-mode . lsp-deferred)
(json-mode . lsp-deferred)
(ts-mode . lsp-deferred)
(web-mode . lsp-deferred)
(vue-mode . lsp-deferred)
(html-mode . lsp-deferred))
:init (progn
;; (setq lsp-keymap-prefix "M-RET")
(setq lsp-headerline-breadcrumb-enable t
gc-cons-threshold (* 100 1024 1024)
read-process-output-max (* 1024 1024)
company-idle-delay 0.0
company-minimum-prefix-length 1
create-lockfiles nil ;; lock files will kill `npm start'
lsp-enable-symbol-highlighting t
lsp-enable-snippet nil ;; Not supported by company capf, which is the recommended company backend
)
(setq lsp-completion-enable t)
(setq lsp-enable-indentation t)
(setq lsp-before-save-edits t)
(setq lsp-signature-render-documentation nil)
(setq lsp-pyls-configuration-sources ["flake8"])
(setq lsp-pyls-plugins-pycodestyle-enabled nil)
(setq lsp-pyls-plugins-flake8-enabled t)
;; (setq lsp-pyls-plugins-flake8-config "~/.config/flake8")
(setq lsp-pyls-plugins-pylint-enabled nil)
(setq lsp-pyls-plugins-pydocstyle-enabled nil)
(setq lsp-pylsp-plugins-autopep8-enabled t)
(setq lsp-pyls-server-command "pylsp")
)
:config
(lsp-register-custom-settings
'(
;; ("pylsp.configurationSources" '("flake8"))
("pylsp.plugins.pyls_mypy.enabled" t t)
("pylsp.plugins.pyls_mypy.live_mode" nil t)
("pylsp.plugins.pyls_isort.enabled" t t)
("pylsp.plugins.pyls_black.enabled" nil t)
("pylsp.plugins.pycodestyle.enabled" nil t)
("pylsp.plugins.pydocstyle.enabled" nil t)
("pylsp.plugins.autopep8.enabled" t t)
("pylsp.plugins.pylint.enabled" nil t)
("pylsp.plugins.flake8.enabled" t t)))
;; (setq lsp-clients-elixir-server-executable "/home/maki/Downloads/elixir-ls/language_server.sh")
;; ("pylsp.plugins.flake8.config" "~/.config/flake8")
(setq lsp-eldoc-hook nil)
;; Ignore setting up watches on gitignored paths
;; https://github.com/emacs-lsp/lsp-mode/issues/713#issuecomment-985653873
(defun ++git-ignore-p (path)
(let* (; trailing / breaks git check-ignore if path is a symlink:
(path (directory-file-name path))
(default-directory (file-name-directory path))
(relpath (file-name-nondirectory path))
(cmd (format "git check-ignore '%s'" relpath))
(status (call-process-shell-command cmd)))
(eq status 0)))
(defun ++lsp--path-is-watchable-directory-a
(fn path dir ignored-directories)
(and (not (++git-ignore-p (f-join dir path)))
(funcall fn path dir ignored-directories)))
(advice-add 'lsp--path-is-watchable-directory
:around #'++lsp--path-is-watchable-directory-a))
(use-package lsp-treemacs
:commands lsp-treemacs-errors-list)
(use-package helm-lsp
:commands helm-lsp-workspace-symbol)
(use-package lsp-pyright
:ensure t
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp-deferred))) ; or lsp-deferred
:init (when (executable-find "python3")
(setq lsp-pyright-python-executable-cmd "python3"))
:custom
(lsp-intelephense-multi-root nil)
(lsp-pyright-multi-root nil)
:config
(defun expand-absolute-name (name)
(if (file-name-absolute-p name)
(tramp-file-local-name
(expand-file-name
(concat (file-remote-p default-directory) name)))
name))
(lsp-register-custom-settings
`(("python.analysis.stubPath" (lambda () (expand-absolute-name lsp-pyright-stub-path)))
("python.venvPath" (lambda () (if lsp-pyright-venv-path
(expand-absolute-name lsp-pyright-venv-path) ""))))))
;; Set up before-save hooks to format buffer and add/delete imports.
;; Make sure you don't have other gofmt/goimports hooks enabled.
(defun lsp-go-install-save-hooks ()
(add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
;; Optional - provides fancier overlays.
(use-package lsp-ui
:after lsp-mode
:commands lsp-ui-mode
:hook (lsp-mode . lsp-ui-mode)
:init (setq lsp-ui-doc-enable t
lsp-ui-doc-use-webkit nil
lsp-ui-doc-delay .3
lsp-ui-doc-include-signature t
lsp-ui-doc-position 'bottom ;; top/bottom/at-point
lsp-eldoc-enable-hover nil ;; Disable eldoc displays in minibuffer
lsp-ui-sideline-enable t
lsp-ui-sideline-diagnostic-max-lines 3
lsp-ui-sideline-show-hover t
lsp-ui-sideline-show-code-actions t
lsp-ui-sideline-show-diagnostics t
lsp-ui-sideline-ignore-duplicate t
lsp-headerline-breadcrumb-enable t)
:bind (:map lsp-ui-mode-map
([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
([remap xref-find-references] . lsp-ui-peek-find-references))
:config
(setq lsp-ui-flycheck-enable t)
(treemacs-resize-icons 14))
(setq lsp-gopls-staticcheck t)
(setq lsp-eldoc-render-all t)
(setq lsp-gopls-complete-unimported t)
(use-package lsp-grammarly
:ensure t
:hook (text-mode . (lambda ()
(require 'lsp-grammarly)
(lsp)))) ; or lsp-deferred
(use-package terraform-mode
:ensure t
:defer t
:mode (
("\\.tf\\'" . terraform-mode)
)
:config
(add-hook 'terraform-mode-hook
(lambda () (add-hook 'before-save-hook #'terraform-format-buffer))))
(use-package lsp-java :config (add-hook 'java-mode-hook 'lsp))
(use-package dap-mode :after lsp-mode :config (dap-auto-configure-mode))
(use-package dap-java :ensure nil)
(use-package go-mode)
;; C-IDE based on https://github.com/tuhdo/emacs-c-ide-demo
(use-package cc-mode
:config
;; Available C style:
;; "gnu": The default style for GNU projects
;; "k&r": What Kernighan and Ritchie, the authors of C used in their book
;; "bsd": What BSD developers use, aka "Allman style" after Eric Allman.
;; "whitesmith": Popularized by the examples that came with Whitesmiths C, an early commercial C compiler.
;; "stroustrup": What Stroustrup, the author of C++ used in his book
;; "ellemtel": Popular C++ coding standards as defined by "Programming in C++, Rules and Recommendations," Erik Nyquist and Mats Henricson, Ellemtel
;; "linux": What the Linux developers use for kernel development
;; "python": What Python developers use for extension modules
;; "java": The default style for java-mode (see below)
;; "user": When you want to define your own style
(setq c-default-style "gnu") ;; set style to "linux"
(setq gdb-many-windows t ;; use gdb-many-windows by default
gdb-show-main t
c-basic-offset 4
tab-width 4
indent-tabs-mode t))
(use-package cmake-ide
:config
(add-hook 'c++-mode-hook '(lambda()
(cmake-ide-setup))))
;; (use-package semantic
;; :config
;; (semanticdb-enable-gnu-global-databases 'c-mode t)
;; (semanticdb-enable-gnu-global-databases 'c++-mode t)
;; (defun my-inhibit-semantic-p ()
;; (not (equal major-mode 'python-mode)))
;; (add-to-list 'semantic-inhibit-functions #'my-inhibit-semantic-p)
;; (setq semanticdb-default-save-directory (expand-file-name "semanticdb/" temp-dir))
;; (let ((semantic-submodes '(global-semantic-decoration-mode
;; global-semantic-idle-local-symbol-highlight-mode
;; global-semantic-highlight-func-mode
;; global-semanticdb-minor-mode
;; global-semantic-mru-bookmark-mode
;; global-semantic-idle-summary-mode
;; global-semantic-stickyfunc-mode
;; )))
;; (setq semantic-default-submodes (append semantic-default-submodes semantic-submodes)
;; semantic-idle-scheduler-idle-time 1))
;; (add-hook 'c-mode-common-hook (lambda () (semantic-mode 1))))
(use-package irony
:config
;; replace the `completion-at-point' and `complete-symbol' bindings in
;; irony-mode's buffers by irony-mode's function
(add-hook 'c++-mode-hook 'irony-mode)
(add-hook 'c-mode-hook 'irony-mode)
(add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options))
(use-package irony-eldoc
:config
(add-hook 'irony-mode-hook 'irony-eldoc))
(use-package company-irony
:config
(add-to-list 'company-backends 'company-keywords)
(add-to-list 'company-backends 'company-irony))
(use-package company-irony-c-headers
:config
(add-to-list 'company-backends 'company-irony-c-headers))
(use-package flycheck-irony
:after flycheck-mode
:config
(add-hook 'flycheck-mode-hook #'flycheck-irony-setup))
;; company-c-headers
(use-package company-c-headers
:config
(add-to-list 'company-backends 'company-c-headers))
(defun me/rtags ()
"Rtags configuration. Used only for nevigation."
(interactive)
(rtags-start-process-unless-running)
(setq rtags-display-result-backend 'ivy)
(add-hook 'kill-emacs-hook 'rtags-quit-rdm))
;; (use-package rtags
;; :commands rtags-start-process-unless-running
;; :bind (:map cc-mode-map
;; ("M-." . rtags-find-symbol-at-point)
;; ("M-?" . rtags-find-references-at-point)
;; ("M-," . rtags-location-stack-back)
;; ("C-," . rtags-location-stack-forward)
;; ("C-c r r" . rtags-rename-symbolrtags-next-match))
;; :config
;; (setq rtags-completions-enabled t)
;; (add-hook 'c++-mode 'me/rtags)
;; (add-hook 'c-mode 'me/rtags)
;; (message "Rtags loaded"))
;; (use-package company-rtags
;; :after rtags
;; :config
;; (add-to-list 'company-backends 'company-rtags))
(use-package lua-mode)
(use-package magit
:config
;; (setq magit-completing-read-function 'ivy-completing-read)
:bind
;; Magic
("C-x g s" . magit-status)
("C-x g x" . magit-checkout)
("C-x g c" . magit-commit)
("C-x g p" . magit-push)
("C-x g u" . magit-pull)
("C-x g e" . magit-ediff-resolve)
("C-x g r" . magit-rebase-interactive)
("C-x g l" . magit-log))
(use-package magit-popup)
;; (use-package gitignore-mode)
;; (use-package helm-gitignore)
Highlights uncommitted changes on the left side of the window, allows you to jump between and revert them selectively.
(use-package diff-hl
:config
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)
(global-diff-hl-mode))
(use-package projectile
:config
(setq projectile-known-projects-file
(expand-file-name "projectile-bookmarks.eld" temp-dir))
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(setq projectile-completion-system 'helm)
(setq projectile-switch-project-action (lambda (&optional arg) (helm-browse-project arg)))
(projectile-global-mode))
Helm Projectile
(use-package helm-projectile
:config
(helm-projectile-on)
(setq helm-projectile-fuzzy-match nil)
)
A file tree for projects
(use-package treemacs
:ensure t
:defer t
:init
(with-eval-after-load 'winum
(define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
:config
(progn
(setq treemacs-collapse-dirs (if treemacs-python-executable 3 0)
treemacs-deferred-git-apply-delay 0.5
treemacs-display-in-side-window t
treemacs-eldoc-display t
treemacs-file-event-delay 5000
treemacs-file-follow-delay 0.2
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-desc
treemacs-space-between-root-nodes t
treemacs-tag-follow-cleanup t
treemacs-tag-follow-delay 1.5
treemacs-width 35)
;; The default width and height of the icons is 22 pixels. If you are
;; using a Hi-DPI display, uncomment this to double the icon size.
;;(treemacs-resize-icons 44)
(treemacs-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-fringe-indicator-mode t)
(pcase (cons (not (null (executable-find "git")))
(not (null treemacs-python-executable)))
(`(t . t)
(treemacs-git-mode 'deferred))
(`(t . _)
(treemacs-git-mode 'simple))))
:bind
(:map global-map
("M-0" . treemacs-select-window)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t t" . treemacs)
("C-x t B" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag)))
Integrate it with projectile
(use-package treemacs-projectile
:after treemacs projectile)
Integrate it with magit
(use-package treemacs-magit
:after treemacs magit)
Allows you to use treemacs icons in dired buffers with treemacs-icons-dired-mode
(use-package treemacs-icons-dired
:after treemacs dired
:config (treemacs-icons-dired-mode))
Use ripgrep to search text in folders/projects, I’m replacing the ag command in the helm-ag package since it has better support than helm-rg
(use-package helm-ag
:config
(setq helm-ag-base-command "rg --no-heading")
(bind-key* "C-c p s r" 'helm-do-ag-project-root)
(bind-key* "C-c p s d" 'helm-do-ag)
)
This package provides an excelent browser to search files in a project M-x helm-browse-project
or C-x C-d
(use-package helm-ls-git)
I use wgrep mode to edit multiple files at once when searching
(use-package wgrep)
Engine mode provide shortcuts to search in diferents search engines like google, github etc
(use-package engine-mode
:init
(engine-mode t)
(engine/set-keymap-prefix (kbd "C-c s"))
:config
(defengine github-eventbrite
"https://github.com/search?l=Python&q=org:eventbrite+%s&type=Code"
:keybinding "e")
(defengine docs-eventbrite
"https://docsearch.evbhome.com/?q=%s"
:keybinding "d")
(defengine github
"https://github.com/search?ref=simplesearch&q=%s"
:keybinding "h")
(defengine stackoverflow
"https://stackoverflow.com/search?q=%s"
:keybinding "s")
(defengine google
"https://www.google.com/search?q=%s"
:keybinding "g"))
Set up Org Mode with a baseline configuration. The following sections will add more things to it.
(use-package ob-restclient)
(use-package ox-rst)
(use-package htmlize)
(global-set-key (kbd "C-c c")
'org-capture)
(setq org-agenda-files (list "~/Dropbox/orgfiles/gcal.org"
"~/Dropbox/orgfiles/i.org"
"~/Dropbox/orgfiles/schedule.org"))
(setq org-capture-templates
'(("a" "Appointment" entry (file "~/Dropbox/orgfiles/gcal.org" "Appointments")
"* TODO %?\n:PROPERTIES:\n\n:END:\nDEADLINE: %^T \n %i\n")
("n" "Note" entry (file+headline "~/Dropbox/orgfiles/notes.org" "Notes")
"* Note %?\n%T")
("l" "Link" entry (file+headline "~/Dropbox/orgfiles/links.org" "Links")
"* %? %^L %^g \n%T" :prepend t)
("b" "Blog idea" entry (file+headline "~/Dropbox/orgfiles/i.org" "Blog Topics:")
"* %?\n%T" :prepend t)
("t" "To Do Item" entry (file+headline "~/Dropbox/orgfiles/i.org" "To Do Items")
"* %?\n%T" :prepend t)
("j" "Journal" entry (file+datetree "~/Dropbox/journal.org")
"* %?\nEntered on %U\n %i\n %a")
("s" "Screencast" entry (file "~/Dropbox/orgfiles/screencastnotes.org")
"* %?\n%i\n")))
(setq org-ditaa-jar-path "~/git/org-mode/contrib/scripts/ditaa.jar")
(setq org-plantuml-jar-path "~/ownCloud/plantuml.jar")
(setq org-log-done 'time)
(add-hook 'org-babel-after-execute-hook 'bh/display-inline-images 'append)
; Make babel results blocks lowercase
(setq org-babel-results-keyword "results")
(defun bh/display-inline-images ()
(condition-case nil
(org-display-inline-images)
(error nil)))
(org-babel-do-load-languages
(quote org-babel-load-languages)
(quote ((emacs-lisp . t)
(dot . t)
(sql . t)
(shell . t)
(python . t)
(org . t)
(plantuml . t)
(restclient . t)
(latex . t))))
; Do not prompt to confirm evaluation
; This may be dangerous - make sure you understand the consequences
; of setting this -- see the docstring for details
(setq org-confirm-babel-evaluate nil)
;; Use fundamental mode when editing plantuml blocks with C-c '
(add-to-list 'org-src-lang-modes (quote ("plantuml" . fundamental)))
;; ;; add additional languages with '((language . t)))
(global-set-key (kbd "C-c a") 'org-agenda)
Fonts and Bullets
(use-package org-superstar
:after org
:hook (org-mode . org-superstar-mode)
:custom
(org-superstar-remove-leading-stars t)
(org-superstar-headline-bullets-list '("◉" "○" "●" "○" "●" "○" "●")))
;; (dolist (face '((org-level-1 . 1.2)
;; (org-level-2 . 1.1)
;; (org-level-3 . 1.05)
;; (org-level-4 . 1.0)
;; (org-level-5 . 1.1)
;; (org-level-6 . 1.1)
;; (org-level-7 . 1.1)
;; (org-level-8 . 1.1))))
;; Make sure org-indent face is available
(require 'org-indent)
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
;; TODO: Others to consider
;; '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
;; '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
;; '(org-property-value ((t (:inherit fixed-pitch))) t)
;; '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
;; '(org-table ((t (:inherit fixed-pitch :foreground "#83a598"))))
;; '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))))
;; '(org-verbatim ((t (:inherit (shadow fixed-pitch))))))
(use-package flyspell
:config
;; Set programms
(setq-default ispell-program-name "aspell")
(setq-default ispell-list-command "--list")
;; Some skipping
(add-to-list 'ispell-skip-region-alist '("^#+begin_src" . "^#+end_src"))
;; Refresh flyspell after directory change
(defun flyspell-buffer-after-pdict-save (&rest _)
(flyspell-buffer))
(advice-add 'ispell-pdict-save :after #'flyspell-buffer-after-pdict-save)
;; Popup
(defun flyspell-emacs-popup-textual (event poss word)
"A textual flyspell popup menu."
(require 'popup)
(let* ((corrects (if flyspell-sort-corrections
(sort (car (cdr (cdr poss))) 'string<)
(car (cdr (cdr poss)))))
(cor-menu (if (consp corrects)
(mapcar (lambda (correct)
(list correct correct))
corrects)
'()))
(affix (car (cdr (cdr (cdr poss)))))
show-affix-info
(base-menu (let ((save (if (and (consp affix) show-affix-info)
(list
(list (concat "Save affix: " (car affix))
'save)
'("Accept (session)" session)
'("Accept (buffer)" buffer))
'(("Save word" save)
("Accept (session)" session)
("Accept (buffer)" buffer)))))
(if (consp cor-menu)
(append cor-menu (cons "" save))
save)))
(menu (mapcar
(lambda (arg) (if (consp arg) (car arg) arg))
base-menu)))
(cadr (assoc (popup-menu* menu :scroll-bar t) base-menu))))
(defun flyspell-emacs-popup-choose (org-fun event poss word)
(if (window-system)
(funcall org-fun event poss word)
(flyspell-emacs-popup-textual event poss word)))
(eval-after-load "flyspell"
'(progn
(advice-add 'flyspell-emacs-popup :around #'flyspell-emacs-popup-choose)))
)