From 4ead9be4468d8d58c027bf6e6616e3b4d6e727eb Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Thu, 22 Aug 2019 18:30:24 +0200 Subject: Complete re-structuring so it's easier to install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miquel Sabaté Solà --- emacs/README.org | 94 -- emacs/custom.el | 24 - emacs/gtkrc | 5 - emacs/init.el | 22 - emacs/init.org | 2349 ---------------------------------------- emacs/lisp/README.md | 18 - emacs/lisp/g.el | 134 --- emacs/org.css | 66 -- emacs/pre-push | 79 -- emacs/snippets/org-mode/header | 8 - emacs/test-startup.sh | 22 - 11 files changed, 2821 deletions(-) delete mode 100644 emacs/README.org delete mode 100644 emacs/custom.el delete mode 100644 emacs/gtkrc delete mode 100644 emacs/init.el delete mode 100644 emacs/init.org delete mode 100644 emacs/lisp/README.md delete mode 100644 emacs/lisp/g.el delete mode 100644 emacs/org.css delete mode 100755 emacs/pre-push delete mode 100644 emacs/snippets/org-mode/header delete mode 100755 emacs/test-startup.sh (limited to 'emacs') diff --git a/emacs/README.org b/emacs/README.org deleted file mode 100644 index 517908a..0000000 --- a/emacs/README.org +++ /dev/null @@ -1,94 +0,0 @@ -#+TITLE: GNU Emacs configuration -#+AUTHOR: Miquel Sabaté Solà -#+EMAIL: mikisabate@gmail.com - -* About this - -I'm following a literate programming approach for my GNU Emacs -configuration. The basic workflow is that on the first run the =init.el= file -will replace itself with a tangled (=org-babel=) version of itself. Therefore, -all changes should go into the =init.org= file. Moreover, I've added a function -that is executed on save which generates and compiles new versions of the -=init.el= file. - -I run GNU Emacs in daemon mode, but I don't use systemd for that. Instead, in -I'm using the =-a= argument of =emacsclient= with an empty string. This -instructs =emacsclient= to spawn a new server if there isn't one already. This -means that the first time around it will take some time, but in the next time -everything will be alright. - -=Supported versions=: GNU Emacs 25.x and 26.x. - -* Dependencies - -First of all, install the [[https://github.com/mssola/soria][soria]] color theme. This should already be handled by -the install script. Then make sure to install the following: - -- =calibre=: a markdown to HTML converter. -- =spell= for spell checking. -- A LaTeX to PDF converter for exporting org files to PDF. In openSUSE this is - fixed by installing the =texlive-pdftex= package. -- =mu= and =mu4e= for email. This should be installed from my [[https://build.opensuse.org/package/show/home:mssola/mu][OBS]] project. - -Last but not least, to get a proper Go environment you need to install the -following: - -#+BEGIN_SRC sh -go get -u golang.org/x/tools/cmd/goimports -go get -u github.com/rogpeppe/godef -go get -u github.com/dougm/goflymake -go get -u github.com/nsf/gocode -#+END_SRC - -* Developing - -I've added a git =pre-push= hook which syncs the =init.html= and the =org.css= -files into my personal server. - -* Installing - -The installation process of my GNU Emacs configuration should already be handled -by the =install.sh= script that can be found in the root of this project. If you -want to do it manually: - -- Create the =~/.emacs.d= directory if it has not been created yet. -- Copy the =init.el= into the =~/.emacs.d= directory. This is the only file that - should be copied instead of linked because it will get replaced on the first run - by =org-babel=. -- Link the =init.org=, =custom.el= and =gtkrc= files into the =~/.emacs.d= - directory. -- Create the =~/.emacs.d/lisp= subdirectory and link the =lisp/g.el= file there. -- Clone the [[https://github.com/mssola/soria][soria]] project and link the =soria-theme.el= file into the - =~/.emacs.d= directory. - -* Credits - -I've built this file by simply scavenging from other people's emacs.d/dotfiles -repositories. I have taken lots of pieces from here and there, but most notably: - -- [[https://github.com/ereslibre/dotfiles][@ereslibre]] -- [[https://github.com/dmacvicar/dotfiles][@dmacvicar]] -- [[https://github.com/bbatsov/emacs.d][@bbatsov]] -- [[https://github.com/aaronbieber/dotfiles][@aaronbieber]] -- [[https://github.com/purcell/emacs.d][@purcell]] -- [[https://github.com/sachac/emacs.d][@sachac]] ([[http://pages.sachachua.com/.emacs.d/Sacha.html][HTML version]]) -- [[https://github.com/larstvei/dot-emacs][@larstvei]] - -* License - -#+BEGIN_SRC text - Copyright (C) 2014-2019 Miquel Sabaté Solà - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -#+END_SRC diff --git a/emacs/custom.el b/emacs/custom.el deleted file mode 100644 index be16428..0000000 --- a/emacs/custom.el +++ /dev/null @@ -1,24 +0,0 @@ -(custom-set-variables - ;; custom-set-variables was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - '(ansi-color-names-vector - ["#1c1c1c" "#d78787" "#b9dc92" "#ffffaf" "#87afd7" "#875f87" "#dfafdf" "#d0d0d0"]) - '(custom-safe-themes - (quote - ("44c996124982462f61fa04eeccb9e3661fbe995489eacd3b0f289e37aed29c98" "613d432fab88d34f9a4451bdbe714a31749de6c5a4d9d0bf0929399ad50f1ac6" "03f4de3e9d5df2d34dc4085ea2fe4906edf6377bf02eef7eb3430b97155c1398" "c2ea64b5a0d8042da7ff3979fc03e5cc13fc1e4bc839c5ab464f69c2dada0804" "1c79d160e207fcd2193beaf95bf25d55e15f3237f6943cc04f516e7ef600bdd7" "6a32c414a3d1a493d534a28e7814a4d6055bc607bbf45d57196cd6ee9215461b" "da9b51d7ba5c03589a7cb74f0da136cf4c9b2fdc6c58e48d78f077c8ccca39a9" "6a068d53e7b2bf41ac4a3874ea296b78c3f90cd1fd44d1769812c4c578313539" "8ebd5ccdc11c1e53647c9efc153dbcf0b00a61a519825d2698ce065913cecd35" "7e69e41a60afea0bea1e5f7a89416466db331ec45cbafe47ebec694411c997b8" "3762f105d8ea307cec0ee7cc36dcbce1ab0009ca1ae448fd07e8e8e65647431f" "75080b8936556e23444bd76fcfc042e484a50a403ccb7f36fd190c21f7bf8941" "e2669e7d32201debd97395277167b6a1d93606b9445ebce01b9f878eb980e200" "92eb47cefb2f03abaaaa52c60a0b89845361577c2201d3399d19b944828505f4" "62c1fac02f61eaad07bf39fd461f5c78ee3424ba87a1f5fe91b1bea25475f327" "62f08bc59e1ac24e6df5b5b01fea2da24f2fec201b285ccda9991b7052a3a46a" "ce1c38b72f45eed22f3dfaf7f3f0df4b0b6ed975cc5d2012fb1aad13e8055840" "e8b0224a3bd5da096120bf19c976a29cfe67af41bfe73171348bfe99ee0da62d" "ad1c0d9498ad9344082d47e3a1bb6b75f0d004e0ae8361613b0c9963b23fbb4d" "8e6f5b61626315a98a6b38acfe966800777bf6a1841aa2b812b471772cc17114" "5869e98ef7446c9e2283e5788c0f6e2790676bdb52e9e1e112bb74e2415733c4" "5a3f33eefbcf2a3098bafd22d7ad44358e66c3e844797e7bf9ef552a08dfeb6f" default))) - '(delete-selection-mode nil) - '(electric-indent-mode t) - '(magit-commit-arguments (quote ("--all" "--verbose" "--signoff"))) - '(magit-log-arguments (quote ("--graph" "--color" "--decorate" "-n256"))) - '(markdown-command "/usr/bin/markdown-calibre") - '(package-selected-packages - (quote - (py-autopep8 elpy inf-ruby move-text git-timemachine debbugs async-await request emojify auctex diminish bats-mode bool-flip salt-mode flycheck-rust rust-playground rust-mode vue-mode coffee-mode json-reformat erc-hl-nicks emoji-cheat-sheet-plus helm-circe htmlize cmake-mode websocket markdown-mode go-mode magit evil-leader evil helm projectile org-eldoc evil-commentary yasnippet yaml-mode which-key web-mode wc-mode use-package terraform-mode smart-tabs-mode slim-mode scss-mode rainbow-delimiters php-mode org-evil olivetti mu4e-alert mmm-jinja2 markdown-preview-mode helm-projectile helm-ag go-eldoc go-add-tags flycheck evil-surround evil-org evil-numbers evil-mu4e evil-magit evil-args dockerfile-mode disable-mouse default-text-scale crux cmake-font-lock ag)))) -(custom-set-faces - ;; custom-set-faces was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - ) diff --git a/emacs/gtkrc b/emacs/gtkrc deleted file mode 100644 index 19d2109..0000000 --- a/emacs/gtkrc +++ /dev/null @@ -1,5 +0,0 @@ -style "emacsfont" -{ - font_name = "Droid Sans Mono Dotted for Powerline 10" -} -widget "*" style "emacsfont" diff --git a/emacs/init.el b/emacs/init.el deleted file mode 100644 index 4129a5c..0000000 --- a/emacs/init.el +++ /dev/null @@ -1,22 +0,0 @@ -;; This file replaces itself with the actual configuration at first run. -;; Idea and file taken from https://github.com/larstvei/dot-emacs. -;; -;; NOTE DO NOT MODIFY THIS FILE. All changes should go into init.org - -;; We can't tangle without org! -(require 'org) - -;; Follow symlinks -(setq vc-follow-symlinks t) - -;; Open the configuration -(find-file (concat user-emacs-directory "init.org")) - -;; Tangle it -(org-babel-tangle) - -;; Load it -(load-file (concat user-emacs-directory "init.el")) - -;; Finally byte-compile it -(byte-compile-file (concat user-emacs-directory "init.el")) diff --git a/emacs/init.org b/emacs/init.org deleted file mode 100644 index 66ed281..0000000 --- a/emacs/init.org +++ /dev/null @@ -1,2349 +0,0 @@ -#+TITLE: mssola's GNU Emacs configuration -#+AUTHOR: Miquel Sabaté Solà -#+EMAIL: mikisabate@gmail.com -#+BABEL: :cache yes -#+PROPERTY: header-args :tangle ~/.emacs.d/init.el - -* Preface - -This is my attempt of getting my configuration organized with literate -programming and =org-babel=. I took the workflow I'm following from [[https://github.com/larstvei][@larstvei]]. -The idea is that the =init.el= file will replace itself on the first execution -with the tangled version of this file. This first version will also be -byte-compiled. This means that all changes are to be made on the =init.org= -file *always*. The initial contents of the =init.el= are: - -#+BEGIN_SRC elisp :tangle no -;; We can't tangle without org! -(require 'org) - -;; Follow symlinks -(setq vc-follow-symlinks t) - -;; Open the configuration -(find-file (concat user-emacs-directory "init.org")) - -;; Tangle it -(org-babel-tangle) - -;; Load it -(load-file (concat user-emacs-directory "init.el")) - -;; Finally byte-compile it -(byte-compile-file (concat user-emacs-directory "init.el")) -#+END_SRC - -There is no reason to track the init.el file, and no reason to change this -file. In order to ensure this, make sure to apply the following command after -cloning: - -#+BEGIN_SRC sh :tangle no -git update-index --assume-unchanged emacs/init.el -#+END_SRC - -Moreover, in order to avoid manually tangling and compiling the =init.org= file -on each change, the following function is provided: - -#+BEGIN_SRC elisp -(defun tangle-init () - "If the current buffer is 'init.org' the code-blocks are - tangled, and the tangled file is compiled. Morever, an init.html is generated." - - (when (or (equal (buffer-file-name) - (expand-file-name (concat user-emacs-directory "init.org"))) - (string-suffix-p "dotfiles/emacs/init.org" (buffer-file-name))) - - ;; Avoid running hooks when tangling - (let ((prog-mode-hook nil)) - (org-babel-tangle) - (byte-compile-file (concat user-emacs-directory "init.el"))))) - -(add-hook 'after-save-hook 'tangle-init) -#+END_SRC - -* Introduction - -I'm using GNU Emacs 26, but everything should be working in GNU Emacs 24. There -are some exceptions to this (e.g. webkit support), but these cases are -individually handled. - -#+BEGIN_SRC elisp - (unless (>= emacs-major-version 25) - (error "Don't be a cheap bastard and upgrade to at least GNU Emacs 25")) -#+END_SRC - -Temporarily reduce garbage collection so startup time is lower. Idea taken from -[[https://github.com/purcell][@purcell]]. - -#+BEGIN_SRC elisp - (defconst mssola-initial-gc-cons-threshold gc-cons-threshold - "Initial value of `gc-cons-threshold' at start-up time.") - (setq gc-cons-threshold (* 1024 1024 1024)) - (add-hook 'after-init-hook - (lambda () (setq gc-cons-threshold mssola-initial-gc-cons-threshold))) -#+END_SRC - -User name and email. - -#+BEGIN_SRC elisp -(setq user-full-name "Miquel Sabaté Solà" - user-mail-address "mikisabate@gmail.com") -#+END_SRC - -* Lisp packages -** Custom packages - -Compile the =g.el= script and bind it to @@html:M-g@@. - -#+BEGIN_SRC elisp -(if (file-exists-p (concat user-emacs-directory "lisp/g.elc")) - (load-file (concat user-emacs-directory "lisp/g.elc")) - (byte-compile-file (concat user-emacs-directory "lisp/g.el") t)) -(global-set-key (kbd "M-g") 'g) -#+END_SRC - -** use-package - -Initialize package. - -#+BEGIN_SRC elisp -(require 'package) - -(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") - -(add-to-list 'package-archives - '("melpa" . "http://melpa.milkbox.net/packages/") t) -(add-to-list 'package-archives - '("melpa-stable" . "https://stable.melpa.org/packages/") t) - -(package-initialize) -#+END_SRC - -I'm using use-package to handle my installed packages. I don't know if it's -the best option or what because I haven't tested all the package managers -for Emacs out there. After trying some custom functions to handle -package-install, I decided on use-package because I feel more well-organized. - -#+BEGIN_SRC elisp -(unless (package-installed-p 'use-package) - (package-refresh-contents) - (package-install 'use-package)) - -(require 'use-package) -#+END_SRC - -Some =use-package= calls require =diminish.el= to be available. So, let's -require it here on the very top. - -#+BEGIN_SRC elisp -(use-package diminish - :ensure t) -#+END_SRC - -* General - -** GUI - -I like a minimalistic GUI. Because of this, almost all GUI elements have been -disabled or tweaked in some custom way. - -The frame title is ": ". If we are not editing a file, then the -name of the buffer is displayed (e.g. "mssola: *scratch*"). - -#+BEGIN_SRC elisp - (setq frame-title-format - '((:eval - (concat (user-real-login-name) ": " - (if (buffer-file-name) - (abbreviate-file-name (buffer-file-name)) - "%b"))))) -#+END_SRC - -Disable the menu, scroll and tool bars. At the same time, enable line and column -modes. - -#+BEGIN_SRC elisp - (menu-bar-mode -1) - (when (fboundp 'set-scroll-bar-mode) - (set-scroll-bar-mode nil)) - (when (fboundp 'tool-bar-mode) - (tool-bar-mode -1)) - (when (fboundp 'tooltip-mode) - (tooltip-mode 0)) - - (line-number-mode 1) - (column-number-mode 1) - - ;; Nice scrolling - (setq scroll-margin 0 - scroll-conservatively 100000 - scroll-preserve-screen-position 1) -#+END_SRC - -Relative line numbers support is builtin since GNU Emacs 26.1: - -#+BEGIN_SRC elisp -(if (>= emacs-major-version 26) - (progn - (add-hook 'prog-mode-hook 'display-line-numbers-mode) - (setq display-line-numbers-type 'relative) - (global-set-key (kbd "C-c L") 'display-line-numbers-mode))) -#+END_SRC - -** Basic editing configuration - -Use UTF-8 *always*. - -#+BEGIN_SRC elisp - (prefer-coding-system 'utf-8) - (set-default-coding-systems 'utf-8) - (set-terminal-coding-system 'utf-8) - (set-keyboard-coding-system 'utf-8) - (set-language-environment 'utf-8) -#+END_SRC - -Some editing tweaks like tabs vs spaces, maximum column width, etc. - -#+BEGIN_SRC elisp - ;; Emacs modes typically provide a standard means to change the indentation - ;; width (e.g. c-basic-offset). Moreover, even though I prefer tabs over space, - ;; for most coding conventions this is not the case (e.g. ruby). For this - ;; reason, I will disable them by default and enabled them back for each - ;; specific case (e.g. C). I'm also using the smart-tabs-mode package, see - ;; below in the languages section. - (setq-default indent-tabs-mode nil) - (setq-default tab-width 4) - - ;; Maximum 80 columns. - (setq-default fill-column 80) - (setq-default auto-fill-function 'do-auto-fill) - - ;; Do not break lines - (set-default 'truncate-lines t) - - ;; Delete the selection with a keypress. - (delete-selection-mode t) - - ;; Remove whitespaces at the end of line - (add-hook 'before-save-hook 'delete-trailing-whitespace) - - ;; Cursor - (blink-cursor-mode 0) - (global-hl-line-mode -1) - (show-paren-mode 1) -#+END_SRC - -** Font and theme - -I'm using "Droid Sans Mono" simply because I've grown used to it. - -#+BEGIN_SRC elisp -(defconst mssola-font - (if (string= system-type "darwin") - "Droid Sans Mono-12" - "Droid Sans Mono Dotted for Powerline-10") - "The font to be used.") - -(set-frame-font mssola-font) -(add-to-list 'default-frame-alist `(font . ,mssola-font)) - -; Emacs in daemon mode does not like `set-face-attribute` because this is only -; applied if there is a frame in place, which doesn't happen when starting the -; daemon. Thus, we should call that after the frame has been created (e.g. by -; emacsclient). -; See: https://lists.gnu.org/archive/html/help-gnu-emacs/2015-03/msg00016.html -(add-hook 'after-make-frame-functions-hook - (lambda () - (set-face-attribute 'default t :font mssola-font))) -#+END_SRC - -I've hacked my own theme called [[https://github.com/mssola/soria][soria]]. This theme combines the vim theme -[[http://www.vim.org/scripts/script.php?script_id=2140][xoria256]] with the [[http://opensuse.github.io/branding-guidelines/][openSUSE branding guidelines]]. - -#+BEGIN_SRC elisp - (load-theme 'soria t) -#+END_SRC - -When hacking your own theme, sometimes you want to know what face is the one -that you see on the screen right now. This function from [[https://github.com/thblt/DotFiles][@thblt]] allows me to -get exactly that: - -#+BEGIN_SRC elisp -(defun mssola-face-at-point (pos) - "Writes a message with the name of the face at the current point. The POS - argument contains the current position of the cursor." - - (interactive "d") - - (let ((face (or (get-char-property (point) 'read-face-name) - (get-char-property (point) 'face)))) - (if face (message "Face: %s" face) (message "No face at %d" pos)))) - -(global-set-key (kbd "C-c f") 'mssola-face-at-point) -#+END_SRC - -** General global key bindings - -Use kill-this-buffer instead of kill-buffer. - -#+BEGIN_SRC elisp - (global-set-key (kbd "C-x k") 'kill-this-buffer) -#+END_SRC - -Disable C-z. It will later on be picked up by Evil's config as the escape -sequence. This is here to make sure that it will be disabled even if Evil -cannot be loaded due to some error. - -#+BEGIN_SRC elisp - (global-unset-key (kbd "C-z")) -#+END_SRC - -Also disable the =C-x i= binding, since I've never used the default behavior, -and it will be used as a prefix for inferior modes (e.g. /ielm/). - -#+BEGIN_SRC elisp - (global-unset-key (kbd "C-x i")) -#+END_SRC - -Disable all the Fn keys. - -#+BEGIN_SRC elisp - (dotimes (i 12) - (global-unset-key (kbd (format "" (+ i 1))))) -#+END_SRC - -Disable overwrite-mode. - -#+BEGIN_SRC elisp - (define-key global-map [(insert)] nil) -#+END_SRC - -Kill GNU Emacs by hitting =C-x r q= (mnemonic /Really quit/). - -#+BEGIN_SRC elisp - (global-set-key (kbd "C-x r q") 'kill-emacs) -#+END_SRC - -** Others - -Revert buffers automatically when underlying files are changed externally. - -#+BEGIN_SRC elisp - (global-auto-revert-mode t) -#+END_SRC - -Follow symlinks. - -#+BEGIN_SRC elisp - (setq vc-follow-symlinks t) -#+END_SRC - -Remove the initial message from the scratch buffer. - -#+BEGIN_SRC elisp - (setq initial-scratch-message nil) -#+END_SRC - -Never kill the scratch buffer, bury it instead. - -#+BEGIN_SRC elisp -(defadvice kill-buffer (around kill-buffer-around-advice activate) - (let ((buffer-to-kill (ad-get-arg 0))) - (if (equal buffer-to-kill "*scratch*") - (bury-buffer) - ad-do-it))) - -(defadvice kill-this-buffer (around kill-buffer-around-advice activate) - (let ((buffer-to-kill (ad-get-arg 0))) - (if (equal buffer-to-kill "*scratch*") - (bury-buffer) - ad-do-it))) -#+END_SRC - -No backups - -#+BEGIN_SRC elisp - (setq-default make-backup-files nil) - (setq-default auto-save-default nil) -#+END_SRC - -But at least save the list of recently open files. - -#+BEGIN_SRC elisp -(require 'recentf) - -(recentf-mode 1) -(global-set-key "\C-x\ \C-r" 'recentf-open-files) - -; Save the list every 5 minutes -(run-at-time nil (* 5 60) 'recentf-save-list) -#+END_SRC - -No welcome screen - -#+BEGIN_SRC elisp - (setq-default inhibit-startup-message t) -#+END_SRC - -Enable y/n answers - -#+BEGIN_SRC elisp - (fset 'yes-or-no-p 'y-or-n-p) -#+END_SRC - -Let flyspell be performant. - -#+BEGIN_SRC elisp - (defvar flyspell-issue-message-flag nil) -#+END_SRC - -Save custom-variables somewhere else. - -#+BEGIN_SRC elisp - (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) - (if (file-exists-p custom-file) - (load custom-file)) -#+END_SRC - -Disable audio notifications. - -#+BEGIN_SRC elisp -(setq ring-bell-function 'ignore) -#+END_SRC - -* Calendar - -We catalans start our weeks on Monday. - -#+BEGIN_SRC elisp - (defvar calendar-week-start-day 1) -#+END_SRC - -Global key binding. - -#+BEGIN_SRC elisp - (global-set-key (kbd "M-c") 'calendar) -#+END_SRC - -Fix some stuff for evil mode. - -#+BEGIN_SRC elisp -(with-eval-after-load "calendar" - (with-eval-after-load "evil" - (evil-set-initial-state 'calendar-mode 'normal) - (evil-define-key 'normal calendar-mode-map - "j" 'calendar-forward-week - "k" 'calendar-backward-week - "b" 'calendar-backward-day - "h" 'calendar-backward-day - "l" 'calendar-forward-day - "w" 'calendar-forward-day - "q" 'calendar-exit - "\C-h" 'evil-window-left - "\C-l" 'evil-window-right - "\C-j" 'evil-window-down - "\C-k" 'evil-window-up - "\C-n" 'calendar-scroll-left-three-months - "\C-p" 'calendar-scroll-right-three-months))) -#+END_SRC - -* General purpose defuns - -I want to read the latest news. That's why I define a function that downloads -the =NEWS= file from the git server and then opens it in a buffer. - -#+BEGIN_SRC elisp - (defun mssola-view-emacs-latest-news () - "Allow users to fetch the latest Emacs' NEWS file." - (interactive) - - (url-copy-file - "http://git.savannah.gnu.org/cgit/emacs.git/plain/etc/NEWS" - "/tmp/emacs-news" t) - - (find-file-read-only "/tmp/emacs-news" t)) -#+END_SRC - -Sometimes I want to debug my initialization time. - -#+BEGIN_SRC elisp - (defun emacs-init-time () - "Redefine the `emacs-init-time' function so it is more detailed. - Idea taken from @purcell." - - (interactive) - (let ((init-time - (float-time (time-subtract after-init-time before-init-time)))) - (message "%.3fs" init-time))) -#+END_SRC - -* Project - -First of all, load the silver searcher, which is a convenient and fast searcher. -Ayo silver! - -#+BEGIN_SRC elisp - (use-package ag - :ensure t - :config - - ; Avoid some disagreements between ag and evil. - (with-eval-after-load 'evil - (add-hook 'ag-mode-hook - (lambda () - (define-key ag-mode-map (kbd "n") 'evil-search-next) - (define-key ag-mode-map (kbd "N") 'evil-search-previous) - (define-key ag-mode-map (kbd "gg") 'evil-goto-first-line)))) - (setq ag-reuse-buffers t) - (setq ag-reuse-window t)) -#+END_SRC - -Then, for keeping up with my projects I use the Projectile + Helm combination. - -#+BEGIN_SRC elisp - (use-package projectile - :ensure t - :config - (projectile-mode 1)) - - (use-package helm - :ensure t - :config - (setq projectile-completion-system 'helm) - - ; Allow the search pattern to be on the header. Taken from this Reddit thread: - ; https://www.reddit.com/r/emacs/comments/3asbyn/new_and_very_useful_helm_feature_enter_search/ - (setq helm-echo-input-in-header-line t) - - (defun helm-hide-minibuffer-maybe () - "Hide the minibuffer if we are in a Helm session" - - (when (with-helm-buffer helm-echo-input-in-header-line) - (let ((ov (make-overlay (point-min) (point-max) nil nil t))) - (overlay-put ov 'window (selected-window)) - (overlay-put ov 'face (let ((bg-color (face-background 'default nil))) - `(:background ,bg-color :foreground ,bg-color))) - (setq-local cursor-type nil)))) - - (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe) - (setq helm-split-window-inside-p t) - - ; Preview files with tab - (define-key helm-map (kbd "") 'helm-execute-persistent-action) - - ; Show available options - (define-key helm-map (kbd "C-a") 'helm-select-action) - - ; Some vim-like bindings - (define-key helm-map (kbd "C-j") 'helm-next-line) - (define-key helm-map (kbd "C-k") 'helm-previous-line) - - (global-set-key (kbd "M-x") 'helm-M-x) - - (use-package helm-ag - :ensure t)) - - (use-package helm-projectile - :ensure t - :config - (helm-projectile-on) - - ; Define M-p as a way to quickly list all the available projects. - (with-eval-after-load 'evil - (define-key evil-normal-state-map (kbd "M-p") - 'helm-projectile-switch-project))) -#+END_SRC - -I use @@html:C-p@@ as the binding for listing relevant files. This -binding works either by using =helm-projectile= or the regular =helm-find= -function. As a final touch, this binding also works for listing channels in ERC -buffers. - -#+BEGIN_SRC elisp -(defun mssola-erc-helm-buffer-list () - "Returns a list with the ERC buffers." - (mapcar 'buffer-name (erc-buffer-list))) - -(defconst mssola-helm-source-erc-channel-list - '((name . "ERC Channels") - (candidates . mssola-erc-helm-buffer-list) - (action . switch-to-buffer))) - -(defun mssola-erc-helm-switch-buffer () - "Use helm to select an active ERC buffer." - - (interactive) - - (helm :sources '(mssola-helm-source-erc-channel-list) - :buffer "*helm-erc-channels*")) - -(defun mssola-find-file () - "Call the proper Helm function for finding files." - - (interactive) - - (if (string= major-mode "erc-mode") - (mssola-erc-helm-switch-buffer) - (condition-case nil - (helm-projectile-find-file) - (error - (helm-find-files nil))))) - -(with-eval-after-load 'evil - (define-key evil-normal-state-map (kbd "C-p") 'mssola-find-file)) -#+END_SRC - -Similarly, =helm-ag= has two functions for applying =ag= on the project. I'm -binding to @@html:,a@@ a function that calls to the proper function. - -#+BEGIN_SRC elisp - (defun mssola-helm-ag () - "Call the right ag command for helm-ag." - - (interactive) - - (condition-case nil - (helm-ag-project-root) - (error (helm-ag)))) - - (with-eval-after-load 'evil-leader - (evil-leader/set-key "a" 'mssola-helm-ag)) -#+END_SRC - -* Edit - -In this section I define some useful packages for editing. First of all, one of -the coolest packages out there is =undo-tree=. It allows you to navigate through -the undo history in a tree (because GNU Emacs is cool and keeps track of undo -actions in a tree structure instead of in a stack). This package is included in -recent versions of GNU Emacs. - -#+BEGIN_SRC elisp -(with-eval-after-load 'undo-tree - (global-undo-tree-mode 1) - - (setq undo-tree-visualizer-diff t - undo-tree-visualizer-timestamps t - undo-tree-visualizer-relative-timestamps t) - - (require 'diminish) - (diminish 'undo-tree-mode)) -#+END_SRC - -Another important package is =flycheck=, which is an on-the-fly syntax checking -extension. This works with lots of languages with proper glue code. - -#+BEGIN_SRC elisp -(use-package let-alist - :ensure t) - -(use-package flycheck - :ensure t - :diminish - :config - (add-hook 'after-init-hook 'global-flycheck-mode) - - ;; Only show the errors buffer if it isn't there and if I'm saving the - ;; buffer. - (setq flycheck-emacs-lisp-load-path 'inherit) - (setq flycheck-check-syntax-automatically '(mode-enabled save)) - (setq flycheck-display-errors-function - #'flycheck-display-error-messages-unless-error-list)) -#+END_SRC - -A recurring issue in speeches and presentations is that when showing something -with your editor, you have to increase/decrease the fonts. I use the -=default-text-scale= package for this. - -#+BEGIN_SRC elisp - (use-package default-text-scale - :ensure t - :config - (global-set-key (kbd "C-+") 'default-text-scale-increase) - (global-set-key (kbd "C--") 'default-text-scale-decrease)) -#+END_SRC - -Some languages use some delimiters a lot (e.g. lisp languages and -parenthesis). For this reason I'm using the =rainbow-delimiters= package, which -properly highlights each level in a different way (provided that your theme -supports it). - -#+BEGIN_SRC elisp - (use-package rainbow-delimiters - :ensure t) -#+END_SRC - -Enable =electric-pair-mode=, which automatically closes pairs like brackets: - -#+BEGIN_SRC elisp -(electric-pair-mode 1) -#+END_SRC - -I never use the mouse. - -#+BEGIN_SRC elisp -(use-package disable-mouse - :ensure t - :config - (global-disable-mouse-mode) - (setq global-disable-mouse-mode-lighter "")) -#+END_SRC - -Sometimes you begin typing a prefix, but then you forget the following -chord. For this reason =which-key= was created. It will show the available -commands for the current chord as a list. - -#+BEGIN_SRC elisp -(use-package which-key - :ensure t - :diminish which-key-mode - :config - (which-key-mode)) -#+END_SRC - -For some modes it is important to count the number of words in the text. For -this, we have =wc-mode=. - -#+BEGIN_SRC elisp - (use-package wc-mode - :ensure t) -#+END_SRC - -Editing files as root is a bit of a pain because usually the root user doesn't -have the same configuration as the current one, and attempting to do so can be -messy. So, instead of that, we could advice the =find-file= function so if the -file is not writable by the current user, then GNU Emacs will ask for editing -this same file as root: - -#+BEGIN_SRC elisp -(defadvice find-file (after find-file-sudo activate) - "Find file as root if necessary." - (if (and buffer-file-name - (not (file-writable-p buffer-file-name))) - (if (yes-or-no-p "Do you want to edit this file as root?") - (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))) -#+END_SRC - -=YASnippet= allows people to define shortcuts for writing some common blocks. -Moreover, it comes with a set of builtin snippets already. Since I don't -remember some of these snippets, I've mapped @@html:, h@@ to -=yas-describe-tables=, which shows the available snippets in another buffer. - -#+BEGIN_SRC elisp -(use-package yasnippet - :ensure t - :diminish yas-minor-mode - :init (yas-global-mode) - :config - (yas-global-mode 1)) -#+END_SRC - -=bool-flip= is a very simple utility that toggles truthy/falsey values. - -#+BEGIN_SRC elisp -(use-package bool-flip - :ensure t - :config - (global-set-key (kbd "C-c b") 'bool-flip-do-flip)) -#+END_SRC - -=move-text= is a small package that allows you to move lines with a -keybinding. This might be feasible with Evil mode, but still this might help -when you want to move lines and keep the default registry empty: - -#+BEGIN_SRC elisp -(use-package move-text - :ensure t - :bind - (("M-k" . move-text-up) - ("M-j" . move-text-down))) -#+END_SRC - -* Dired - -I use dired mode mainly for attaching document into emails. That being said, -whenever I use it, I want basic evil movement. - -#+BEGIN_SRC elisp - (with-eval-after-load 'evil - (evil-add-hjkl-bindings dired-mode-map 'normal - (kbd "w") 'evil-forward-word-begin)) -#+END_SRC - -I also extend =dired= with some handy tweaks. - -#+BEGIN_SRC elisp -(setq directory-free-space-args "-Pkh" - dired-dwim-target t - dired-omit-mode nil - dired-recursive-copies 'always - dired-recursive-deletes 'always - delete-old-versions t) -#+END_SRC - -And now instruct dired mode how to attach files when using mu4e. This is taken -from the [[https://www.djcbsoftware.nl/code/mu/mu4e/Dired.html#Dired][mu4e documentation]], and it's available by typing -@@html:C-c RET C-a@@. - -#+BEGIN_SRC elisp - (require 'gnus-dired) - - ;; Make the `gnus-dired-mail-buffers' function also work on message-mode derived - ;; modes, such as mu4e-compose-mode. - (defun gnus-dired-mail-buffers () - "Return a list of active message buffers." - - (let (buffers) - (save-current-buffer - (dolist (buffer (buffer-list t)) - (set-buffer buffer) - (when (and (derived-mode-p 'message-mode) - (null message-sent-message-via)) - (push (buffer-name buffer) buffers)))) - (nreverse buffers))) - - (setq gnus-dired-mail-mode 'mu4e-user-agent) - (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) -#+END_SRC - -* Evil - -Forgive me, [[https://stallman.org/saint.html][Father]], for I have sinned. I've been exposed to modal editing -through Vim, and that has changed how I view editing for the foreseeable future. -Because of this, I use Evil. The following blocks include some heavy-lifting so -Evil and GNU Emacs work without hitting each other, and it also includes some -Evil extensions. - -First of all, let's define a function that will be called whenever Evil is loaded. - -#+BEGIN_SRC elisp -(defun mssola-evil () - "Configure evil mode." - - ; We can safely remap because the counting will be handled a-la Vim. - (define-key evil-normal-state-map (kbd "C-u") 'evil-scroll-up) - - ; Make window navigation easier. - (define-key evil-normal-state-map (kbd "C-j") 'evil-window-down) - (define-key evil-normal-state-map (kbd "C-k") 'evil-window-up) - (define-key evil-normal-state-map (kbd "C-l") 'evil-window-right) - (define-key evil-normal-state-map (kbd "C-h") 'evil-window-left) - - ; The window navigation tweaks effectively wipe out the help prefix, which - ; is bad. Fortunately we can workaround this by providing "M-h" as the new - ; help prefix. This prefix is only used in emacs mode to mark lines, which is - ; something already handled by Evil. - (define-key global-map (kbd "M-h") 'help-command) - (fset 'help-command help-map) - - ; Go back to Emacs' bindings on beginning/end of line. - (eval-after-load "evil-maps" - (dolist (map '(evil-motion-state-map - evil-insert-state-map - evil-emacs-state-map)) - (define-key (eval map) "\C-a" 'crux-move-beginning-of-line) - (define-key (eval map) "\C-e" 'end-of-line))) - - ; I store macros on the register for convenience, so I used to use the - ; combo to execute this macro in Vim. In Emacs though, this combo is - ; reserved to a rather useful function, and I'd like to keep it that way. So, - ; now the mapping is set to (mnemonic: where the @ symbol is). Moreover, - ; it's applied as many times as specified by the numeric prefix argument. - (define-key evil-normal-state-map (kbd "C-2") - (lambda (n) - (interactive "p") - (evil-execute-macro n "@q"))) - - ; C-s: switch to normal mode and save the buffer. I know :) - (define-key evil-normal-state-map (kbd "C-s") 'save-buffer) - (define-key evil-insert-state-map (kbd "C-s") - (lambda () (interactive) (save-buffer) (evil-force-normal-state)))) -#+END_SRC - -Now make sure that Evil is installed, and call the relevant configuration functions. - -#+BEGIN_SRC elisp -(use-package evil - :ensure t - :config - (add-hook 'evil-mode-hook 'mssola-evil) - (evil-mode 1) - - ;; C-z is unused and it's close to my beloved C-c. Since I don't want to mess - ;; with one of the most sacred Emacs prefixes, I'm moving to C-z. - (define-key key-translation-map (kbd "C-z") [escape]) - (define-key evil-operator-state-map (kbd "C-z") 'keyboard-quit) - - ;; Use the proper initial evil state for the following modes. - (evil-set-initial-state 'help-mode 'normal) - (evil-set-initial-state 'debugger-mode 'normal) - (evil-set-initial-state 'describe-mode 'normal) - (evil-set-initial-state 'Buffer-menu-mode 'normal) -#+END_SRC - -If Evil was properly loaded, then make sure that the following Evil-related -packages are installed and configured as well. I start by defining the -=evil-leader= package, which brings the @@html:leader@@ feature from -Vim into Evil. - -#+BEGIN_SRC elisp - (use-package evil-leader - :ensure t - :config - (global-evil-leader-mode) - (evil-leader/set-leader ",") - (setq evil-leader/in-all-states 1) - (evil-leader/set-key - "c" 'delete-window - "k" 'kill-buffer-and-window - "v" 'split-window-right - "V" (lambda () (interactive) (split-window-right) (other-window 1)) - "f" 'flycheck-list-errors)) -#+END_SRC - -Another handy Vim plugin that has made it into Evil is =evil-surround=, which -defines a new text object for surrounding characters (e.g. change a string from -having double quotes with single quotes in a single command). - -#+BEGIN_SRC elisp - (use-package evil-surround - :ensure t - :config - (global-evil-surround-mode 1)) -#+END_SRC - -Next is another Vim plugin that has been ported to Evil: =evil-commentary=. This -package defines a new motion for comments, which is bound to -@@html:gc@@. So, for example, @@html:gcc@@ will comment -the current line, regardless of the programming language. - -#+BEGIN_SRC elisp - (use-package evil-commentary - :ensure t - :config - (evil-commentary-mode t)) -#+END_SRC - -Another cool package is =evil-args= which defines the argument text object. This -text object can be targeted with the =a= character, and we can move backward and -forward through arguments with @@html:H@@ and @@html:L@@ -respectively. - -#+BEGIN_SRC elisp - (use-package evil-args - :ensure t - :config - ; Configuration taken from the documentation of evil-args. - - ;; Bind evil-args text objects - (define-key evil-inner-text-objects-map "a" 'evil-inner-arg) - (define-key evil-outer-text-objects-map "a" 'evil-outer-arg) - - ;; Bind evil-forward/backward-args - (define-key evil-normal-state-map "L" 'evil-forward-arg) - (define-key evil-normal-state-map "H" 'evil-backward-arg) - (define-key evil-motion-state-map "L" 'evil-forward-arg) - (define-key evil-motion-state-map "H" 'evil-backward-arg)) -#+END_SRC - -Last but not least, =evil-numbers= brings a couple of bindings available to Vim -into Evil: @@html:C-c +@@ for increasing a number, and -@@html:C-c -@@ for decreasing it. - -#+BEGIN_SRC elisp - (use-package evil-numbers - :ensure t - :config - (define-key evil-normal-state-map (kbd "C-c +") 'evil-numbers/inc-at-pt) - (define-key evil-normal-state-map (kbd "C-c -") 'evil-numbers/dec-at-pt))) -#+END_SRC - -* Git - -A git porcelain for GNU Emacs. Even if I'm still using the git CLI, it's -certainly useful for some common tasks (I guess that I still need some learning). - -#+BEGIN_SRC elisp -(use-package magit - :ensure t - :config -#+END_SRC - -Set some global key bindings for Magit. - -#+BEGIN_SRC elisp -(global-set-key (kbd "C-x g") 'magit-status) -(global-set-key (kbd "C-c l") 'magit-log-buffer-file) -#+END_SRC - -And repair some key bindings from Evil mode. - -#+BEGIN_SRC elisp - (with-eval-after-load 'evil - (use-package evil-magit - :ensure t - :config - - ; The magit + evil-magit combo messes up some chords, let's fix this. - (evil-define-key 'normal magit-mode-map - "\C-h" 'evil-window-left - "\C-l" 'evil-window-right - "\C-j" 'evil-window-down - "\C-k" 'evil-window-up)))) -#+END_SRC - -=git-timemachine= is a package that goes hand-in-hand with Magit, and it -provides a very easy way to go through the history of a file (while providing -ways of jumping into Magit): - -#+BEGIN_SRC elisp -(use-package git-timemachine - :ensure t - :bind (("C-x t m" . git-timemachine-toggle))) -#+END_SRC - -* Email - -I use [[http://www.djcbsoftware.nl/code/mu/][mu]] and [[http://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]] to manage my email. The configuration for this has been taken -mainly from the documentation, plus some cool remarks on Reddit. This -configuration makes quite some assumptions. Read the =emacs/README.org= file as -provided in my [[https://github.com/mssola/dotfiles][dotfiles]] project to get more details. - -I'm using an RPM that I've built on [[https://build.opensuse.org/package/show/home:mssola/mu][OBS]] which installs mu4e globally. - -#+BEGIN_SRC elisp -(unless (file-directory-p "/usr/share/emacs/site-lisp/mu4e") - (message "Skipping mu4e because it's not installed.")) - -(when (file-directory-p "/usr/share/emacs/site-lisp/mu4e") - (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e") - (require 'mu4e) - - (when (featurep 'mu4e) -#+END_SRC - -Set =mu4e= as the default user agent. This will be picked up by =compose-mail=. - -#+BEGIN_SRC elisp -(setq mail-user-agent 'mu4e-user-agent) -#+END_SRC - -Diferent SMTP options that will be used for each context. - -#+BEGIN_SRC elisp - (setq message-send-mail-function 'smtpmail-send-it - mu4e-maildir (expand-file-name "~/.mail") - starttls-use-gnutls t) -#+END_SRC - -After that, I am defining some functions that will be used in various parts of -the configuration. - -#+BEGIN_SRC elisp -(defun mssola-smtp (server port) - "Set SMTP variables depending on the given SERVER and PORT." - - (require 'smtpmail) - - (setq smtpmail-starttls-credentials '((server port nil nil)) - smtpmail-auth-credentials (expand-file-name "~/.authinfo.gpg") - smtpmail-default-smtp-server server - smtpmail-smtp-server server - message-send-mail-function 'smtpmail-send-it - smtpmail-smtp-service port)) - -; https://www.reddit.com/r/emacs/comments/47t9ec/share_your_mu4econtext_configs/d0fsih6 -(defun mu4e-message-maildir-matches (msg rx) - "Returns true if the maildir of MSG matches the given regexp RX." - - (when rx - (if (listp rx) - ;; if rx is a list, try each one for a match - (or (mu4e-message-maildir-matches msg (car rx)) - (mu4e-message-maildir-matches msg (cdr rx))) - ;; not a list, check rx - (string-match rx (mu4e-message-field msg :maildir))))) - -(defun suse-refile-folder (key) - "Returns the refile folder for the given SUSE account in the KEY arg" - - (if (string= key "susecom") - (setq archives-dir "/Arxiu/") - (setq archives-dir "/Archives/")) - (concat "/" key archives-dir - (format-time-string "%Y" (current-time)))) -#+END_SRC - -Depending on the context, it's better a signature or another: - -#+BEGIN_SRC elisp -(defun mssola-mu4e-signature (key) - "Returns a string containing the mail signature for the given KEY." - - (if (string= key "ajuntament") - (concat - "Miquel Sabaté Solà,\n" - "Regidor de Joventut, Participació ciutadana i Transparència\n" - "\n" - "Ajuntament de Capellades\n" - "Carrer de Ramon Godó, 9, 08786 - Capellades\n" - "Tel. 93 801 10 01 – mòbil 677 12 72 07\n" - "sabatesm@capellades.cat\n") - (concat - "Miquel Sabaté Solà,\n" - "PGP: 4096R / 1BA5 3C7A C93D CA2A CFDF DA97 96BE 8C6F D89D 6565\n"))) -#+END_SRC - -Now it's time to define the different contexts that I have. Defining contexts -this way is relatively new (since mu 0.9.16). - -#+BEGIN_SRC elisp -(setq mu4e-contexts - `( - ;; GMail - ,(make-mu4e-context - :name "gmail" - :enter-func (lambda () - (mu4e-message "Switching to gmail.com") - (setq mu4e-compose-signature (mssola-mu4e-signature "gmail")) - (setq mu4e-sent-messages-behavior 'delete) - (mssola-smtp "smtp.gmail.com" 587)) - :match-func (lambda (msg) - (when msg - (mu4e-message-maildir-matches msg "^/gmail"))) - :vars '( - (user-mail-address . "mikisabate@gmail.com") - (mu4e-reply-to-address . "mikisabate@gmail.com") - (mu4e-drafts-folder . "/gmail/Drafts") - (mu4e-sent-folder . "/gmail/Sent") - (mu4e-refile-folder . "/gmail/All") - (mu4e-trash-folder . "/gmail/Trash"))) - - ;; City hall - ,(make-mu4e-context - :name "ajuntament" - :enter-func (lambda () - (mu4e-message "Switching to mail.diba.cat") - (setq mu4e-compose-signature (mssola-mu4e-signature "ajuntament")) - (setq mu4e-sent-messages-behavior 'sent) - (mssola-smtp "mail.diba.cat" 587) - (setq smtpmail-local-domain "capellades.cat")) - :match-func (lambda (msg) - (when msg - (mu4e-message-maildir-matches msg "^/ajuntament"))) - :vars '( - (user-mail-address . "sabatesm@capellades.cat") - (mu4e-reply-to-address . "sabatesm@capellades.cat") - (mu4e-drafts-folder . "/ajuntament/Esborranys") - (mu4e-sent-folder . "/ajuntament/Elements enviats") - (mu4e-refile-folder . "/ajuntament/Arxiu") - (mu4e-trash-folder . "/ajuntament/Elements suprimits"))) - - ;; suse.com - ,(make-mu4e-context - :name "comsuse" - :enter-func (lambda () - (mu4e-message "Switching to suse.com") - (setq mu4e-compose-signature (mssola-mu4e-signature "comsuse")) - (setq mu4e-sent-messages-behavior 'sent) - (mssola-smtp "smtp.office365.com" 587)) - :match-func (lambda (msg) - (when msg - (mu4e-message-maildir-matches msg "^/susecom"))) - :vars `( - (user-mail-address . "msabate@suse.com") - (mu4e-reply-to-address . "msabate@suse.com") - (mu4e-drafts-folder . "/susecom/Esborranys") - (mu4e-sent-folder . "/susecom/Elements enviats") - (mu4e-refile-folder . ,(suse-refile-folder "susecom")) - (mu4e-trash-folder . "/susecom/Elements suprimits"))) - - ;; suse.de - ,(make-mu4e-context - :name "desuse" - :enter-func (lambda () - (mu4e-message "Switching to suse.de") - (setq mu4e-compose-signature (mssola-mu4e-signature "desuse")) - (setq mu4e-sent-messages-behavior 'sent) - (mssola-smtp "imap.suse.de" 587)) - :match-func (lambda (msg) - (when msg - (mu4e-message-maildir-matches msg "^/susede"))) - :vars `( - (user-mail-address . "msabate@suse.de") - (mu4e-reply-to-address . "msabate@suse.de") - (mu4e-drafts-folder . "/susede/Drafts") - (mu4e-sent-folder . "/susede/Sent") - (mu4e-refile-folder . ,(suse-refile-folder "susede")) - (mu4e-trash-folder . "/susede/Trash"))))) -#+END_SRC - -If mu4e cannot figure things out, ask me. - -#+BEGIN_SRC elisp - (setq mu4e-context-policy 'ask) - (setq mu4e-compose-context-policy 'ask) -#+END_SRC - -Fill the =mu4e-user-mail-address-list= variable with the contexts. - -#+BEGIN_SRC elisp - (setq mu4e-user-mail-address-list - (delq nil - (mapcar (lambda (context) - (when (mu4e-context-vars context) - (cdr (assq 'user-mail-address - (mu4e-context-vars context))))) - mu4e-contexts))) -#+END_SRC - -Setting my bookmarks - -#+BEGIN_SRC elisp -(setq mu4e-bookmarks - '(("maildir:/gmail/inbox OR maildir:/susecom/inbox OR maildir:/susede/inbox OR maildir:/ajuntament/inbox" "Inbox Folders" ?n) - ("maildir:/gmail/Sent OR maildir:/susecom/Elements\\ enviats OR maildir:/susede/Sent OR maildir:/ajuntament/Elements\\ enviats" "Sent Folders" ?s) - ("flag:unread AND NOT flag:trashed" "Unread messages" ?u) - ("date:today..now" "Today's messages" ?t))) -#+END_SRC - -Sign outgoing emails always. - -#+BEGIN_SRC elisp - (add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime) -#+END_SRC - -To avoid UID clashes. See [[http://pragmaticemacs.com/emacs/fixing-duplicate-uid-errors-when-using-mbsync-and-mu4e/][this]]. - -#+BEGIN_SRC elisp - (setq mu4e-change-filenames-when-moving t) -#+END_SRC - -Miscellaneous settings. - -#+BEGIN_SRC elisp -(setq mu4e-html2text-command "w3m -T text/html" - mu4e-attachment-dir "~/Downloads" - mu4e-headers-date-format "%Y-%m-%d %H:%M" - message-citation-line-format "%N @ %Y-%m-%d %H:%M %Z:\n" - message-citation-line-function 'message-insert-formatted-citation-line - message-kill-buffer-on-exit t - mu4e-get-mail-command "mbsync -aqV" - mu4e-update-interval 600 - mu4e-compose-dont-reply-to-self t - mu4e-compose-format-flowed t - mu4e-view-show-addresses t - mu4e-headers-skip-duplicates t - mu4e-headers-include-related t - mu4e-headers-auto-update t) -#+END_SRC - -The headers to show in the headers list a pair of a field and its width, -with `nil' meaning 'unlimited' (better only use that for the last field. -These are the defaults: - -#+BEGIN_SRC elisp - (setq mu4e-headers-fields - '( (:date . 18) - (:mailing-list . 15) - (:from-or-to . 20) - (:subject . nil))) -#+END_SRC - -Add as a header action to toggle gnus mode for the view mode. I'm doing this -because this is way better to visualize attached .eml emails. - -#+BEGIN_SRC elisp -(defun mssola-toggle-gnus-mode (msg) - "Toggle gnus on view mode from now on." - (if mu4e-view-use-gnus - (setq mu4e-view-use-gnus nil) - (setq mu4e-view-use-gnus t))) - -(add-to-list 'mu4e-headers-actions - '("gnus mode toggle" . mssola-toggle-gnus-mode) t) -#+END_SRC - -Show images - -#+BEGIN_SRC elisp - (setq mu4e-view-show-images t - mu4e-view-image-max-width 800) - - ; Use imagemagick, if available - (when (fboundp 'imagemagick-register-types) - (imagemagick-register-types)) -#+END_SRC - -Correct some key bindings that are screwed up by =evil-mode=: - -#+BEGIN_SRC elisp -(evil-define-key 'normal mu4e-view-mode-map - ";" 'mu4e-context-switch - "e" 'mu4e-view-save-attachment - "F" 'mu4e-compose-forward) -#+END_SRC - -As of 0.9.18 and GNU Emacs 25, the =mu4e-action-with-xwidget= can be used to -render an HTML message with Webkit. - -#+BEGIN_SRC elisp - (if (>= emacs-major-version 25) - (add-to-list 'mu4e-view-actions - '("webkit" . mu4e-action-view-with-xwidget))) -#+END_SRC - -Look for =mu4e-msg2pdf= in the exec path. The reason for this is that the OBS -package installs mu's =toys= into the exec path, but =mu4e= doesn't really count -on it. - -#+BEGIN_SRC elisp - (let ((exec (locate-file "msg2pdf" exec-path exec-suffixes))) - (if exec - (setq mu4e-msg2pdf exec))) -#+END_SRC - -Adding hooks for composing and viewing messages. - -#+BEGIN_SRC elisp - (defun mssola-compose-mode () - "My settings for message composition." - - ; If we are composing an email from scratch, it's more convenient to be in - ; insert mode. Otherwise start with normal mode. - (with-eval-after-load 'evil - (if mu4e-compose-parent-message - (evil-set-initial-state 'mu4e-compose-mode 'normal) - (evil-set-initial-state 'mu4e-compose-mode 'insert))) - - ; Guess hard newlines - (use-hard-newlines t 'guess) - - ; So it's easy to encrypt/decrypt emails. - (epa-mail-mode) - - ; Spellz - (flyspell-mode)) - - (add-hook 'mu4e-compose-mode-hook 'mssola-compose-mode) - - ; I want to read messages in the format that the sender used. I'm also - ; enabling epa-mail-mode, so it's easy to decrypt received emails. - (add-hook 'mu4e-view-mode-hook - (lambda () - (epa-mail-mode) - (visual-line-mode 1))) -#+END_SRC - -I want desktop notifications when receiving email. - -#+BEGIN_SRC elisp - (use-package mu4e-alert - :ensure t - :config - - ; Notify me for unread emails from my inbox. - (mu4e-alert-set-default-style 'libnotify) - (add-hook 'after-init-hook #'mu4e-alert-enable-notifications) - (add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display) - (setq mu4e-alert-interesting-mail-query - (concat - "(maildir:/gmail/inbox OR maildir:/susecom/inbox OR maildir:/susede/inbox OR maildir:/ajuntament/inbox) " - "AND flag:unread AND NOT flag:trashed")) - (setq mu4e-alert-email-notification-types '(count))) - - ; Evil mode in mu4e - (with-eval-after-load 'evil - (use-package evil-mu4e - :ensure t - :config - - ; Idea taken from evil-mu4e.el - (defvar mssola-evil-mu4e-mode-map-bindings - `((,evil-mu4e-state mu4e-headers-mode-map "\C-u" evil-scroll-up) - (,evil-mu4e-state mu4e-main-mode-map "\C-u" evil-scroll-up) - (,evil-mu4e-state mu4e-view-mode-map "h" evil-backward-char))) - - (dolist (binding mssola-evil-mu4e-mode-map-bindings) - (evil-define-key - (nth 0 binding) (nth 1 binding) (nth 2 binding) (nth 3 binding))))) -#+END_SRC - -And finally define a proper shortcut. - -#+BEGIN_SRC elisp - ; The trailing parenthesis closes the "(when (featurep 'mu4e)" statement from - ; the very beginning. - (global-set-key (kbd "C-c m") 'mu4e))) -#+END_SRC - -* org - -** TODO org template for creating "article" and similar stuff - -[[http://orgmode.org/][org mode]] is an incredible tool that keeps me organized: TODOs, notes, agenda, -etc. Moreover, it's built in GNU Emacs: - -#+BEGIN_SRC elisp -(require 'org) -#+END_SRC - -** General settings - -First of all, let me define some helper functions. - -#+BEGIN_SRC elisp - (defun mssola-org-skip-if-priority (priority &optional subtree) - "Skip an agenda item if it has a priority of PRIORITY. - PRIORITY may be one of the characters ?A, ?B, or ?C. - Skips the current entry unless SUBTREE is not nil. This function has been - copied from @aaronbieber." - - (let ((end (if subtree (save-excursion (org-end-of-subtree t)) - (save-excursion (progn (outline-next-heading) (1- (point)))))) - (pri-value (* 1000 (- org-lowest-priority priority))) - (pri-current (org-get-priority (thing-at-point 'line t)))) - (if (= pri-value pri-current) - end - nil))) - - (defun mssola-org-skip-if-not-closed-in-day (time &optional subtree) - "Skip entries that were not closed in the given TIME. - Skip the current entry unless SUBTREE is not nil, in which case skip - the entire subtree. Idea taken from @aaronbieber" - - (let ((end (if subtree (save-excursion (org-end-of-subtree t)) - (save-excursion (progn (outline-next-heading) (1- (point)))))) - (day-prefix (format-time-string "%Y-%m-%d" time))) - - (if (save-excursion - (and (re-search-forward org-closed-time-regexp end t) - (string= (substring (match-string-no-properties 1) 0 10) day-prefix))) - nil - end))) -#+END_SRC - -Some general UI settings for org mode. - -#+BEGIN_SRC elisp -(setq org-src-tab-acts-natively t - org-confirm-babel-evaluate nil - org-edit-src-content-indentation 0) - -(setq org-todo-keywords - '((sequence "TODO(t)" "|" "DONE(d!)") - (sequence "IDEA(i)" "WORKING(w)" "|" "USED(u@/!)" "DISCARDED(x@/!)"))) - -(setq org-todo-keyword-faces - '(("TODO" . org-todo) - ("IDEA" . font-lock-constant-face) - ("WORKING" . font-lock-constant-face) - ("DONE" . org-done) - ("USED" . org-done) - ("DISCARDED" . org-done))) -#+END_SRC - -Logging settings. - -#+BEGIN_SRC elisp - (setq org-log-done t) - (setq org-log-redeadline (quote time)) - (setq org-log-reschedule (quote time)) -#+END_SRC - -Where org files reside. - -#+BEGIN_SRC elisp - (setq org-agenda-files '("~/org/")) -#+END_SRC - -** Publishing - -In order to publish files into HTML, I would like to have =htmlize= installed. -This package allows org to export to HTML in a better way (e.g. allowing code -blocks to be converted into HTML as well, so we can properly colorize it). - -#+BEGIN_SRC elisp -(use-package htmlize - :ensure t) -#+END_SRC - -And now let's set all the related settings. - -#+BEGIN_SRC elisp -(setq org-src-fontify-natively t - org-html-include-timestamps nil - org-html-toplevel-hlevel 2 - org-html-htmlize-output-type 'css - org-export-with-section-numbers nil - org-export-with-sub-superscripts nil - org-export-htmlize-output-type 'css) -#+END_SRC - -Make sure to use the proper template when exporting to ODT: - -#+BEGIN_SRC elisp -(setq org-odt-styles-file "~/Documents/Templates/mssola.ott") -#+END_SRC - -Sometimes it's useful to export to LaTeX. That is, when you are simply writing a -quick document that will end up being converted into LaTeX and finally into PDF: - -#+BEGIN_SRC elisp -(require 'ox-latex) - -(unless (boundp 'org-latex-classes) - (setq org-latex-classes nil)) - -(add-to-list 'org-latex-classes - '("article" - "\\documentclass{article}" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) -#+END_SRC - -You can also export org documents to man pages. In order to do so, you have to -perform this first: - -#+BEGIN_SRC elisp -(require 'ox-man) -#+END_SRC - -Setup a function to toggle =org-publish-current-file= on save: - -#+BEGIN_SRC elisp -(defun toggle-org-publish-current-file-on-save () - (interactive) - (if (memq 'org-publish-current-file after-save-hook) - (progn - (remove-hook 'after-save-hook 'org-publish-current-file t) - (message "Disabled org-publish-current-file for current buffer...")) - (add-hook 'after-save-hook 'org-publish-current-file nil t) - (message "Enabled org-publish-current-file for current buffer..."))) -#+END_SRC - -Also hide the "Footnotes: " title on footnotes: - -#+BEGIN_SRC elisp -(setq org-html-footnotes-section "
- -
-%s -
-
") -#+END_SRC - -Last but not least, some handy shortcuts: - -#+BEGIN_SRC elisp -(with-eval-after-load "org" - (define-key org-mode-map (kbd "") 'org-latex-export-to-pdf) - (define-key org-mode-map (kbd "") 'org-odt-export-to-odt)) -#+END_SRC - -** Agenda - -Custom commands for =org-agenda=. - -#+BEGIN_SRC elisp - (setq org-agenda-custom-commands - '(("p" "Printed agenda" - ; Daily agenda with a 2-weeks deadline warning. Tasks are - ; represented as [ ] items. - ((agenda "" - ((org-agenda-ndays 1) - (org-deadline-warning-days 14) - (org-agenda-todo-keyword-format "[ ]") - (org-agenda-scheduled-leaders '("" "")))) - - ; Display a "High Priority" list of tasks on top. - (tags "PRIORITY=\"A\"" - ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) - (org-agenda-sorting-strategy '(tag-up priority-down)) - (org-agenda-todo-keyword-format "") - (org-agenda-overriding-header "\nHigh priority\n--------------\n"))) - - - ; All tasks except those already listed as high priority or - ; ideas. Scheduled and deadlines are also ignored here. - (alltodo "" - ((org-agenda-skip-function '(or (mssola-org-skip-if-priority ?A) - (org-agenda-skip-entry-if 'todo '("IDEA" "WORKING")) - (org-agenda-skip-if nil '(scheduled deadline)))) - (org-agenda-sorting-strategy '(tag-up priority-down)) - (org-agenda-todo-keyword-format "") - (org-agenda-overriding-header "\nAll tasks\n----------\n"))) - - ; List of ideas. - (todo "IDEA" - ((org-agenda-overriding-header "\nIdeas\n------\n") - (org-agenda-todo-keyword-format "")))) - - ((org-agenda-compact-blocks t) - (org-agenda-remove-tags t))) - - ; List of done items. Useful for standups, review meetings, weekly - ; reports, etc. - ("d" "Done items" - ; First show the items done yesterday. Useful for standups. - ((todo "DONE" - ((org-agenda-overriding-header "Done yesterday\n---------------\n") - (org-agenda-skip-function - '(mssola-org-skip-if-not-closed-in-day - (time-subtract (current-time) (seconds-to-time 86400)))) - (org-agenda-todo-keyword-format ""))) - - ; Then show what I've done today. - (todo "DONE" - ((org-agenda-overriding-header "\nDone today\n-----------\n") - (org-agenda-skip-function - '(mssola-org-skip-if-not-closed-in-day - (current-time))) - (org-agenda-todo-keyword-format ""))) - - ; Finally show what I've been doing in the past 15 days. Useful for - ; review meetings and weekly reports. - (todo "DONE" - ((org-agenda-start-day "-15d") - (org-agenda-span 15) - (org-agenda-start-on-weekday nil) - (org-agenda-todo-keyword-format "") - (org-agenda-scheduled-leaders '("" "")) - (org-agenda-overriding-header "\nDone during the past 15 days\n-----------------------------\n")))) - - ((org-agenda-compact-blocks t) - (org-agenda-remove-tags t))))) -#+END_SRC - -The prefix for the different kinds of types being used. - -#+BEGIN_SRC elisp - (setq org-agenda-prefix-format '((agenda . "%t%s") - (tags . "%c:%s") - (todo . "%c:%t%s"))) -#+END_SRC - -Set up a key binding for org-agenda. - -#+BEGIN_SRC elisp -(global-set-key (kbd "C-c a") 'org-agenda) -#+END_SRC - -** Capture - -Set the default notes file and the key binding. - -#+BEGIN_SRC elisp -(setq org-default-notes-file (concat org-directory "/notes.org")) -(define-key global-map "\C-cc" 'org-capture) -#+END_SRC - -And finally set =org-capture-templates=. - -#+BEGIN_SRC elisp -(setq org-capture-templates - `(("t" "todo" entry (file "") "* TODO %?\n%U\n") - ("i" "idea" entry (file "") "* %? :IDEA:\n%U\n%a\n"))) -#+END_SRC - -** Publish project - -I write blog posts with org-mode. Here's the trick: - -#+BEGIN_SRC elisp -(setq org-publish-project-alist - '(("org-mssola" - ;; Path to your org files. - :base-directory "~/src/mssola/jo/org/" - :base-extension "org" - - ;; Path to your Jekyll project. - :publishing-directory "~/src/mssola/jo/_i18n" - :recursive t - :publishing-function org-html-publish-to-html - :headline-levels 4 - :html-extension "html" - :body-only t ;; Only export section between - ) - - ("mssola" :components ("org-mssola")))) -#+END_SRC - -** Other - -Insert a value in org mode. See this [[http://emacs.stackexchange.com/questions/2206/i-want-to-have-the-kbd-tags-for-my-blog-written-in-org-mode][StackExchange answer]]. - -#+BEGIN_SRC elisp -(defun endless/insert-key (key) - "Ask for a key then insert its description. -Will work on both org-mode and any mode that accepts plain html." - (interactive "kType key sequence: ") - (let* ((is-org-mode (derived-mode-p 'org-mode)) - (tag (if is-org-mode - "@@html:%s@@" - "%s"))) - (if (null (equal key "\r")) - (insert - (format tag (help-key-description key nil))) - (insert (format tag "")) - (forward-char (if is-org-mode -8 -6))))) - -(define-key org-mode-map "\C-ck" #'endless/insert-key) -#+END_SRC - -Define profiles. - -#+BEGIN_SRC elisp -;; Variables - -(defvar mssola-org-profiles - '(("minimal" . mssola-org-minimal) - ("monthly" . mssola-org-monthly)) - "Defined profiles for organization matters.") - -(defvar mssola-org-default-profile "minimal" - "The default profile for mssola-org.") - -;; Profiles - -(defun mssola-org-minimal () - "Load a minimal set of files." - (find-file (concat (file-name-as-directory org-directory) "setmana.org"))) - -(defun mssola-org-monthly () - "Load a set of files useful for monthly planning." - (find-file (concat (file-name-as-directory org-directory) "setmana.org")) - (split-window-right) - (windmove-right) - (find-file (concat (file-name-as-directory org-directory) "any.org")) - (windmove-left)) - -;; Functions - -(defun mssola-org (&optional profile) - "Setup a frame for organizational matters. -PROFILE is the profile to be picked when given. If it's not given, then the -user will be prompted to provide it." - (interactive) - - (delete-other-windows) - (unless profile - (setq profile (completing-read "Give me the profile: " - (mapcar 'car mssola-org-profiles) nil t))) - (funcall (cdr (assoc profile mssola-org-profiles)))) - -(defun mssola-org-default () - "Setup a frame for organizational matters given a default profile has been set." - (interactive) - - (mssola-org mssola-org-default-profile)) - -(define-key global-map (kbd "C-c C-o") #'mssola-org-default) -(define-key global-map (kbd "C-c M-o") #'mssola-org) -#+END_SRC - -** TODO shortcut for making an org link, and transforming a link into a proper org link -** TODO make it work with evil -** TODO Proper keybindings for quick access. - -** TODO shortcuts for stuff like: create something urgent for today - -* IRC - -I'm using [[https://www.gnu.org/software/emacs/manual/html_mono/erc.html][ERC]] for IRC. - -#+BEGIN_SRC elisp -(use-package erc - :config -#+END_SRC - -First of all, let's add some basic modules. - -#+BEGIN_SRC elisp - (dolist (mod '(autojoin track truncate)) - (add-to-list 'erc-modules mod)) -#+END_SRC - -Setting up basic stuff. - -#+BEGIN_SRC elisp - (setq erc-hide-list '("PART") - erc-prompt (lambda () (concat (buffer-name) ">")) - erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE") - erc-server-coding-system '(utf-8 . utf-8) - erc-kill-buffer-on-part t - erc-kill-queries-on-quit t - erc-kill-server-buffer-on-quit t - erc-fill-column 100 - erc-fill-prefix "" - erc-timestamp-format "[%H:%M] " - erc-insert-timestamp-function 'erc-insert-timestamp-left - erc-insert-away-timestamp-function 'erc-insert-timestamp-left - erc-hide-timestamps nil - erc-whowas-on-nosuchnick t - erc-public-away-p nil - erc-echo-notice-always-hook '(erc-echo-notice-in-minibuffer) - erc-auto-set-away nil - erc-autoaway-message "%i seconds out..." - erc-away-nickname "msabate" - erc-enable-logging t - erc-query-on-unjoined-chan-privmsg t) -#+END_SRC - -Let's log messages whenever I receive/send them. The other option is to only do -that on =/quit= or =/part=, but it's better to be safe than sorry. - -#+BEGIN_SRC elisp - (require 'erc-log) - (erc-log-enable) - - (setq erc-log-channels-directory "~/.emacs.d/erc" - erc-save-buffer-on-part nil - erc-save-queries-on-quit nil - erc-log-write-after-send t - erc-log-write-after-insert t) -#+END_SRC - -Servers and channels to auto-join. - -#+BEGIN_SRC elisp - (setq erc-autojoin-channels-alist - '(("irc.freenode.net" "#gnu" "#emacs") - ("irc.nue.suse.com" "#suse" "#docker"))) -#+END_SRC - -Use the =erc-hl-nicks= package, so highlight support for nicknames is better. - -#+BEGIN_SRC elisp -(use-package erc-hl-nicks - :ensure t - :init - (with-eval-after-load 'erc - (add-to-list 'erc-modules 'hl-nicks))) -#+END_SRC - -I want to have a desktop notification whenever someone mentions my name. For -this, I'm using the =erc-notifications= package which is built in ERC since -GNU Emacs 24.3. - -#+BEGIN_SRC elisp -(with-eval-after-load 'erc - (setq erc-notifications-icon - (concat - "/usr/share/emacs/" - (format "%s.%s" emacs-major-version emacs-minor-version) - "/etc/images/icons/hicolor/24x24/apps/emacs.png")) - (add-to-list 'erc-modules 'notifications)) -#+END_SRC - -At this point, we can safely update all the loaded ERC modules. - -#+BEGIN_SRC elisp - (add-hook 'erc-connect-pre-hook - (lambda (x) (erc-update-modules))) -#+END_SRC - -Start some modules which won't do it by default. Moreover, according to the [[https://www.emacswiki.org/emacs/ErcFilling][wiki]] -=auto-fill-mode= should be disabled if I'm using =erc-fill-mode=. - -#+BEGIN_SRC elisp - (add-hook 'erc-mode-hook - '(lambda () - (erc-track-mode t) - (auto-fill-mode -1) - (erc-log-mode 1) - (erc-autojoin-mode 1))) -#+END_SRC - -And now define a function to connect to both IRC servers. - -#+BEGIN_SRC elisp - (defun mssola-erc () - "Join pre-specified servers and channels." - - (interactive) - - (erc :server "irc.freenode.net" :port 6667 :nick "mssola") - (erc-tls :server "irc.nue.suse.com" :port 6697 :nick "mssola")) - - (global-set-key (kbd "C-c i") 'mssola-erc)) -#+END_SRC - -* Languages - -** General - -First of all, define a function that identifies some warning keywords -(e.g. TODO). This function can then be applied to the proper mode. - -#+BEGIN_SRC elisp - (defun warnings-mode-hook () - "Hook for enabling the warning face on strings with a warning prefix." - - (font-lock-add-keywords nil - '(("\\(XXX\\|FIXME\\|TODO\\|HACK\\|NOTE\\|BUG\\)" - 1 font-lock-warning-face prepend)))) -#+END_SRC - -Text mode is not a programming language, but it's used quite often in this -context too. In this case, I want spell check and =wc-mode= activated. - -#+BEGIN_SRC elisp - (add-hook 'text-mode-hook - (lambda () - (flyspell-mode 1) - (wc-mode 1))) -#+END_SRC - -** Shell - -#+BEGIN_SRC elisp -(use-package bats-mode - :ensure t) -#+END_SRC - -** Lisp - -Emacs lisp needs =rainbow-delimiters=, so the amount of parenthesis is less -confusing. Moreover, I'm also enabling =eldoc-mode= and the aforementioned -=warnings-mode-hook=. - -#+BEGIN_SRC elisp - (add-hook 'emacs-lisp-mode-hook - (lambda () - (eldoc-mode 1) - (warnings-mode-hook) - (rainbow-delimiters-mode 1) - ; https://github.com/jhenahan/emacs.d/blob/master/emacs-init.org#emacs-lisp - (setq mode-name "ξ"))) -#+END_SRC - -Configure =ielm= with the proper ELisp utilities: - -#+BEGIN_SRC elisp -(use-package ielm - :config - (add-hook 'ielm-mode-hook #'eldoc-mode) - (add-hook 'ielm-mode-hook #'rainbow-delimiters-mode) - (global-set-key (kbd "C-x i e") 'ielm) - (global-set-key (kbd "C-x i l") 'ielm)) -#+END_SRC - -** C and C++ - -C and C++ only require the =warnings-mode-hook= function, spell checking for the -comments and the usage of tabs instead of spaces. - -#+BEGIN_SRC elisp -; Note that C-common includes languages with a similar syntax of C. -(add-hook 'c-mode-common-hook 'warnings-mode-hook) -(add-hook 'c-mode-common-hook (lambda() (flyspell-prog-mode))) - -;; C -(add-hook 'c-mode-hook - (lambda () (setq indent-tabs-mode t))) - -;; C++ -(add-hook 'c++-mode-hook - (lambda () (setq indent-tabs-mode t))) -#+END_SRC - -CMake for y'all. - -#+BEGIN_SRC elisp - (use-package cmake-mode - :ensure t - :config - - (setq auto-mode-alist - (append - '(("CMakeLists\\.txt\\'" . cmake-mode)) - '(("\\.cmake\\'" . cmake-mode)) - auto-mode-alist)) - - (use-package cmake-font-lock - :ensure t - :config - - (add-hook 'cmake-mode-hook 'cmake-font-lock-activate) - (add-hook 'yaml-mode-hook 'warnings-mode-hook))) -#+END_SRC - -** Ruby - -Include warning keywords in Ruby and do not automatically include the encoding -magic comment: - -#+BEGIN_SRC elisp -(use-package ruby-mode - :config - (setq ruby-insert-encoding-magic-comment nil) - (add-hook 'ruby-mode-hook #'subword-mode) - (add-hook 'ruby-mode-hook 'warnings-mode-hook)) -#+END_SRC - -And give me an IRB instance: - -#+BEGIN_SRC elisp -(use-package inf-ruby - :ensure t - :config - (add-hook 'ruby-mode-hook #'inf-ruby-minor-mode) - (global-set-key (kbd "C-x i r") 'inf-ruby)) -#+END_SRC - -** Go - -And now my Go configuration. This includes stuff like the usage of =goimports=, -=gofmt= on save, among many other useful things. - -#+BEGIN_SRC elisp - (defun mssola-go-mode () - "My configuration for Go mode." - - ; Use goimports instead of go-fmt - (setq gofmt-command "goimports") - - ; Call Gofmt before saving - (add-hook 'before-save-hook 'gofmt-before-save) - - ; Integration flycheck with Go - (add-to-list 'load-path - (concat (getenv "GOPATH") "/src/github.com/dougm/goflymake")) - (require 'go-flycheck) - - (setq indent-tabs-mode t) - (flyspell-prog-mode) - - ; eldoc support - (use-package go-eldoc - :ensure t - :config - (require 'go-eldoc))) - - ;; Go - (use-package go-mode - :ensure t - :pin melpa-stable - :config - - (add-hook 'go-mode-hook 'warnings-mode-hook) - (add-hook 'go-mode-hook 'go-eldoc-setup) - (add-hook 'go-mode-hook 'mssola-go-mode)) -#+END_SRC - -** Python - -Install =elpy= as the environment for Python support: - -#+BEGIN_SRC elisp -(use-package elpy - :ensure t - :config - (advice-add 'python-mode :before 'elpy-enable) - (when (require 'flycheck nil t) - (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) - (add-hook 'elpy-mode-hook 'flycheck-mode))) -#+END_SRC - -Automatically use =autopep8= on save: - -#+BEGIN_SRC elisp -(use-package py-autopep8 - :ensure t - :config - (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save)) -#+END_SRC - -** Rust - -Install =rust-mode= and add some hooks to make it friendlier. - -#+BEGIN_SRC elisp -(use-package rust-mode - :ensure t - :config - - (add-hook 'before-save-hook - #'(lambda () - (when (eq major-mode 'rust-mode) - (rust-format-buffer)))) - - (use-package flycheck-rust - :ensure t - :config - - (add-hook 'flycheck-mode-hook #'flycheck-rust-setup))) -#+END_SRC - -** Tabs vs spaces - -Tabs or spaces? [[https://www.emacswiki.org/emacs/TabsSpacesBoth][Both]]. The =smart-tabs-mode= has the philosophy of: tabs for -indentation, spaces for alignment. This is only applied in languages where I'm -usings tabs for indentation (C, C++ and Go). - -#+BEGIN_SRC elisp - (use-package smart-tabs-mode - :ensure t - :config - (smart-tabs-add-language-support golang go-mode-hook - ((c-indent-line . c-basic-offset) - (c-indent-region . c-basic-offset))) - (smart-tabs-insinuate 'c 'c++ 'golang)) -#+END_SRC - -** Inferior markup languages. - -#+BEGIN_SRC elisp - ;; Markdown mode with preview mode in the browser. - (use-package markdown-mode - :ensure t - :config - - ; This is the one that I got from openSUSE. - (custom-set-variables - '(markdown-command "/usr/bin/markdown-calibre")) - - ; Preview mode does its things through websockets, so it's a requirement. - ; After that, we can safely require it. - (use-package websocket - :ensure t - :config - (use-package markdown-preview-mode - :ensure t))) - - ; YAML - (use-package yaml-mode - :ensure t - :config - - (add-hook 'yaml-mode-hook 'warnings-mode-hook)) -#+END_SRC - -** Web-related stuff. - -Slim and SCSS. - -#+BEGIN_SRC elisp -(use-package slim-mode - :ensure t) - -(use-package scss-mode - :ensure t - :config - - (setq scss-compile-at-save nil) - (add-hook 'yaml-mode-hook 'warnings-mode-hook)) - -(use-package coffee-mode - :ensure t) -#+END_SRC - -Languages specific for backend code like PHP, and =web-mode=, which provides a -bundle of features which are interesting for web-related stuff. - -#+BEGIN_SRC elisp -(use-package php-mode - :ensure t) - -(use-package web-mode - :ensure t - :config - - (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) - (add-to-list 'auto-mode-alist '("\\.jinja\\'" . web-mode)) - (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) - - (add-hook 'web-mode-hook - (lambda () - (setq web-mode-markup-indent-offset 2) - (setq web-mode-css-indent-offset 2) - (setq web-mode-code-indent-offset 2))) - - (add-hook 'js-mode-hook - (lambda () - (setq js-indent-level 2) - (rainbow-delimiters-mode 1))) - - (use-package vue-mode - :ensure t - :config - (setq mmm-submode-decoration-level 0)) - - ; React: treat it as a derived mode. Idea taken from spacemacs. - (define-derived-mode react-mode web-mode "react") - (add-to-list 'auto-mode-alist '("\\.jsx\\'" . react-mode)) - (add-to-list 'auto-mode-alist '("\\.react.js\\'" . react-mode)) - - (add-hook 'react-mode-hook - (lambda () - (yas-activate-extra-mode 'js-mode) - (web-mode-set-content-type "jsx") - (setq-local web-mode-enable-auto-quoting nil) - (rainbow-delimiters 1)))) -#+END_SRC - -The =json-reformat= package provides functions for reformatting JSON strings. It -happens from time to time that I have to read JSON output from responses, and it -can be frustrating without proper formatting. - -#+BEGIN_SRC elisp -(use-package json-reformat - :ensure t) -#+END_SRC - -** Devops - -Highlighting for Dockerfiles. - -#+BEGIN_SRC elisp - (use-package dockerfile-mode - :ensure t - :config - - (add-to-list 'auto-mode-alist '("Dockerfile" . dockerfile-mode))) -#+END_SRC - -Stuff from Hashicorp like terraform and HCL. - -#+BEGIN_SRC elisp -(use-package terraform-mode - :ensure t - :config - - (terraform-format-on-save-mode)) - -(use-package hcl-mode - :ensure t) -#+END_SRC - -#+BEGIN_SRC elisp -(use-package salt-mode - :ensure t) -#+END_SRC - -** Others - -The [[https;//github.com/mssola/soria][soria]] theme has the =soria-purple-identifiers= hook. This hook instructs -the theme to use purple for identifiers instead of the default color. This is a -remnant from my Vim times, and I only apply it to some languages (random -criteria really). - -#+BEGIN_SRC elisp - (dolist (lang-hook '(ruby-mode-hook - php-mode-hook - perl-mode-hook - emacs-lisp-mode-hook)) - (add-hook lang-hook 'soria-purple-identifiers)) -#+END_SRC - -** LaTeX - -Let's use [[https://www.gnu.org/software/auctex/][Auctex]] for LaTeX files. - -#+BEGIN_SRC elisp -(use-package tex - :ensure auctex - :config - (setq TeX-auto-save t) - (setq TeX-parse-self t) - (setq-default TeX-master nil)) -#+END_SRC - -* WoMan - -=WoMan= is a package that is included inside of GNU Emacs by default, and that -takes care of visualizing man pages. Let's properly setup Evil mode for this: - -#+BEGIN_SRC elisp -(with-eval-after-load "evil" - (evil-set-initial-state 'woman-mode 'normal) - (evil-define-key 'normal woman-mode-map - "J" 'Man-next-section - "K" 'Man-previous-section - "\C-h" 'evil-window-left - "\C-l" 'evil-window-right - "\C-j" 'evil-window-down - "\C-k" 'evil-window-up - "\C-u" 'evil-scroll-up)) -#+END_SRC - -Finally, I want man pages to fill all the frame: - -#+BEGIN_SRC elisp -(setq woman-fill-frame t) -#+END_SRC - -Start =WoMan= as a subcommand of the help command: - -#+BEGIN_SRC elisp -(define-key 'help-command (kbd "M-m") #'woman) -#+END_SRC - -* Misc - -Install a set of useful functions from [[https://github.com/bbatsov][@bbatsov]]. The bindings are following -Emacs style instead of being more Vim-like on purpose (I don't want to put -too many things into my leader and these shortcuts look sensible to me). - -#+BEGIN_SRC elisp -(use-package crux - :ensure t - :config - - (global-set-key (kbd "C-c d") 'crux-delete-file-and-buffer) - (global-set-key (kbd "C-c r") 'crux-rename-file-and-buffer) - (global-set-key (kbd "C-c n") 'crux-cleanup-buffer-or-region) - (global-set-key (kbd "C-") 'crux-kill-line-backwards) - (global-set-key [remap move-beginning-of-line] 'crux-move-beginning-of-line) - (global-set-key (kbd "C-c o") 'crux-open-with)) -#+END_SRC - -** Emojis - -Display emojis in buffer! - -#+BEGIN_SRC elisp -(use-package emojify - :ensure t - :config - - (add-hook 'after-init-hook #'global-emojify-mode) - (setq emojify-composed-text-p nil) - (setq emojify-emoji-styles '(unicode github))) -#+END_SRC - -* Credits - -I've built this file by simply scavenging from other people's emacs.d/dotfiles -repositories. I have taken lots of pieces from here and there, but most notably: - -- [[https://github.com/ereslibre/dotfiles][@ereslibre]] -- [[https://github.com/dmacvicar/dotfiles][@dmacvicar]] -- [[https://github.com/bbatsov/emacs.d][@bbatsov]] -- [[https://github.com/aaronbieber/dotfiles][@aaronbieber]] -- [[https://github.com/purcell/emacs.d][@purcell]] -- [[https://github.com/sachac/.emacs.d][@sachac]] ([[http://pages.sachachua.com/.emacs.d/Sacha.html][HTML version]]) -- [[https://github.com/larstvei/dot-emacs][@larstvei]] - -* License - -#+BEGIN_SRC text :tangle no - Copyright (C) 2014-2019 Miquel Sabaté Solà - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -#+END_SRC diff --git a/emacs/lisp/README.md b/emacs/lisp/README.md deleted file mode 100644 index 64e6da0..0000000 --- a/emacs/lisp/README.md +++ /dev/null @@ -1,18 +0,0 @@ -## GNU Emacs Modules written by Miquel Sabaté Solà - -This directory contains Lisp modules I've written. - -### g.el - -A port of my [g](https://github.com/mssola/g) script for GNU Emacs. This is not -helpful all the time, but it does help whenever Projectile does not cover me. -This module implements the following interactive functions: - -- `g`: allows users to jump through a shortcut. After performing the jump, the - user will be presented with the `dired` mode. -- `g-add`: add a new shortcut that points to a valid path. -- `g-remove`: remove an existing shortcut. -- `g-list`: list all the available shortcuts. - -This module is completely compatible with the `g.sh` script, which means that -they both can be run side by side without any problems. diff --git a/emacs/lisp/g.el b/emacs/lisp/g.el deleted file mode 100644 index 3a4660a..0000000 --- a/emacs/lisp/g.el +++ /dev/null @@ -1,134 +0,0 @@ -;;; g.el --- Adding shortcuts to GNU Emacs - -;; Copyright (C) 2016-2019 Miquel Sabaté Solà -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;; Author: Miquel Sabaté Solà -;; Version: 0.1 -;; URL: https://github.com/mssola/dotfiles/emacs/site-lisp/g.el - -;;; Commentary: -;; -;; This is a GNU Emacs port of my g.sh bash script that can be found here: -;; https://github.com/mssola/g. This package can be seen as useless given the -;; fantastic Helm + Projectile combo, but it still comes in handy when you want -;; to edit: -;; - A file which is in a project unknown to Projectile. -;; - A file that does not really belong to a real project. - -;;; Code: - -(defvar g-file "~/.gfile" - "The path to the gfile.") - -;; Utils - -(defun g-read-file (file) - "Read the given FILE and return it as a list of lines." - - (if (file-exists-p file) - (with-temp-buffer - (insert-file-contents file) - (split-string (buffer-string) "\n" t)) - "")) - -(defun g-write (shortcuts) - "Write the given SHORTCUTS into the gfile." - - (let ((output "")) - (maphash (lambda (key value) - (setq output - (concat output (format "%s\n%s\n" key value)))) - shortcuts) - (write-region output nil g-file))) - -(defun g-read () - "Read all the shortcuts as defined by the gfile. -The returned object is a hash table." - - (let ((shortcuts (make-hash-table :test 'equal)) - (list (g-read-file g-file))) - - ; The format of the file is a bit special because it was meant to be easily - ; parseable by Bash. It consists of pairs of lines, where n is the key, and - ; n+1 is the value. - (dotimes (i (/ (length list) 2)) - (let ((n (* i 2))) - (puthash - (nth n list) - (nth (+ n 1) list) - shortcuts))) - shortcuts)) - -;; Interactive functions - -(defun g () - "Go to the given directory with the supplied alias." - - (interactive) - - (if (file-exists-p g-file) - (progn - (let* ((shortcuts (g-read)) - (alias (completing-read - "Give me the name: " shortcuts nil t))) - (find-file (gethash alias shortcuts)))) - (message "Add a shortcut first!"))) - -(defun g-list () - "List all the available shortcuts." - - (interactive) - - (let ((output "")) - (maphash (lambda (key value) - (setq output - (concat output (format "%s => %s\n" key value)))) - (g-read)) - (message output))) - -(defun g-add () - "Add a new shortcut." - - (interactive) - - (let ((shortcuts (g-read)) - (to-create (read-string "Shortcut to create: "))) - (if (gethash to-create shortcuts) - (message "Error: shortcut already exists.") - (let ((path (read-file-name "Path: " nil nil t))) - (if (file-exists-p path) - (progn - (puthash to-create (file-truename path) shortcuts) - (g-write shortcuts)) - (message "Error: given path does not exist.")))))) - -(defun g-remove () - "Remove an existing shortcut." - - (interactive) - - (if (file-exists-p g-file) - (progn - (let* ((shortcuts (g-read)) - (alias (completing-read - "Give me the shortcut to remove: " shortcuts nil t))) - (remhash alias shortcuts) - (g-write shortcuts))) - (message "There are no shortcuts!"))) - -(provide 'g) - -;;; g.el ends here diff --git a/emacs/org.css b/emacs/org.css deleted file mode 100644 index 98110e5..0000000 --- a/emacs/org.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2017-2019 Miquel Sabaté Solà - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file tries to mimick what we have in the soria theme. That being said, - * the HTML exporter of org-mode is not perfect, so there's tons of stuff that - * are not highlighted in the same way as in GNU Emacs. Anyways, the colors are - * as follows: - * - * soria-purple "#dfafdf" - * soria-darkpurple "#875f87" - * soria-white "#d0d0d0" - * soria-darkgray "#1c1c1c" - * soria-brightgreen "#81c13b" - * soria-green "#b9dc92" - * soria-darkgreen "#2f5361" - * soria-gray "#808080" - * soria-linegray "#3a3a3a" - * soria-statusgray "#4e4e4e" - * soria-statusncgray "#b2b2b2" - * soria-black "#000000" - * soria-whitest "#eeeeee" - * soria-yellow "#ffffaf" - * soria-orange "#d7af87" - * soria-redpastel "#d78787" - * soria-blue "#87afd7" - */ - -.org-src-container pre { - color: #d0d0d0; - background-color: #1c1c1c; - border-left: 0px; -} - -.org-warning { color: #b9dc92; } -.org-keyword { color: #87afd7; } -.org-function-name { color: #87afd7; } -.org-builtin { color: #87afd7; } -.org-constant { color: #ffffaf; } -.org-string { color: #ffffaf; } -.org-doc { color: #808080; } -.org-comment { color: #808080; } -.org-comment-delimiter { color: #808080; } -.org-rainbow-delimiters-depth-1 { color: #81c13b; } -.org-rainbow-delimiters-depth-2 { color: #d78787; } -.org-rainbow-delimiters-depth-3 { color: #d7af87; } -.org-rainbow-delimiters-depth-4 { color: #87afd7; } -.org-rainbow-delimiters-depth-5 { color: #d0d0d0; } -.org-rainbow-delimiters-depth-6 { color: #d0d0d0; } -.org-rainbow-delimiters-depth-7 { color: #d0d0d0; } -.org-rainbow-delimiters-depth-8 { color: #d0d0d0; } -.org-rainbow-delimiters-depth-9 { color: #d0d0d0; } diff --git a/emacs/pre-push b/emacs/pre-push deleted file mode 100755 index dcc8dce..0000000 --- a/emacs/pre-push +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh -# Copyright (C) 2017-2019 Miquel Sabaté Solà -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Most of the code is taken from the default pre-push.sample file. - -# From the documentation, if the foreign ref does not yet exist the -# will be 40 0. -z40=0000000000000000000000000000000000000000 - -# The path where the files are to be stored on the server. -__mssola_remote_path=/home/mssola/static - -# Safely join paths. -__mssola_join_path() { - local IFS="/"; echo "$*"; -} - -# This function does the actual syncing. It takes one argument, which is the -# file to be synced. Note that this function assumes that the given file is -# under the "emacs" directory. -__mssola_sync_cheato() { - path=$(realpath .) - - src=$(__mssola_join_path $path "emacs" $1) - dst=$(__mssola_join_path "cheato.mssola.com:$__mssola_remote_path" $1) - - echo "Syncing $(__mssola_join_path emacs $1)" - rsync $src $dst -} - -# Copy the files that I want to my server. -__mssola_sync() { - __mssola_sync_cheato "init.html" - __mssola_sync_cheato "org.css" -} - -# This block iterates through all the given info provided by git. If there is -# a change on a GNU Emacs file, then it needs to by synced with my server. -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Commits afecting GNU Emacs are prefixed with "emacs: ". It's a - # convention that I always follow. - commit=`git rev-list -n 1 --grep '^emacs:' "$range"` - if [ -n "$commit" ] - then - #__mssola_sync - exit 0 - fi - fi -done - -exit 0 diff --git a/emacs/snippets/org-mode/header b/emacs/snippets/org-mode/header deleted file mode 100644 index a3f7fca..0000000 --- a/emacs/snippets/org-mode/header +++ /dev/null @@ -1,8 +0,0 @@ -# -*- mode: snippet -*- -#name : header -# -- -#+TITLE: ${1:} -#+AUTHOR: `(user-full-name)` -#+EMAIL: `user-mail-address` - -* $0 \ No newline at end of file diff --git a/emacs/test-startup.sh b/emacs/test-startup.sh deleted file mode 100755 index d8f3547..0000000 --- a/emacs/test-startup.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -ex -# Kindly taken from: https://github.com/purcell/emacs.d - -if [ -n "$TRAVIS" ]; then - # We still need to have an .emacs.d directory, so emacs-async (dependency of - # some other package) is happy. - export HOME=$PWD/.. - ln -s emacs ../.emacs.d -fi - -echo "Attempting startup..." - -${EMACS:=emacs} -nw --batch \ - --eval '(let ((debug-on-error t) - (url-show-status nil) - (user-emacs-directory default-directory) - (package-user-dir (expand-file-name (concat "elpa-" emacs-version))) - (custom-theme-directory default-directory) - (user-init-file (expand-file-name "init.el"))) - (load-file user-init-file) - (run-hooks (quote after-init-hook)))' -echo "Startup successful" -- cgit v1.2.3