BadDaemons/content-org/emacs-conf.org

120 KiB
Raw Blame History

Mi configuración de emacs

Tabla de contenido   TOC_5_org

Acerca de este documento

Este documento está hecho en org-mode y es tanto mi configuración de emacs como la explicación de esta. Más información sobre la programación literaria aquí.

Mi idea es que termine siendo más o menos un tutorial de emacs, extendido con los articulos del blog.

Se puede instalar mi configuración de emacs del siguiente modo:

git clone https://git.daemons.it/drymer/emacs-dotfiles ~/.emacs.d/
emacs

O se puede usar el playbook de ansible que gestiona todas mis configuraciones.

Configuración Genérica

En esta sección se tocará la configuración que tenga que ver con el manejo general de emacs. Yo suelo arrancar emacs usando un script que llamo demacs. En el llamo a emacs en modo demonio para que quede corriendo en segundo plano y luego abro emacsclient.

Que ventajas tiene esto? Emacs no es como vim, no abres tantos emacs como ediciones quieres hacer. Dado que es mucho más pesado que vim, lo más eficiente es abrir uno solo y cuando quieres editar algún fichero usas emacsclient, un binario que permite conectarse a una sesión existente.

demacs contiene lo siguiente:

#!/bin/bash

USERID=`id -u`
if [[ ! -e /tmp/emacs$USERID/server ]]
then
    emacs --daemon
    emacsclient -c -n -e '(load-file "/tmp/powerline.el")' -e "(org-agenda-list)"
else
    emacsclient -c -n -e "(org-agenda-list)"
fi

Me gusta que nada más abrirlo, me muestre la agenda, por eso está el (org-agenda-list). El load-file al fichero del powerline es debido a que emacs al lanzarse en modo demonio, es como si se lanzase en modo terminal, por lo que hay ciertos paquetes que los carga como tal. Y dado que el powerline que uso es un poco especialito, si no se arranca desde la gui, se ve feo. Por ello la primera vez que se ejecute el emacsclient, evalua el powerline.

Seguridad de las conexiones

(setq network-security-level 'high)

Iniciar paquetes elpa/melpa/marmalade

Ahora mismo el repositorio de marmalade está comentado por que da un error al usarlo con https. Uso el de ojab.ru, que es un proxy a marmalade.

(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
			 ("marmalade" . "https://ojab.ru/marmalade/")
			 ("melpa" . "https://melpa.org/packages/")))
(package-initialize)

Actualizar paquetes

(package-refresh-contents)

Asegurarse de que use-package y el-get estan instalados

;; Comprueba si use-package está instalado, sinó lo instala desde los repositorios
(unless (require 'use-package nil 'noerror)
  (package-install 'use-package))

(require 'use-package)

;; Añade la ruta de el-get
(add-to-list 'load-path (concat user-emacs-directory "el-get/el-get/"))

;; Comprueba si el-get está instalado, sinó lo instala desde un gist
(unless (require 'el-get nil 'noerror)
  ;; comprobar si existe el fichero a descargar, si existe no lo descarga
  (if (not (file-exists-p "/tmp/el-get-install.el"))
      (url-copy-file "https://raw.githubusercontent.com/dimitri/el-get/master/el-get-install.el" "/tmp/el-get-install.el"))
  (load-file "/tmp/el-get-install.el"))

(use-package el-get)

Powerline modificada

(use-package spaceline
 :ensure t
 :config
(require 'spaceline-config)
(setq powerline-default-separator "wave")
(spaceline-spacemacs-theme)
(spaceline-toggle-org-clock-on)
(spaceline-toggle-version-control-on)
(spaceline-toggle-major-mode-off)
(spaceline-toggle-selection-info-on)
(spaceline-toggle-buffer-encoding-abbrev-off)
(spaceline-toggle-hud-on)
(spaceline-toggle-projectile-root-on)
(spaceline-toggle-which-function-on)
(spaceline-toggle-minor-modes-off))

Powerline viejo, lo mantengo por razones historicas:

Lo siguiente lo he cogido de la configuración de Dennis Ogbe, modificando sólo los colores (creo).

(use-package powerline
  :ensure t
  :config
  (progn (setq powerline-default-separator 'contour)
             (setq powerline-height 25))
      (setq powerline-default-separator-dir '(right . left))

      ;; first reset the faces that already exist
      (set-face-attribute 'mode-line nil
                          :foreground (face-attribute 'default :foreground)
                          :family "Fira Sans"
                          :weight 'bold
                          :background (face-attribute 'fringe :background))
      (set-face-attribute 'mode-line-inactive nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'fringe :background)
                          :family "Fira Sans"
                          :weight 'bold
                          :box `(:line-width -2 :color ,(face-attribute 'fringe :background)))
      (set-face-attribute 'powerline-active1 nil
                          :background "gray30")
      (set-face-attribute 'powerline-inactive1 nil
                          :background (face-attribute 'default :background)
                          :box `(:line-width -2 :color ,(face-attribute 'fringe :background)))

      ;; these next faces are for the status indicator
      ;; read-only buffer
      (make-face 'mode-line-read-only-face)
      (make-face 'mode-line-read-only-inactive-face)
      (set-face-attribute 'mode-line-read-only-face nil
                          :foreground (face-attribute 'default :foreground)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-read-only-inactive-face nil
                          :foreground (face-attribute 'default :foreground)
                          :inherit 'mode-line-inactive)

      ;; modified buffer
      (make-face 'mode-line-modified-face)
      (make-face 'mode-line-modified-inactive-face)
      (set-face-attribute 'mode-line-modified-face nil
                          :foreground (face-attribute 'default :background)
                          :background "#729FCF"
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-modified-inactive-face nil
                          :foreground (face-attribute 'default :background)
                          :background "#729FCF"
                          :inherit 'mode-line-inactive)

      ;; unmodified buffer
      (make-face 'mode-line-unmodified-face)
      (make-face 'mode-line-unmodified-inactive-face)
      (set-face-attribute 'mode-line-unmodified-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-unmodified-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'mode-line-inactive)

      ;; the remote indicator
      (make-face 'mode-line-remote-face)
      (make-face 'mode-line-remote-inactive-face)
      (set-face-attribute 'mode-line-remote-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-remote-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line-inactive)

      ;; the current file name
      (make-face 'mode-line-filename-face)
      (make-face 'mode-line-filename-inactive-face)
      (set-face-attribute 'mode-line-filename-face nil
                          :foreground "#729FCF"
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-filename-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line-inactive)

      ;; the major mode name
      (make-face 'mode-line-major-mode-face)
      (make-face 'mode-line-major-mode-inactive-face)
      (set-face-attribute 'mode-line-major-mode-face nil
                          :foreground (face-attribute 'default :foreground)
                          :inherit 'powerline-active1)
      (set-face-attribute 'mode-line-major-mode-inactive-face nil
                          :box `(:line-width -2 :color ,(face-attribute 'fringe :background))
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'powerline-inactive1)

      ;; the minor mode name
      (make-face 'mode-line-minor-mode-face)
      (make-face 'mode-line-minor-mode-inactive-face)
      (set-face-attribute 'mode-line-minor-mode-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'powerline-active1)
      (set-face-attribute 'mode-line-minor-mode-inactive-face nil
                          :box `(:line-width -2 :color ,(face-attribute 'fringe :background))
                          :foreground (face-attribute 'powerline-inactive1 :background)
                          :inherit 'powerline-inactive1)

      ;; the position face
      (make-face 'mode-line-position-face)
      (make-face 'mode-line-position-inactive-face)
      (set-face-attribute 'mode-line-position-face nil
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-position-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line-inactive)

      ;; the 80col warning face
      (make-face 'mode-line-80col-face)
      (make-face 'mode-line-80col-inactive-face)
      (set-face-attribute 'mode-line-80col-face nil
                          :background "#729FCF"
                          :foreground (face-attribute 'default :background)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-80col-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :background (face-attribute 'default :background)
                          :inherit 'mode-line-inactive)

      ;; the buffer percentage face
      (make-face 'mode-line-percentage-face)
      (make-face 'mode-line-percentage-inactive-face)
      (set-face-attribute 'mode-line-percentage-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'mode-line)
      (set-face-attribute 'mode-line-percentage-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'mode-line-inactive)

      ;; the directory face
      (make-face 'mode-line-shell-dir-face)
      (make-face 'mode-line-shell-dir-inactive-face)
      (set-face-attribute 'mode-line-shell-dir-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'powerline-active1)
      (set-face-attribute 'mode-line-shell-dir-inactive-face nil
                          :foreground (face-attribute 'font-lock-comment-face :foreground)
                          :inherit 'powerline-inactive1)

      (defpowerline dennis-powerline-narrow
        (let (real-point-min real-point-max)
          (save-excursion
            (save-restriction
              (widen)
              (setq real-point-min (point-min) real-point-max (point-max))))
          (when (or (/= real-point-min (point-min))
                    (/= real-point-max (point-max)))
            (propertize (concat (char-to-string #x2691) " Narrow")
                        'mouse-face 'mode-line-highlight
                        'help-echo "mouse-1: Remove narrowing from the current buffer"
                        'local-map (make-mode-line-mouse-map
                                    'mouse-1 'mode-line-widen)))))

      (defpowerline dennis-powerline-vc
        (when (and (buffer-file-name (current-buffer)) vc-mode)
          (if window-system
              (let ((backend (vc-backend (buffer-file-name (current-buffer)))))
                (when backend
                  (format "%s %s: %s"
                          (char-to-string #xe0a0)
                          backend
                          (vc-working-revision (buffer-file-name (current-buffer)) backend)))))))

      (setq-default
       mode-line-format
       '("%e"
         (:eval
          (let* ((active (powerline-selected-window-active))

                 ;; toggle faces between active and inactive
                 (mode-line (if active 'mode-line 'mode-line-inactive))
                 (face1 (if active 'powerline-active1 'powerline-inactive1))
                 (face2 (if active 'powerline-active2 'powerline-inactive2))
                 (read-only-face (if active 'mode-line-read-only-face 'mode-line-read-only-inactive-face))
                 (modified-face (if active 'mode-line-modified-face 'mode-line-modified-inactive-face))
                 (unmodified-face (if active 'mode-line-unmodified-face 'mode-line-unmodified-inactive-face))
                 (position-face (if active 'mode-line-position-face 'mode-line-position-inactive-face))
                 (80col-face (if active 'mode-line-80col-face 'mode-line-80col-inactive-face))
                 (major-mode-face (if active 'mode-line-major-mode-face 'mode-line-major-mode-inactive-face))
                 (minor-mode-face (if active 'mode-line-minor-mode-face 'mode-line-minor-mode-inactive-face))
                 (filename-face (if active 'mode-line-filename-face 'mode-line-filename-inactive-face))
                 (percentage-face (if active 'mode-line-percentage-face 'mode-line-percentage-inactive-face))
                 (remote-face (if active 'mode-line-remote-face 'mode-line-remote-inactive-face))
                 (shell-dir-face (if active 'mode-line-shell-dir-face 'mode-line-shell-dir-inactive-face))

                 ;; get the separators
                 (separator-left (intern (format "powerline-%s-%s"
                                                 (powerline-current-separator)
                                                 (car powerline-default-separator-dir))))
                 (separator-right (intern (format "powerline-%s-%s"
                                                  (powerline-current-separator)
                                                  (cdr powerline-default-separator-dir))))

                 ;; the right side
                 (rhs (list
                       (dennis-powerline-vc minor-mode-face 'r)
                       (funcall separator-right face1 position-face)
                       (powerline-raw " " position-face)
                       (powerline-raw (char-to-string #xe0a1) position-face)
                       (powerline-raw " " position-face)
                       (powerline-raw "%4l" position-face 'r)
                       ;; display a warning if we go above 80 columns
                       (if (>= (current-column) 80)
                           (funcall separator-right position-face 80col-face)
                         (powerline-raw (char-to-string #x2502) position-face))
                       (if (>= (current-column) 80)
                           (powerline-raw "%3c" 80col-face 'l)
                         (powerline-raw "%3c" position-face 'l))
                       (if (>= (current-column) 80)
                           (powerline-raw " " 80col-face)
                         (powerline-raw " " position-face))
                       (if (>= (current-column) 80)
                           (funcall separator-left 80col-face percentage-face)
                         (funcall separator-left position-face percentage-face))
                       (powerline-raw " " percentage-face)
                       (powerline-raw "%6p" percentage-face 'r)))

                 ;; the left side
                 (lhs (list
                       ;; this is the modified status indicator
                       (cond (buffer-read-only
                              (powerline-raw "  " read-only-face))
                             ((buffer-modified-p)
                              ;; do not light up when in an interactive buffer. Set
                              ;; ML-INTERACTIVE? in hooks for interactive buffers.
                              (if (not (bound-and-true-p ml-interactive?))
                                  (powerline-raw "  " modified-face)
                                (powerline-raw "  " unmodified-face)))
                             ((not (buffer-modified-p))
                              (powerline-raw "  " unmodified-face)))
                       (cond (buffer-read-only
                              (powerline-raw (concat (char-to-string #xe0a2) " ") read-only-face 'l))
                             ((buffer-modified-p)
                              (if (not (bound-and-true-p ml-interactive?))
                                  (powerline-raw (concat (char-to-string #x2621) " ") modified-face 'l)
                                (powerline-raw (concat (char-to-string #x259e) " ") unmodified-face 'l)))
                             ((not (buffer-modified-p))
                              (powerline-raw (concat (char-to-string #x26c1) " ") unmodified-face 'l)))
                       (cond (buffer-read-only
                              (funcall separator-right read-only-face filename-face))
                             ((buffer-modified-p)
                              (if (not (bound-and-true-p ml-interactive?))
                                  (funcall separator-right modified-face filename-face)
                                (funcall separator-right unmodified-face filename-face)))
                             ((not (buffer-modified-p))
                              (funcall separator-right unmodified-face filename-face)))
                       ;; remote indicator
                       (when (file-remote-p default-directory)
                         (powerline-raw (concat " " (char-to-string #x211b)) remote-face))
                       ;; filename and mode info
                       (powerline-buffer-id filename-face 'l)
		       (if (not (string= "-" (projectile-project-name)))
			   (powerline-raw (format " [ %s ] " (projectile-project-name)) filename-face))
                       (powerline-raw " " filename-face)
                       (funcall separator-left filename-face major-mode-face)
                       ;; do not need mode info when in ansi-term
                       (unless (bound-and-true-p show-dir-in-mode-line?)
                         (powerline-major-mode major-mode-face 'l))
                       (unless (bound-and-true-p show-dir-in-mode-line?)
                         (powerline-process major-mode-face 'l))
                       ;; show a flag if in line mode in terminal
                       (when (and (bound-and-true-p show-dir-in-mode-line?) (term-in-line-mode))
                         (powerline-raw (concat (char-to-string #x2691) " Line") major-mode-face))
                       (powerline-raw " " major-mode-face)
                       ;; little trick to move the directory name to the mode line
                       ;; when inside of emacs set SHOW-DIR-IN-MODE-LINE? to enable
                       (if (bound-and-true-p show-dir-in-mode-line?)
                           (when (not (file-remote-p default-directory))
                             (powerline-raw (shorten-directory default-directory 45)
                                            shell-dir-face))
                         (powerline-minor-modes minor-mode-face 'l))
                       (unless (bound-and-true-p show-dir-in-mode-line?)
                         (dennis-powerline-narrow major-mode-face 'l)))))

            ;; concatenate it all together
            (concat (powerline-render lhs)
                    (powerline-fill face1 (powerline-width rhs))
                    (powerline-render rhs)))))))

          (defvar-local hidden-mode-line-mode nil)
(define-minor-mode hidden-mode-line-mode
            "Minor mode to hide the mode-line in the current buffer."
            :init-value nil
            :global t
            :variable hidden-mode-line-mode
            :group 'editing-basics
            (if hidden-mode-line-mode
                (setq hide-mode-line mode-line-format
                      mode-line-format nil)
              (setq mode-line-format hide-mode-line
                    hide-mode-line nil))
            (force-mode-line-update)
            ;; Apparently force-mode-line-update is not always enough to
            ;; redisplay the mode-line
            (redraw-display)
            (when (and (called-interactively-p 'interactive)
                       hidden-mode-line-mode)
              (run-with-idle-timer
               0 nil 'message
               (concat "Hidden Mode Line Mode enabled.  "
                       "Use M-x hidden-mode-line-mode to make the mode-line appear."))))

Tema cyberpunk

(use-package cyberpunk-theme
  :config (load-theme 'cyberpunk t)
  :ensure t
  :init (custom-set-variables
	 '(custom-safe-themes
	   (quote
	    ("71ecffba18621354a1be303687f33b84788e13f40141580fa81e7840752d31bf" default)))))

Deshabilitar el background cuando se usa la terminal:

(defun on-frame-open (&optional frame)
  "If the FRAME created in terminal don't load background color."
  (unless (display-graphic-p frame)
    (set-face-background 'default "unspecified-bg" frame)))

(add-hook 'after-make-frame-functions 'on-frame-open)

General

(use-package general
  :ensure t
  :config
  (setq my-spc-prefix "<SPC>")
  (setq my-comma-prefix ",")
  (setq general-override-states '(insert
                                  emacs
                                  hybrid
                                  normal
                                  visual
                                  motion
                                  operator
                                  replace))
  (general-override-mode))

Definir el modo menor daemons-mode para juntar todos los atajos de teclado:

;; Code:
(defgroup daemons-mode nil
  "My mode for mapping keys."
  :group 'keyboard)

(defvar daemons-mode-map nil
  "Keymap for daemons emacs minor mode.")

(if daemons-mode-map
    nil
  (setq daemons-mode-map (make-sparse-keymap)))

;;;###autoload
(define-minor-mode daemons-mode
  "Daemons emacs minor mode."
  nil " dm" daemons-mode-map)

;;;###autoload
(define-globalized-minor-mode global-daemons-mode
  daemons-mode daemons-mode)

(provide 'daemons-mode)
;;; daemons-mode.el ends here

Cargar el modo menor daemons-mode:

(use-package daemons-mode
  :load-path "/tmp/daemons-mode/")
(add-hook 'after-init-hook 'global-daemons-mode)

Atajos de teclado generales con prefijo SPC:

(general-def '(normal visual motion) "SPC" nil)

(general-create-definer spc-map
  :keymaps 'daemons-mode-map
  :states '(normal visual motion)
  :prefix "SPC")

(spc-map
 "0" 'delete-window
 "1" 'delete-other-windows
 "2" 'split-window-vertically
 "3" 'split-window-horizontally
 "u" 'universal-argument
 "f" '(nil :which-key "file prefix")
 "ff" 'counsel-find-file
 "fl" 'counsel-locate
 "fz" 'counsel-fzf
 "b" '(nil :which-key "buffer prefix")
 "bb" 'switch-to-buffer
 "bk" 'kill-this-buffer
 "bj" 'scroll-other-window
 "bk" 'scroll-other-window-down
 "," 'goto-last-change
 ";" 'goto-last-change-reverse
 "s" '(nil :which-key "search prefix")
 "ss" 'isearch-forward)

Atajos de teclado generales:

(general-define-key
 :keymaps '(normal insert visual)
 "C-a" 'evil-beginning-of-line
 "C-e" 'evil-end-of-line
 "C-d" 'evil-scroll-page-down
 "C-u" 'evil-scroll-page-up)

Formato de las columnas de numeracion

Por defecto no se activan, hay que hacerlo a mano con M-x linum-mode.

(setq linum-format "%4d \u2502 ")

Ventana limpia

Sin scroll bar, menu bar ni tool bar.

(tool-bar-mode -1)
(scroll-bar-mode -1)
(menu-bar-mode -1)
(blink-cursor-mode 0)

UTF-8

(prefer-coding-system       'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))

Tipo de fuente

(custom-set-faces '(default ((t (:family "DejaVu Sans Mono" :foundry "unknown" :slant normal :weight normal :height 107 :width normal)))))

Partir buffers de manera más bonita

(add-to-list 'default-frame-alist '(height . 40))
(add-to-list 'default-frame-alist '(width . 90))

Scroll

Similar a la manera de vim. No tengo claro en que se diferencia, pero me gusta cómo funciona.

(setq scroll-step            1
      scroll-conservatively  10000)

(setq scroll-margin 80
      scroll-conservatively 3000
      scroll-up-aggressively 0.02
      scroll-down-aggressively 0.02)

Aumentar y disminuir tamaño de la fuente

Con C-+ aumenta la fuente y con C-- la disminuye.

(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)

Moverse por el buffer

Subir y bajar párrafos:

(global-set-key "\M-p" 'backward-paragraph)
(global-set-key "\M-n" 'forward-paragraph)

Establecer nombre y correo

Al exportar en org-mode, por ejemplo, coge estos valores.

(setq user-full-name "drymer"
      user-mail-address "drymer [ EN ] autistici.org")

Establecer buffer inicial

(setq initial-buffer-choice "~/Documentos/org/index.org")

Iniciar cómo servidor

De este modo puedo usar emacsclient desde la terminal y la sesión de emacs existente.

(server-start)

Destacar el par coincidente

(show-paren-mode)

Auto-guardado

Es bastante molesto que te vaya dejando la mierda por ahí, mejor en un directorio conjunto.

(defvar backup-dir (expand-file-name (concat user-emacs-directory "backup/")))
(defvar autosave-dir (expand-file-name (concat user-emacs-directory "backup/")))
(setq backup-directory-alist (list (cons ".*" backup-dir)))
(setq auto-save-list-file-prefix autosave-dir)
(setq auto-save-file-name-transforms `((".*" ,autosave-dir t)))
(setq tramp-backup-directory-alist backup-directory-alist)
(setq tramp-auto-save-directory autosave-dir)

Modo por defecto

Al abrir un archivo o bufer sin algún modo asociado, se abrirá en modo texto.

(setq major-mode 'text-mode)

Acepta 'y' o 'n' cuando pide 'yes' o 'no'

(fset 'yes-or-no-p 'y-or-n-p)

Lenguaje por defecto en emacs y org-mode

(setq current-language-environment "Spanish")
(setq org-export-default-language "es")

No seguir enlaces simbólicos

(setq vc-follow-symlinks nil)

Emparejar parentesis y otros

Empareja () [] {} y "".

(electric-pair-mode 1)

Mantener lista de buffers recientes

Al usar ivy o helm y ejecutar switch-buffer (C-x b) se pueden ver los buffers que se han abierto recientemente si se tiene recentf activo.

(setq recentf-max-saved-items 200)
(setq recentf-max-menu-items 200)
(recentf-mode 1)

Truncar líneas

(setq truncate-lines t)
(setq visual-line-mode t)

Auto identación

(global-set-key (kbd "RET") 'newline-and-indent)

Insertar licencia

(add-to-list 'el-get-sources '(:name xlicense-github
				     :type github
				     :pkgname "jtimberman/xlicense-el"))

(if (not (el-get-package-installed-p 'xlicense-github))
    (el-get 'sync 'xlicense-github))

(use-package xlicense
  :load-path "el-get/xlicense-github"
  :init
  (setq license-directory (concat user-emacs-directory "el-get/xlicense-github/licenses/")))

Borrar espacios sobrantes

Al guardar, borrar los que sobren de cada linea despues de el último carácter.

(add-hook 'before-save-hook 'delete-trailing-whitespace)

Usar ssh con tramp

Por defecto usa scp, que es muy lento. Así se usará ssh.

(setq tramp-default-method "ssh")

Abrir enlaces en el navegador por defecto

La configuración para que abra los enlaces en el navegador por defecto y no eww, es la siguiente:

(setq browse-url-browser-function 'browse-url-generic)
(setq browse-url-generic-program "my-sensible-browser")

Terminal

Establecer shell.

(setq explicit-shell-file-name "/bin/bash")
(setq shell-file-name explicit-shell-file-name)
(setenv "SHELL" shell-file-name)
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)

Sobreescribir al seleccionar texto

No está activo.

(delete-selection-mode t)

Buffer *Scratch* persistente

(use-package persistent-scratch
  :ensure t
  :config
  (persistent-scratch-setup-default))

kill-this-buffer en vez de kill-buffer

Fuente: http://pragmaticemacs.com/emacs/dont-kill-buffer-kill-this-buffer-instead/

(global-set-key (kbd "C-x k") 'kill-this-buffer)

Ispell

Instalamos el diccionario de esta dirección y configuramos emacs para que lo use:

(setq ispell-dictionary "español")

Activar atajos desactivados por defecto

(setq disabled-command-function nil)

Mostrar orden en minibuffer

(setq echo-keystrokes 0.1)

Dired

Reusar buffers de dired:

(with-eval-after-load 'dired
  (define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file))

Mostrar nombre de función en el mode-line

(which-function-mode)

Desactivar M-{numero}

Lo usaré para cambiar de workspace con eyebrowse:

(dotimes (n 10)
  (global-unset-key (kbd (format "M-%d" n))))

Narrow-to-region más bonito

(use-package fancy-narrow
  :ensure t)

(spc-map
 "n" '(nil :which-key "narrow prefix")
 "nn" 'fancy-narrow-to-region
 "nw" 'fancy-widen)

Actualizar fichero automáricamente

(global-auto-revert-mode 1)

evil-mode

(use-package evil
  :ensure t
  :init
  ;; sane defaults
  (setq evil-want-C-u-scroll t)
  (setq evil-move-cursor-back nil)
  (setq evil-cross-lines t)
  (setq evil-move-beyond-eol nil)
  (setq evil-want-fine-undo t)
  (setq evil-symbol-word-search t)
  (setq evil-want-Y-yank-to-eol t)
  (setq evil-want-integration nil)
  (general-define-key
   :keymaps 'normal
   "j" 'evil-next-visual-line
   "k" 'evil-previous-visual-line
   "M-u" 'universal-argument)
  :config
  (add-to-list 'evil-insert-state-modes 'global-git-commit)
  (evil-mode 1)
  (setq evil-motion-state-modes (append evil-emacs-state-modes evil-motion-state-modes))
  (setq evil-emacs-state-modes nil)
  :bind
  ;; ESC == C-g
  (:map minibuffer-local-map
	("ESC" . minibuffer-keyboard-quit)
	:map minibuffer-local-ns-map
	("ESC" . minibuffer-keyboard-quit)
	:map minibuffer-local-completion-map
	("ESC" . miminibuffer-keyboard-quit)
	:map minibuffer-local-must-match-map
	("ESC" . minibuffer-keyboard-quit)))
(general-evil-setup)

Evil org:

;; binds: https://github.com/Somelauw/evil-org-mode/blob/master/doc/keythemes.org
(use-package evil-org
  :ensure t
  :config
  (add-hook 'org-mode-hook 'evil-org-mode)
  (evil-org-set-key-theme '(navigation insert textobjects additional calendar))
  (use-package evil-org-agenda :config (evil-org-agenda-set-keys)))

Evil collection:

;; binds: https://github.com/jojojames/evil-collection
(use-package evil-collection
  :ensure t
  :config
  (evil-collection-init))

Evil nerd commenter:

(use-package evil-nerd-commenter
  :ensure t
  :config
  (evilnc-default-hotkeys))

Evil lion:

(use-package evil-lion
  :ensure t
  :bind (:map evil-normal-state-map
	      ("g l " . evil-lion-left)
	      ("g L " . evil-lion-right)
	      :map evil-visual-state-map
	      ("g l " . evil-lion-left)
	      ("g L " . evil-lion-right)))

Evil matchit:

(use-package evil-matchit
  :ensure t
  :init
  (defun evilmi-customize-keybinding ()
    (evil-define-key 'normal evil-matchit-mode-map
      "ñ" 'evilmi-jump-items))
  :config
  (global-evil-matchit-mode 1))

Evil escape:

(use-package evil-escape
  :ensure t
  :config
  (evil-escape-mode))

Evil numbers:

(use-package evil-numbers
  :ensure t
  :config
  (spc-map
    "+" 'evil-numbers/inc-at-pt
    "-" 'evil-numbers/dec-at-pt))

Evil jumper:

(spc-map
  "j" 'evil-jump-forward
  "J" 'evil-jump-backward)

Evil surround:

(use-package evil-surround
  :ensure t
  :config
  (global-evil-surround-mode 1))

org-mode

org-mode merece tener la configuración a parte. Ahí va.

Definir fuente de el-get

Se usa la rama maint del repositorio git. Primero se comprueba si está instalado, de no ser así se instalará. Tardará un buen rato.

;; Cutre-codigo para quitar del path el org de emacs para que no se lie al cargar de nuevo el modo
(dolist (val load-path)
(if (string-match "lisp\/org" val)
    (delete val load-path)))
(add-to-list 'el-get-sources '(:name org-mode-maint
                                    :website "http://orgmode.org/"
                                    :description "Org-mode is for keeping notes, maintaining ToDo lists, doing project planning, and authoring with a fast and effective plain-text system."
                                    :type git
                                    :url "https://code.orgmode.org/bzg/org-mode.git"
                                    :branch "maint"
                                    :load-path ("." "lisp/")))

(if (not (el-get-package-installed-p 'org-mode-maint))
(el-get 'sync 'org-mode-maint))

Agenda

Definir archivos de la agenda
(setq org-agenda-files '("~/Documentos/org/" "~/Documentos/BadDaemons/Articulos/articulos.org"))
Asignar keybinds
;; mapa generico
(spc-map
 "a" '(nil :which-key "org-agenda prefix")
 "aa" 'org-agenda
 "ac" 'counsel-org-capture
 "l" '(nil :which-key "org link prefix")
 "li" 'org-insert-link
 "ll" 'org-store-link)

;; Definir mapa de coma en org-mode
(general-create-definer org-comma-map
  :keymaps 'org-mode-map
  :states '(normal visual)
  :prefix ",")

;; Definir mapa de coma en org-mode-src
(general-create-definer org-src-comma-map
   :keymaps 'org-src-mode-map
   :states 'motion
   :prefix ","
   "" nil)

;; Mapa concreto
(org-comma-map
 "c" '(nil :which-key "org-clock prefix")
 "ci" 'org-clock-in
 "co" 'org-clock-out
 "t" '(nil :which-key "org-todo prefix")
 "tt" 'org-todo
 "ts" 'org-schedule
 "td" 'org-deadline
 "e" '(nil :which-key "org-edit prefix")
 "ee" 'org-edit-special
 "ex" 'org-edit-src-exit
 "r" 'org-refile
 "R" 'org-copy
 "l" 'org-metaright
 "h" 'org-metaleft
 "j" 'org-metadown
 "k" 'org-metaup
 "n" 'org-narrow-to-element
 "w" 'widen
 "-" 'org-ctrl-c-minus
 "*" 'org-ctrl-c-star
 "H" 'org-promote-subtree
 "L" 'org-demote-subtree
 "K" 'org-move-subtree-up
 "J" 'org-move-subtree-down
 "C" 'org-ctrl-c-ctrl-c)
Comandos de Agenda

#+name:custom-commands

(setq org-agenda-custom-commands
    '(;; Cosas del blog
      ("b" . "Blog")
      ("bi" "Ideas para articulo" todo "TODO|INPROGRESS" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org")) (org-agenda-sorting-strategy)))
      ("bp" "Articulos listos para publicar" todo "READY|PROGRAMMED" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
      ("bc" "Articulos cancelados" todo "CANCELLED" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
      ("bf" "Articulos publicados" todo "DONE" ((org-agenda-files '("~/Documentos/BadDaemons/Articulos/articulos.org"))))
      ;; Casa
      ("c" . "Casa")
      ;; Ver lo que se ha hecho, no terminado
      ("cg" "Estado de todas las tareas" tags "+casa|+chustaserver|+vps|+labrecha|+emacs|+productividad/+TODO|NEXT|INPROGRESS|HOTFIX|BLOCKED|TESTING" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("ce" "Estado de las tareas activas" tags "+casa/+TODO|NEXT|INPROGRESS|HOTFIX" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("cp" "Estado de las tareas paradas" tags "+casa/+BLOCKED|TESTING" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("cd" "Tareas terminadas sin terminar" tags "/DONE" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("cm" "Mostras miscelaneos" tags "+miscelaneos/TODO" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("cr" "Mostras radar" tags "+radar/TODO" ((org-agenda-files '("~/Documentos/org/index.org"))))
      ("ct" "Hecho la semana anterior"
       ((agenda "")
        (org-agenda-overriding-header "Semana anterior")
        (org-agenda-span 7)
        (org-agenda-archives-mode t)
        (org-agenda-show-log 'clockcheck)
        (org-agenda-files '("~/Documentos/org/index.org"))))
      ("cs" "Calendario de la semana que viene"
       ((agenda "")
        (org-agenda-overriding-header "Semana que viene")
        (org-agenda-span 7)
        (org-agenda-start-day "+7d")
        (org-agenda-files '("~/Documentos/org/index.org"))))
      ;; Reportes del trabajo
      ("t" . "Trabajo")
      ;; Ver lo que se ha hecho, no terminado
      ("tl" "Hecho en los últimos tres días" agenda ""
       ((org-agenda-overriding-header "Last three days")
	(org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-log)
        (org-agenda-span 3)
       	(org-agenda-start-day "-3d")
       	(org-agenda-start-with-log-mode t)
       	(org-agenda-log-mode-items '(clock closed))
        (org-agenda-archives-mode t)
        (org-agenda-show-log 'clockcheck)))
      ("ti" "Hecho en la última semana" agenda ""
       ((org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-log)
        (org-agenda-span 7)
       	(org-agenda-start-day "-7d")
       	(org-agenda-start-with-log-mode t)
       	(org-agenda-log-mode-items '(clock closed))
        (org-agenda-archives-mode t)
        (org-agenda-show-log 'clockcheck)))
      ("tn" "Siguientes tareas" tags-todo "+trabajo/NEXT"
       ((org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-next)))
      ("ta" "Tareas activas" tags-todo
       "+trabajo/INPROGRESS|TESTING|HOTFIX"
       ((org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-active)))
      ("tb" "Tareas paradas" tags-todo "+trabajo/BLOCKED|TOFOLLOW"
       ((org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-blocked)))
      ("tt" "Tareas por hacer" tags "+trabajo/TODO"
       ((org-super-agenda-mode)
	(org-super-agenda-groups org-agenda-supergroup-tags-todo)))
      ("td" "Tareas terminadas sin archivar" tags "+trabajo/DONE|CANCELLED"
       ((org-super-agenda-mode)
       	(org-super-agenda-groups org-agenda-supergroup-tags-done)))
      ;; Reportes
      ("r" . "Reportes")
      ;; Mostrar tareas a reubicar
      ("rr" "Reubicar" tags "+refile" ((org-agenda-remove-tags nil) (org-agenda-hide-tags-regexp "refile")))
      ;; Reporte
      ("ra" "Ver anteriores asambleas de La Brecha Digital" tags "ARCHIVE_ITAGS={labrecha}&ARCHIVE_ITAGS={asamblea}/DONE"
       ((org-agenda-files (file-expand-wildcards "~/Documentos/org/index.org_archive"))))
      ;; Buscar en archivados solamente
      ("l" . "Archivo")
      ("ls" "Archive search" search ""
       ((org-agenda-files (file-expand-wildcards "~/Documentos/org/*.org_archive"))))))

Referencias:

Capturas de notas

#+name:capture-templates

(setq org-capture-templates
    '(
    ("r" "Reuniones" entry (file "~/Documentos/org/inbox.org")
     (file "~/.emacs.d/org-capture-templates/reuniones.org")
     :clock-in t :clock-resume t)
    ;; Para reuniones de seguimiento, tener el arbol partido en días
    ("rs" "Reuniones semanales" entry (file "~/Documentos/org/inbox.org")
     (file "~/.emacs.d/org-capture-templates/reuniones-periodicas.org")
     :clock-in t :clock-resume t)
    ;; Para cuando voy a comer en el trabajo
    ("c" "Comida" entry
     (file+olp "~/Documentos/org/trabajo.org" "Meta" "Comidas")
     "* Comida %(emacswiki/insert-current-date) "
     :clock-in t :clock-resume t)
    ;; Meter fecha debajo de un header principal para no tener chorrocientos "Dailies"
    ("d" "Daily" entry (file+olp "~/Documentos/org/trabajo.org" "Meta" "Dailies")
        "* Daily %(emacswiki/insert-current-date)" :clock-in t :clock-resume t)
    ;; Decidir si quiero una captura que me permita iniciar el reloj al capturar
    ("t" "Tarea simple" entry (file "~/Documentos/org/inbox.org")
        "* %? %^G\n%U\n" :clock-in t :clock-resume t)
    ;; Para marcadores desde el navegador
    ("w" "Marcadores" entry (file "~/Documentos/org/inbox.org")
        "* %c\n%a" :inmediate-finish t)
    ;; Diario de 2 minutos cada mañana
    ("dm" "Diario de 5 minutos: Mañana" entry (file+olp+datetree "~/Documentos/org/index.org" "Diario")
        (file "~/.emacs.d/org-capture-templates/journal-morning.org") :tree-type month)
    ;; Diario de 2 minutos cada noche
    ("dn" "Diario de 5 minutos: Noche"  entry (file+olp+datetree "~/Documentos/org/index.org" "Diario")
        (file "~/.emacs.d/org-capture-templates/journal-evening.org") :tree-type month)
    ;; Revisiones
    ("rsp" "Revisión Semanal Personal" entry (file+olp+datetree "~/Documentos/org/index.org" "Diario")
        (file "~/.emacs.d/org-capture-templates/personal-weekly-review.org"))
    ("rst" "Revisión Semanal Trabajo" entry (file+headline "~/Documentos/org/trabajo.org" "Revisión Semanal")
        (file "~/.emacs.d/org-capture-templates/work-weekly-review.org"))
    ("m" "Captura desde correo" entry (file "~/Documentos/org/inbox.org") "* %? %^G\n%U\n%a\n" :clock-in t :clock-resume t)))

Referencias:

Estados de los objetos de las listas

Todas las secuencias anteriores al símbolo | son tareas que no se consideran terminadas, al contrario de las que estan después de este.

Los estados que tienen el símbolo @ son los que, al escogerlos, abren un buffer preguntando si se quiere añadir alguna nota respecto al cambio de estado. Las que tienen el símbolo !, en cambio, crean una estampa de tiempo, para dejar constancia de cuando se ha cambiado a ese estado.

(setq org-todo-keywords
    '((sequence "TODO(t)" "NEXT(n)" "INPROGRESS(p@/!)" "WAITING(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
Refile

Mover un arbol debajo de otro del mismo fichero o de los archivos de las agendas.

(setq org-refile-targets '((nil :maxlevel . 10) (org-agenda-files . (:maxlevel . 10))))

Crear nodo si no existe:

;; Source: https://blog.aaronbieber.com/2017/03/19/organizing-notes-with-refile.html
(setq org-refile-use-outline-path 'file)
(setq org-outline-path-complete-in-steps nil)
(setq org-refile-allow-creating-parent-nodes t)
Configuración del calendario
(setq org-icalendar-timezone "Europe/Madrid")
Tareas repetitivas

Las tareas marcadas para repetirse, al marcarlas cómo DONE vuelven al estado TODO y añade un timestamp del dia y la hora.

(setq org-log-repeat "time")
Quitar tags de la agenda
(setq org-agenda-remove-tags t)
Alargar el historial del reloj
(setq org-clock-history-length 60)
punch-in y punch-out
(setq bh/keep-clock-running nil)
(defun bh/find-project-task ()
"Move point to the parent (project) task if any"
(save-restriction
(widen)
(let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point))))
    (while (org-up-heading-safe)
    (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
        (setq parent-task (point))))
    (goto-char parent-task)
    parent-task)))

(defun bh/punch-in (arg)
"Start continuous clocking and set the default task to the
selected task.  If no task is selected set the Organization task
as the default task."
(interactive "p")
(setq bh/keep-clock-running t)
(if (equal major-mode 'org-agenda-mode)
    ;;
    ;; We're in the agenda
    ;;
    (let* ((marker (org-get-at-bol 'org-hd-marker))
            (tags (org-with-point-at marker (org-get-tags-at))))
    (if (and (eq arg 4) tags)
        (org-agenda-clock-in '(16))
        (bh/clock-in-organization-task-as-default)))
;;
;; We are not in the agenda
;;
(save-restriction
    (widen)
    ; Find the tags on the current task
    (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4))
        (org-clock-in '(16))
    (bh/clock-in-organization-task-as-default)))))

(defun bh/punch-out ()
(interactive)
(setq bh/keep-clock-running nil)
(when (org-clock-is-active)
(org-clock-out))
(org-agenda-remove-restriction-lock))

(defun bh/clock-in-default-task ()
(save-excursion
(org-with-point-at org-clock-default-task
    (org-clock-in))))

(defun bh/clock-in-parent-task ()
"Move point to the parent (project) task if any and clock in"
(let ((parent-task))
(save-excursion
    (save-restriction
    (widen)
    (while (and (not parent-task) (org-up-heading-safe))
        (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
        (setq parent-task (point))))
    (if parent-task
        (org-with-point-at parent-task
            (org-clock-in))
        (when bh/keep-clock-running
        (bh/clock-in-default-task)))))))

(defvar bh/organization-task-id "b0c4c249-3349-4cf2-894a-90a769c1d62c")

(defun bh/clock-in-organization-task-as-default ()
(interactive)
(org-with-point-at (org-id-find bh/organization-task-id 'marker)
(org-clock-in '(16))))

(defun bh/clock-out-maybe ()
(when (and bh/keep-clock-running
            (not org-clock-clocking-in)
            (marker-buffer org-clock-default-task)
            (not org-clock-resolving-clocks-due-to-idleness))
(bh/clock-in-parent-task)))

(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append)
(setq org-clock-out-remove-zero-time-clocks t)
(setq org-clock-out-when-done t)
(setq org-clock-perist t)
(setq org-clock-report-include-clocking-task t)
(setq org-clone-delete-id t)

; Exclude DONE state tasks from refile targets
(defun bh/verify-refile-target ()
"Exclude todo keywords with a done state from refile targets"
(not (member (nth 2 (org-heading-components)) org-done-keywords)))
(setq org-refile-target-verify-function 'bh/verify-refile-target)

;; Change tasks to IN-PROGRESS when clocking in
(setq org-clock-in-switch-to-state 'bh/clock-in-to-progress)

(defun bh/clock-in-to-progress (kw)
"Based in bh/clock-in-to-next: Switch a task from
TODO to IN-PROGRESS when clocking in. Skips capture tasks,
projects, and subprojects. Switch projects and
subprojects from IN-PROGRESS back to TODO"
(when (not (and (boundp 'org-capture-mode) org-capture-mode))
(cond
    ((and (member (org-get-todo-state) (list "TODO"))
        (bh/is-task-p))
    "IN-PROGRESS")
    ((and (member (org-get-todo-state) (list "IN-PROGRESS"))
        (bh/is-project-p))
    "TODO"))))

;; Usado por bh/clock-in-to-progress
(defun bh/is-task-p ()
"Any task with a todo keyword and no subtask"
(save-restriction
(widen)
(let ((has-subtask)
        (subtree-end (save-excursion (org-end-of-subtree t)))
        (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
    (save-excursion
    (forward-line 1)
    (while (and (not has-subtask)
                (< (point) subtree-end)
                (re-search-forward "^\*+ " subtree-end t))
        (when (member (org-get-todo-state) org-todo-keywords-1)
        (setq has-subtask t))))
    (and is-a-task (not has-subtask)))))

;; Usado por bh/clock-in-to-progress
(defun bh/is-subproject-p ()
"Any task which is a subtask of another project"
(let ((is-subproject)
    (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
(save-excursion
    (while (and (not is-subproject) (org-up-heading-safe))
    (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
        (setq is-subproject t))))))

;; Usado por bh/clock-in-to-progress
(defun bh/is-project-p ()
"Any task with a todo keyword subtask"
(save-restriction
(widen)
(let ((has-subtask)
        (subtree-end (save-excursion (org-end-of-subtree t)))
        (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
    (save-excursion
    (forward-line 1)
    (while (and (not has-subtask)
                (< (point) subtree-end)
                (re-search-forward "^\*+ " subtree-end t))
        (when (member (org-get-todo-state) org-todo-keywords-1)
        (setq has-subtask t))))
    (and is-a-task has-subtask))))
calfw

Paquete para ver las tareas de org-mode en un formato de calendario más típico. Los arrays son sólo traducciones. Si el paquete no está instalado, lo instala mediante el-get.

#+name:calfw

(if (not (el-get-package-installed-p 'calfw))
(el-get 'sync 'calfw))

(use-package calfw
:load-path "el-get/calfw"
:config
(require 'calfw-org)
(setq cfw:org-overwrite-default-keybinding t)
(setq calendar-week-start-day 1)
(setq calendar-month-name-array
    ["Gener" "Febrer" "Març" "Abril" "Maig" "Juny" "Juliol" "Agost" "Septembre" "Octubre" "Novembre" "Desembre"])
(setq calendar-day-name-array
    ["Diumenge" "Dilluns" "Dimarts" "Dimecres" "Dijous" "Divendres" "Dissabte"])
:bind ("C-c f" . cfw:open-org-calendar))
Mostrar los clockin en la agenda
(setq org-agenda-clock-consistency-checks t)
Caldav

Lo tengo funcionando con owncloud. Si no está instalado, lo instala con el-get. Esta parte no es real, como son cosas "sensibles", van en un fichero a parte. Pero seria algo así:

(unless (require 'org-caldav nil 'noerror)
(el-get-install 'org-caldav))

(use-package org-caldav
:init
(setq org-caldav-url "http://caldav.ejemplo/")
(setq org-caldav-calendar-id "org")
(setq org-caldav-files '("~/Documentos/org/index.org" "~/Documentos/org/index.org_archive" "~/Documentos/org/notas.org"))
(setq org-caldav-inbox '(id "c14f-42fe-a358-648240e73991"))
(setq org-caldav-save-directory "~/Documentos/org/"))

Esto es un workaround para un bug raro de url-cookie:

;; source http://emacs.stackexchange.com/questions/5469/invalid-date-01-jan-2055
(defun url-cookie-expired-p (cookie)
"Return non-nil if COOKIE is expired."
(let ((exp (url-cookie-expires cookie)))
(and (> (length exp) 0)
        (condition-case ()
            (> (float-time) (float-time (date-to-time exp)))
        (error nil)))))
Añadir timestamp al terminar tarea
(setq org-log-done 'time)
Archivado
(setq org-archive-mark-done t)

Edición, diseño y varios

Definir lenguajes que entiende babel
(org-babel-do-load-languages
'org-babel-load-languages
'((dot . t)
(emacs-lisp . t)
(gnuplot . t)
(latex . t)
(ledger . t)
(python . t)
(shell . t)
(sql . t)
(sqlite . t)
(elasticsearch . t)
(http . t)))
(use-package yaml-mode
:ensure t
:config
(add-to-list 'auto-mode-alist '("\\.ya?ml\\'" . yaml-mode)))
(add-to-list 'org-src-lang-modes '("yaml" . yaml))
(add-to-list 'org-src-lang-modes '("dockerfile" . dockerfile))
Asteriscos bonitos

Requerir el paquete y activarlo sólo cuando se abra un buffer de org-mode.

(unless (require 'org-bullets nil 'noerror)
(sleep-for 5))

(use-package org-bullets
:init
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
:ensure t)
Seguir links

Presionando tanto RET cómo TAB.

(setq org-return-follows-link t)
(setq org-tab-follows-link t)
Exportar a Markdown
(use-package ox-md)
Exportar rst
(add-to-list 'el-get-sources   '(:name ox-rst
                                    :type github
                                    :pkgname "masayuko/ox-rst"))

(if (not (el-get-package-installed-p 'ox-rst))
(el-get 'sync 'ox-rst))

(use-package ox-rst
:load-path "el-get/ox-rst")
Exportar a asciidoc
(use-package ox-asciidoc
  :ensure t)
Configuracion de bloques de código
(setq org-src-fontify-natively t)
(setq org-src-tab-acts-natively t)
(setq org-src-preserve-indentation t)
(setq org-edit-src-content-indentation 0)
Elementos de marcado

La primera línea esconde los símbolos y aplica el marcado, y la segunda cambia el color a los elementos de marcado que empiezan por =.

(setq org-hide-emphasis-markers t)
(add-to-list 'org-emphasis-alist '("=" (:foreground "cyan")))
Quitar confirmación al evaluar código

Cada vez que se evalua código de un bloque, pide que se confirme. Con el siguiente código, no lo hará.

(setq org-confirm-babel-evaluate nil)
Añadir imágenes in-line
(org-display-inline-images t t)
;; Con un tamaño a concretar inline: #+attr_org: :width 750px
(setq org-image-actual-width nil)
org2blog

No está cargado ni configurado, lo mantengo por si acaso. Para publicar articulos con marcado org-mode en wordpress.

(defun org2web-add-keys()
(local-set-key "n" (quote org2blog/wp-new-entry))
(local-set-key "p" (quote org2blog/wp-post-buffer)))

(add-hook 'org2blog/wp-mode-hook 'org2web-add-keys)

(require 'org2blog-autoloads)

;; habia un bug raro que hace que tengas que tener dos blogs puestos
(setq org2blog/wp-blog-alist
    '(("blog"
        :url "http://blog.net/xmlrpc.php"
        :username "drymer"
        :default-title "Hola Mundo"
        :tags-as-categories nil)
    ("my-blog"
        :url "http://username.server.com/xmlrpc.php"
        :username "admin")))

(setq org2blog/wp-use-sourcecode-shortcode nil)
nikola

Sirve para publicar en nikola con marcado org-mode. Las funciones cutres son mías.

#+name:org2nikola

(use-package org2nikola
:load-path "~/Proyectos/org2nikola/"
:init
;; Se instala el htmlize de melpa, el de org-mode es demasiado viejo
(use-package htmlize :ensure t)
:config
(setq org2nikola-output-root-directory (concat (getenv "HOME") "/Documentos/BadDaemons"))
(setq org2nikola-use-verbose-metadata t))

(defun daemons/nikola-deploy-partido ()
"Ejecuta un script que tira de at para programar el push al repositorio git."
(interactive)
(shell-command (concat "/bin/bash $HOME/Documentos/BadDaemons/scripts/deploy-partido.sh " (org-read-date))))

;; Las dos siguientes funciones probablemente no sirvan a nadie
(defun daemons/nikola-url-post ()
"Devuelve el enlace del articulo en el que esté el cursor."
(interactive)
(setq url (concat "https://daemons.it/posts/"
                (cdr (car (org-entry-properties (point) "post_slug")))))
(message url)
(kill-new url))

(defun daemons/nikola-url-config ()
"Devuelve el enlace de la parte de la configuración en la que esté el cursor."
(interactive)
(setq url (concat "https://daemons.it/stories/mi-configuracin-de-emacs/#"
                (cdr (car (org-entry-properties (point) "CUSTOM_ID")))))
(message url)
(kill-new url))

(use-package nikola
:load-path "~/Proyectos/nikola.el/"
:config
(setq nikola-output-root-directory "~/Documentos/BadDaemons/")
(setq nikola-verbose t)
(setq nikola-webserver-auto nil)
(setq nikola-webserver-host "127.0.0.1")
(setq nikola-webserver-port "8080")
(setq nikola-webserver-open-browser-p t)
(setq nikola-deploy-input t)
(setq nikola-deploy-input-default "Nuevo articulo")
(setq nikola-build-before-hook-script (concat nikola-output-root-directory "scripts/pre-build.sh"))
(setq nikola-build-after-hook-script (concat nikola-output-root-directory "scripts/post-build.sh")))
Notas a pie de página

Prefiero que aparezcan las notas debajo del arbol en el que se ha tomado.

(setq org-footnote-section nil)
toc-org
(use-package toc-org
:ensure t
:init
(add-hook 'org-mode-hook 'toc-org-enable))
Cifrar archivos
(use-package epa-file
:init
(epa-file-enable)
(setq epa-pinentry-mode 'loopback))
;; En el fichero ~/.gnupg/gpg-agent.conf tiene que estar:
;; allow-emacs-pinentry
;; allow-loopback-pinentry
;; Reiniciar con:
;; gpgconf --reload gpg-agent
Añadir el nombre a la propiedad

A diferencia de la función de writequit, esta establece el título como custom_id.

;; Fuente: https://writequit.org/articles/emacs-org-mode-generate-ids.html
;; requerir libreria de ayuda
(require 'org-id)

;; función que creará los id
(defun eos/org-custom-id-get (&optional pom create prefix)
"Get the CUSTOM_ID property of the entry at point-or-marker POM.
If POM is nil, refer to the entry at point. If the entry does
not have an CUSTOM_ID, the function returns nil. However, when
CREATE is non nil, create a CUSTOM_ID if none is present
already. PREFIX will be passed through to `org-id-new'. In any
case, the CUSTOM_ID of the entry is returned."
(interactive)
(org-with-point-at pom
(let ((id (org-entry-get nil "CUSTOM_ID")))
    (cond
    ((and id (stringp id) (string-match "\\S-" id))
    id)
    (create
    (setq id (org-get-heading))
    (org-entry-put pom "CUSTOM_ID" id)
    (org-id-add-location id (buffer-file-name (buffer-base-buffer)))
    id)))))

(defun eos/org-add-ids-to-headlines-in-file ()
"Add CUSTOM_ID properties to all headlines in the
current file which do not already have one."
(interactive)
(org-map-entries (lambda () (eos/org-custom-id-get (point) 'create))))
Más profundidad en imenu
(setq org-imenu-depth 50)
Empareja simbolos de marcado y paréntesis
(modify-syntax-entry ?/ "(/" org-mode-syntax-table)
(modify-syntax-entry ?* "(*" org-mode-syntax-table)
(modify-syntax-entry ?_ "(_" org-mode-syntax-table)
(modify-syntax-entry ?= "(=" org-mode-syntax-table)
org-protocol
(use-package org-protocol)
Temas para exportación en html
(add-to-list 'el-get-sources '(:name org-html-themes
                                    :type github
                                    :pkgname "fniessen/org-html-themes"))

(if (not (el-get-package-installed-p 'org-html-themes))
(el-get 'sync 'org-html-themes))
Ejecución de bloques babel asyncrona
(add-to-list 'el-get-sources '(:name ob-async
                                    :type github
                                    :pkgname "astahlman/ob-async"))

(if (not (el-get-package-installed-p 'ob-async))
(el-get 'sync 'ob-async))

(use-package ob-async
:load-path "el-get/ob-async/")
org-brain

De momento no lo uso. Igual en el futuro.

(add-to-list 'el-get-sources '(:name org-brain
                                    :type github
                                    :pkgname "Kungsgeten/org-brain"))

(if (not (el-get-package-installed-p 'org-brain))
(el-get 'sync 'org-brain))

(use-package org-brain
:load-path "el-get/org-brain"
:config
(setq org-brain-path "~/Documentos/org/brain/"))
Mostrar imágenes
(org-display-inline-images)
Abrir nota aleatoria
(use-package org-randomnote
:ensure t
:config
(setq org-randomnote-open-behavior 'indirect-buffer)
(setq org-randomnote-candidates '("~/Documentos/org/cuaderno.org")))
Hábitos
(use-package org-habit
:init
(add-to-list 'org-modules 'org-habit)
:config
(setq org-habit-preceding-days 7
        org-habit-following-days 0
        org-habit-graph-column 50
        org-habit-show-habits-only-for-today t
        org-habit-show-all-today t))
org-yank-rich
(add-to-list 'el-get-sources '(:name org-rich-yank
				     :type github
				     :pkgname "unhammer/org-rich-yank"))

(if (not (el-get-package-installed-p 'org-rich-yank))
    (el-get 'sync 'org-rich-yank))

(use-package org-rich-yank
  :load-path "el-get/org-rich-yank")

(general-define-key :keymaps 'org-mode-map
                    :prefix my-spc-prefix
                    :states '(normal visual)
                    "cY" 'org-rich-yank)
org-download

Para mover imágenes comodamente.

(use-package org-download
  :ensure t
  :init
  (setq org-download-image-dir "./img/")
  (setq org-download-heading-lvl nil)
  (setq org-download-image-html-width 750))
Mostrar horas en vez dias
(setq org-duration-format 'h:mm)

Paquetes genéricos

Movimiento y gestión

Ivy/counsel/swipper

Ivy es más liviano que helm, aunque más simple. Más información aquí.

#+name:ivy-mode

(unless (require 'ivy nil 'noerror)
  (sleep-for 5))

(use-package ivy
  :init
  ;; Añade los buffers de bookmarks y de recentf
  (setq ivy-use-virtual-buffers t)
  ;; Muestra las coincidencias con lo que se escribe y la posicion en estas
  (setq ivy-count-format "(%d/%d) ")
  ;; Un mejor buscador
  (setq ivy-re-builders-alist
	'((read-file-name-internal . ivy--regex-fuzzy)
	  (t . ivy--regex-plus)))
  ;; No se sale del minibuffer si se encuentra un error
  (setq ivy-on-del-error-function nil)
  ;; ivy mete el simbolo ^ al ejecutar algunas ordenes, así se quita
  (setq ivy-initial-inputs-alist nil)
  ;; Dar la vuelta a los candidatos
  (setq ivy-wrap t)
  ;; Ver la ruta de los ficheros virtuales
  (setq ivy-virtual-abbreviate 'full)
  ;; Seleccionar el candidato actual (C-m en vez de C-S-m)
  (setq ivy-use-selectable-prompt t)

  ;; Asegurarse de que están smex, flx y ivi-hydra
  (use-package smex :ensure t)
  (use-package flx :ensure t)
  (use-package ivy-hydra :ensure t)
  :config
  (ivy-mode 1)
  (setq magit-completing-read-function 'ivy-completing-read)
  :diminish ivy-mode
  :ensure t)

(use-package counsel
	 :config
	 (setq counsel-find-file-at-point t)
	 :ensure t)

(use-package swiper
  ;; comentado en favor de ace-isearch
  ;; :bind (;; Sustituir isearch
  ;; 	 ("C-s" . swiper)
  ;; 	 ("C-r" . swiper))
  :ensure t)

;; Atajos de teclado
(spc-map
 "c" '(nil :which-key "general prefix")
 "cr" 'ivy-resume
 "ci" 'counsel-imenu
 "cy" 'counsel-yank-pop
 "ck" 'counsel-rg
 "cq" 'counsel-org-tag
 "SPC" 'counsel-M-x)

(general-define-key
 :keymaps 'ivy-minibuffer-map
 "M-y" 'ivy-next-line-and-call)

Salir con ESC:

(use-package evil-escape
  :ensure t
  :config
  (general-define-key
   :keymaps '(ivy-minibuffer-map
	      ivy-switch-buffer-map
	      ivy-mode-map
	      ivy-occur-mode-map
	      ivy-occur-grep-mode-map)
   "<escape>" 'evil-escape))
ace-isearch
(use-package ace-isearch
  :ensure t
  :init
  ;; Dependencias
  ;; (use-package helm-swoop :ensure t)
  (use-package avy
    :ensure t
    :config
    (setq avy-all-windows t))
  ;; (use-package ace-jump-mode :ensure t)
  :config
  (setq avy-background t)
  (setq ace-isearch-function 'avy-goto-char)
  (setq ace-isearch-input-length 5)
  (setq ace-isearch-jump-delay 0.30)
  (setq ace-isearch-use-jump 'printing-char)
  (setq ace-isearch-function-from-isearch 'ace-isearch-swiper-from-isearch)
  (global-ace-isearch-mode +1)
  (global-ace-isearch-mode -1)
  (global-ace-isearch-mode +1)
  :bind (:map isearch-mode-map
	      ("C-'" . avy-isearch))
  :diminish ace-isearch-mode)
counsel-dash

Necesita helm, no está correctamente separado. Inactivo.

#+name:counsel-dash-conf

(add-to-list 'el-get-sources '(:name counsel-dash
				     :description "counsel-dash"
				     :type github
				     :pkgname "nathankot/counsel-dash"))

(if (not (el-get-package-installed-p 'counsel-dash))
  (progn
    (package-install 'helm)
    (package-install 'dash-functional)
    (package-install 'helm-dash)
    (el-get 'sync 'counsel-dash)))

(use-package counsel-dash
  :load-path "el-get/counsel-dash"
  :init
  (setq counsel-dash-docsets-path "~/.emacs.d/docsets/")
  (setq helm-dash-docsets-path counsel-dash-docsets-path)
  (setq counsel-dash-common-docsets '("Bash" "Emacs Lisp" "HTML" "Markdown" "Nginx" "Python 3" "Docker" "Font_Awesome" "LaTeX" "MySQL" "Python 2" "SQLite" "Ansible" "Apache_HTTP_Server" "HTML" "Nginx"))
  (setq counsel-dash-browser-func 'eww))

Auto-instala los docsets:

(if (not (concat counsel-dash-docsets-path "Bash.docset"))
    (let ((local_docsets counsel-dash-common-docsets)
	  (docs))
      (while local_docsets
	(setq docs (car local_docsets))
	(if (string-match "Python" docs)
	    (setq docs (replace-regexp-in-string " " "_" docs)))
	(if (string-match "Emacs Lisp" docs)
	    (setq docs (replace-regexp-in-string " " "_" docs)))
	(if (not (file-exists-p (concat counsel-dash-docsets-path "/" (car local_docsets) ".docset")))
	    (progn
	      (counsel-dash-install-docset docs)
	      (setq local_docsets (cdr local_docsets)))
	  (setq local_docsets (cdr local_docsets))))))
Helm

Copiado del git de helm. Esta es una configuración bastante mínima. Más información por aquí. Está inactivo.

#+name:helm

(require 'helm)
(require 'helm-config)

(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))

(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-z")  'helm-select-action)

(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(global-set-key (kbd "C-x b") 'helm-mini)
(global-set-key (kbd "C-x C-f") 'helm-find-files)
(global-set-key (kbd "M-x") 'helm-M-x)

(helm-mode 1)

(require 'helm-descbinds)
(helm-descbinds-mode)
Buscar más eficazmente en Helm

Más información en este articulo. Desactivado actualmente.

#+name:buscar-helm

(custom-set-variables
 '(ace-isearch-input-length 7)
 '(ace-isearch-jump-delay 0.25)
 '(ace-isearch-function 'avy-goto-char)
 '(ace-isearch-use-jump 'printing-char))
Projectile
(use-package projectile
  :ensure t
  :init
  (use-package counsel-projectile
    :ensure t
    :config
    (counsel-projectile-mode))
  (projectile-mode)
  (setq projectile-switch-project-action #'counsel-projectile-find-file)
  :diminish projectile-mode)
Atajos de teclado:
(spc-map
 "p" '(nil :which-key "projectile prefix")
 "pb" 'projectile-switch-to-buffer
 "pf" 'projectile-find-file
 "pp" 'projectile-switch-project
 "pr" 'projectile-replace-regexp
 "pk" 'projectile-kill-buffers
 "ps" 'counsel-projectile-rg
 "pm" 'projectile-multi-occur
 "pe" 'projectile-run-eshell)
Modifica la ruta real por la simbolica:
(defun daemons/projectile-project-root (arg)
  (replace-regexp-in-string "\\(/media/.secret/Casa\\|/media/.secret/Trabajo\\)" (getenv "HOME") arg))

(advice-add 'projectile-project-root :filter-return #'daemons/projectile-project-root)
org-projectile:
(add-to-list 'el-get-sources '(:name org-projectile
				     :type github
				     :pkgname "IvanMalison/org-projectile"))

(if (not (el-get-package-installed-p 'org-projectile))
    (el-get 'sync 'org-projectile))

(use-package org-projectile
  :load-path "el-get/org-projectile"
  :config
  (org-projectile-per-project)
  (setq org-projectile-per-project-filepath "TODO.org")
  (setq org-agenda-files (append org-agenda-files (org-projectile-todo-files)))
  (push (org-projectile-project-todo-entry) org-capture-templates)
  (spc-ma "ap" 'org-projectile-project-todo-entry))
which-key
(use-package which-key
  :ensure t
  :config
  (setq which-key-allow-evil-operators t)
  (setq which-key-show-operator-state-maps t)
  (which-key-mode))
ace-window

Antes usaba esto:

(use-package switch-window
  :ensure t
  :bind ("C-x o" . switch-window))

Ahora uso esto:

(use-package ace-window
  :ensure t
  :config
  (setq aw-scope 'frame)
  (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))

;; Atajos de teclado
(spc-map "o" 'ace-window)
Mostrar teclas presionadas en un buffer
(use-package mwe-log-commands
  :ensure t)
Hardcodear atajos de teclado

Desactivado en modo emacs, en modo evil está activo #+name:hardcore-mode

(use-package hardcore-mode
  :ensure t
  :config
  (global-set-key "\M-p" 'backward-paragraph)
  (global-set-key "\M-n" 'forward-paragraph)
  (define-key key-translation-map [?\C-h] [?\C-?])
  (global-set-key (kbd "<f1>") 'help-command)
  (define-key hardcore-mode-map
    (kbd "<C-up>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use M-p instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-down>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use M-n instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-left>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use M-b instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-right>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use M-f instead.")))
  (define-key hardcore-mode-map
    (kbd "<prior>") (lambda ()
			(interactive)
			(message "This key is disabled. Use M-v instead.")))
  (define-key hardcore-mode-map
    (kbd "<next>") (lambda ()
			(interactive)
			(message "This key is disabled. Use C-v instead.")))
  (define-key hardcore-mode-map
    (kbd "<home>") (lambda ()
			(interactive)
			(message "This key is disabled. Use C-a instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-home>") (lambda ()
			(interactive)
			(message "This key is disabled. Use M-< instead.")))
  (define-key hardcore-mode-map
    (kbd "<end>") (lambda ()
			(interactive)
			(message "This key is disabled. Use C-e instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-end>") (lambda ()
			(interactive)
			(message "This key is disabled. Use M-> instead.")))
  (global-hardcore-mode))

Modo evil:

(use-package hardcore-mode
  :ensure t
  :init
   (setq too-hardcore-backspace t)
   (setq too-hardcore-return t)
   (setq general-implicit-kbd nil)
  :config
  (general-define-key :keymaps 'hardcore-mode-map
                    :states '(normal insert visual emacs)
                    "C-up" (lambda ()
                           (interactive)
                           (message "This key is disabled. Use M-p instead."))))
  (define-key hardcore-mode-map
    (kbd "<C-down>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use M-n instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-left>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use b instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-right>") (lambda ()
		       (interactive)
		       (message "This key is disabled. Use w or e instead.")))
  (define-key hardcore-mode-map
    (kbd "<M-v>") (lambda ()
			(interactive)
			(message "This key is disabled. Use C-u instead.")))
  (define-key hardcore-mode-map
    (kbd "<C-v>") (lambda ()
			(interactive)
			(message "This key is disabled. Use C-d instead.")))
  (define-key hardcore-mode-map
    (kbd "<M-<>") (lambda ()
			(interactive)
			(message "This key is disabled. Use gg instead.")))
  (define-key hardcore-mode-map
    (kbd "<M->>") (lambda ()
			(interactive)
			(message "This key is disabled. Use G instead.")))
  (define-key hardcore-mode-map
    (kbd "<M-x>") (lambda ()
			(interactive)
			(message "This key is disabled. Use SPC SPC instead.")))
  (global-hardcore-mode))

Testing:

(general-create-definer daemons-hardcore-map
   :states '(normal visual motion insert))

(defun daemons-hardcore-disabled()
  (interactive)
  (message "You're not evil enough. Shame on you!"))

(daemons-hardcore-map
  "<C-down>" 'daemons-hardcore-disabled
  "<C-left>" 'daemons-hardcore-disabled
  "<C-up>" 'daemons-hardcore-disabled
  "<C-right>" 'daemons-hardcore-disabled
  "M-v" 'daemons-hardcore-disabled
  "C-s" 'daemons-hardcore-disabled
  "M-<" 'daemons-hardcore-disabled
  "M->" 'daemons-hardcore-disabled
  "M-x" 'daemons-hardcore-disabled
  "C-x b" 'daemons-hardcore-disabled
  "C-x C-f" 'daemons-hardcore-disabled
  "C-x C-s" 'daemons-hardcore-disabled
  "C-h f" 'daemons-hardcore-disabled
  "C-h v" 'daemons-hardcore-disabled
  "M-TAB" 'daemons-hardcore-disabled
  "C-h k" 'daemons-hardcore-disabled)
Hydra
(use-package hydra :ensure t)
undo-tree

Visualiza los cambios hechos con un arbol. Además, cuando se tira para atras y se hace un cambio, los primeros siguen accesibles.

(use-package undo-tree
  :diminish undo-tree-mode
  :ensure t
  :config
  (global-undo-tree-mode)
  (setq undo-tree-visualizer-timestamps t)
  (setq undo-tree-auto-save-history t)
  (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo-tree"))))
multiple-cursors

#+name:multiple-cursors

(use-package multiple-cursors
  :ensure t
  :bind
  ("C-S-c C-S-c" . mc/edit-lines)
  ("C-c ma" . mc/mark-all-dwim)
  ("C-c mp" . mc/mark-previous-lines)
  ("C-c mn" . mc/mark-next-lines)
  ("C-c mP" . mc/mark-previous-like-this)
  ("C-c mN" . mc/mark-next-like-this)
  ("C-c mh" . mc-hide-unmatched-lines-mode))
kanban.el
(use-package kanban :ensure t)
multifiles
(use-package multifiles
    :ensure t
    :bind (("C-c mf" . mf/mirror-region-in-multifile)))
emacs-purpose
(use-package window-purpose
  :ensure t
  ;; :init
  (use-package ivy-purpose :ensure t :config (ivy-purpose-setup))
  (use-package window-purpose-x :config (purpose-x-golden-ratio-setup))
  (setq purpose-user-mode-purposes
	'((python-mode . py)
	  (inferior-python-mode . py-int)
	  (org-mode . org)))
  (setq purpose-user-name-purposes
	'(("index.org" . agenda)
	  ("index.org_archive" . agenda)
	  ("web.org" . agenda)
	  ("notas.org" . agenda)
	  (" *command-log*" . command)))
  (purpose-compile-user-configuration)
  :config
  ;; https://github.com/bmag/ivy-purpose/issues/1
  (define-purpose-prefix-overload purpose-switch-buffer-overload
    '(ivy-switch-buffer
      switch-buffer-without-purpose
      purpose-switch-buffer-with-purpose))
  (purpose-mode))
hideshow

Mostrar y esconder código.

(use-package hideshow
  :bind (("C-c <tab>" . hs-toggle-hiding))
  :config
  (hs-minor-mode))
expand-region
(use-package expand-region
  :ensure t
  :config
  (setq expand-region-contract-fast-key "z"))

(spc-map "r" 'er/expand-region)
free-keys
(use-package free-keys :ensure t)
helpful

Fuente: http://irreal.org/blog/?p=6812

(use-package helpful
  :ensure t)

;; Help
(spc-map
 "h" '(nil :which-key "help prefix")
 "hf" 'helpful-function
 "hv" 'helpful-variable
 "hk" 'helpful-key)
Golden Ratio

Gestiona las ventanas abiertas modificando el tamaño para hacerlo aceptable. Ignora los buffers concretados en la variable golden-ratio-exclude-buffer-regexp. Inactivo.

#+name:golden-ratio

(use-package golden-ratio
  :config
  ;; (defun init/no-golden-ratio-for-buffers (bufname)
  ;;   "Disable golden-ratio if BUFNAME is the name of a visible buffer."
  ;;   (and (get-buffer bufname) (get-buffer-window bufname 'visible)))
  ;; (defun init/no-golden-ratio ()
  ;;   "Disable golden-ratio for guide-key popwin buffer."
  ;;   (or (init/no-golden-ratio-for-buffers " *undo-tree*")
  ;;       (init/no-golden-ratio-for-buffers " *undo-tree Diff*")
  ;;       ))

  ;; (add-to-list 'golden-ratio-inhibit-functions
  ;;              'init/no-golden-ratio)

  (golden-ratio-mode t)
  (setq golden-ratio-exclude-buffer-regexp '("undo-tree" "help" "diff" "calendar" "messages" "Org Agenda" "Agenda Commands" "Org Select" "magit:" "Calendar"))
  (setq golden-ratio-auto-scale t)
  :diminish golden-ratio-mode
  :ensure t)
counsel-rg

Seguir enlaces simbólicos:

(setq counsel-rg-base-command "rg -L -S --no-heading --line-number --color never %s .")

(defun daemons/counsel-rg-occur ()
  "My daemons generate a custom occur buffer for `counsel-rg'."
  (counsel-grep-like-occur
   "rg -L -i --no-heading --line-number --color never -- %s ."))
(advice-add 'counsel-rg-occur :override #'daemons/counsel-rg-occur)
notmuch
(use-package notmuch
  :ensure t
  :init
  (setf notmuch-show-logo nil)
  (setf notmuch-mua-cite-function 'message-cite-original-without-signature)
  (setf message-kill-buffer-on-exit t)
  ;; Responder a todos en vez de responder a uno
  (define-key notmuch-show-mode-map "r" 'notmuch-show-reply)
  (define-key notmuch-show-mode-map "R" 'notmuch-show-reply-sender)
  (define-key notmuch-search-mode-map "r" 'notmuch-search-reply-to-thread)
  (define-key notmuch-search-mode-map "R" 'notmuch-search-reply-to-thread-sender)
  ;; Preguntar a quien envias el mail
  (setq notmuch-always-prompt-for-sender t)
  ;; Indentacion en cadenas
  (setq notmuch-show-indent-messages-width 4)
  ;; Mostrar los más nuevos primero
  (setq notmuch-search-oldest-first t)
  ;; Esconder mierdas
  (setq notmuch-show-all-multipart/alternative-parts nil)
  ;; Iniciar notmuch en modo emacs
  (evil-set-initial-state 'notmuch-hello-mode 'emacs)
  ;; Cabeceras al mínimo
  (setq notmuch-hello-sections '(notmuch-hello-insert-saved-searches))
  ;; Enviar mail sin mas
  (setq send-mail-function 'smtpmail-send-it)
  (setq message-sendmail-envelope-from 'header)
  (setq notmuch-show-all-multipart/alternative-parts nil)
  (add-hook 'notmuch-hello-mode-hook 'evil-insert-state)
  (defun daemons-notmuch-toggle-read ()
    "toggle unread tag for thread"
    (interactive)
    (if (member "unread" (notmuch-search-get-tags))
	(notmuch-search-tag '("-unread"))
      (notmuch-search-tag '("+unread"))))

  (general-define-key :keymaps 'notmuch-show-mode-map
		      :states '(normal visual)
		      "M-j" 'notmuch-show-next-message
		      "M-k" 'notmuch-show-previous-message
                "s" 'counsel-notmuch
		      "g" 'notmuch-poll-and-refresh-this-buffer
		      "u" 'daemons-notmuch-toggle-read
		      "C-c C-o" 'browse-url-at-point)

  (general-define-key :keymaps 'notmuch-search-mode-map
		      :states '(normal visual)
		      "g" 'notmuch-poll-and-refresh-this-buffer
		      "u" 'daemons-notmuch-toggle-read
                "s" 'counsel-notmuch
		      "C-c C-o" 'browse-url-at-point)

  (general-define-key :keymaps 'notmuch-hello-mode-map
		      :states '(normal visual)
		      "g" 'notmuch-poll-and-refresh-this-buffer
                "s" 'counsel-notmuch
		      "C-c C-o" 'browse-url-at-point
		      "u" 'daemons-notmuch-toggle-read))

(use-package org-notmuch
  :load-path "~/.emacs.d/el-get/org-mode-maint/contrib/lisp/")

(use-package counsel-notmuch
  :ensure t)
eyebrowse
(use-package eyebrowse
  :ensure t
  :diminish eyebrowse-mode
  :config
  (define-key eyebrowse-mode-map (kbd "M-1") 'eyebrowse-switch-to-window-config-1)
  (define-key eyebrowse-mode-map (kbd "M-2") 'eyebrowse-switch-to-window-config-2)
  (define-key eyebrowse-mode-map (kbd "M-3") 'eyebrowse-switch-to-window-config-3)
  (define-key eyebrowse-mode-map (kbd "M-4") 'eyebrowse-switch-to-window-config-4)
  (eyebrowse-mode t)
  (setq eyebrowse-new-workspace t))
dumb-jump
(use-package dumb-jump
  :ensure t
  :config
  (setq dumb-jump-force-searcher 'rg))

Programación

Flycheck

Corrector

(use-package flycheck
  :ensure t
  :config (global-flycheck-mode))
company-mode
(use-package company
  :ensure t
  :config
  (add-hook 'after-init-hook 'global-company-mode)
  (use-package company-ansible :ensure t)
  (use-package company-jedi :ensure t)
  (use-package company-terraform :ensure t)
  (use-package company-statistics :ensure t)

  (setq company-backends '((company-keywords
			    company-files
			    company-jedi
			    company-ansible
			    company-terraform
			    company-abbrev
			    company-capf)))
  (company-statistics-mode)
  (evil-define-key 'insert company-mode-map (kbd "C-SPC") 'company-complete)
  :diminish company-mode)
Magit y git
(use-package magit
  :ensure t
  :diminish magit-mode)

(use-package git-timemachine
  :ensure t)

(use-package evil-magit
  :ensure t)

(use-package magit-gitflow
  :ensure t
  :init
  (add-hook 'magit-mode-hook 'turn-on-magit-gitflow))

(spc-map
  "g" '(nil :which-key "git prefix")
  "gs" 'magit-status)

(general-define-key :keymaps 'magit-mode-map
                    :states '(normal)
                    :prefix my-spc-prefix
                     "gf" 'magit-gitflow-popup)

(evil-set-initial-state 'magit-popup-mode 'emacs)

;; Evita que se lie con los colores por defecto de git
(setq magit-git-global-arguments
      (nconc magit-git-global-arguments
             '("-c" "color.ui=false"
               "-c" "color.diff=false")))
;; Entra en modo inserción cuando se hace un commit
(add-hook 'with-editor-mode-hook 'evil-insert-state)

(use-package git-gutter
  :ensure t
  :init
  (global-git-gutter-mode t))

(use-package gitconfig
  :ensure t)
Pastear en sprunge.us
(add-to-list 'el-get-sources '(:name sprunge
				     :type github
				     :pkgname "tomjakubowski/sprunge.el"))

(if (not (el-get-package-installed-p 'sprunge))
    (el-get 'sync 'sprunge))

(use-package sprunge
  :init
  (use-package request :ensure t)
  :load-path "el-get/sprunge")
Yasnippet

Desactivado.

(use-package yasnippet
  :load-path "el-get/yasnippet/"
  :config
  (yas-global-mode)
  (setq yas-snippet-dirs
	'("~/.emacs.d/snippets"
	  "~/.emacs.d/el-get/yasnippet/snippets/"
	  "~/.emacs.d/el-get/yasnippet/yasmate/"))
  (add-to-list 'hippie-expand-try-functions-list 'yas-hippie-try-expand)
  (setq yas-prompt-functions '(yas-ido-prompt))
  :diminish yas-minor-mode)
Python

Hacer que emacs sea consciente de que existe python2 y python3:

(add-to-list 'interpreter-mode-alist '("python2" . python-mode))
(add-to-list 'interpreter-mode-alist '("python3" . python-mode))

La configuración de elpy:

(defun elpy-goto-definition-or-rgrep ()
  "Go to the definition of the symbol at point, if found. Otherwise, run `elpy-rgrep-symbol'."
    (interactive)
    (ring-insert find-tag-marker-ring (point-marker))
    (condition-case nil (elpy-goto-definition)
        (error (elpy-rgrep-symbol
                   (concat "\\(def\\|class\\)\s" (thing-at-point 'symbol) "(")))))

(use-package elpy
  :ensure t
  :init
  (use-package pyvenv :ensure t)
  (setq elpy-modules '(elpy-module-sane-defaults elpy-module-company elpy-module-eldoc elpy-module-pyvenv))
  (setq elpy-rpc-backend "jedi")
  :config
  (add-to-list 'ivy-completing-read-handlers-alist '(elpy-doc . completing-read-default)) ;; véase https://github.com/abo-abo/swiper/issues/892
  ;; Use pytest
  (setq elpy-test-runner 'elpy-test-pytest-runner)
  (setq elpy-test-pytest-runner-command '("tox"))
  (add-to-list 'elpy-project-ignored-directories "__pycache__")
  (add-to-list 'elpy-project-ignored-directories ".cache")
  (setq compilation-scroll-output 'first-error)
  (add-to-list 'auto-mode-alist '("\\.py" . python-mode))
  (add-to-list 'auto-mode-alist '("\\.py" . elpy-mode))
  (elpy-enable)
  (evil-define-key 'normal elpy-mode-map
      "gd" 'elpy-goto-definition-or-rgrep))

Probando jedi:

(use-package jedi
  :ensure t
  :init
  (add-hook 'python-mode-hook 'jedi:setup)
  (evil-define-key 'normal jedi-mode-map
      "gd" 'jedi-goto-definition))

Este paquete muestra una ralla que marca los 79 carácteres, para cumplir con el pep8.

(use-package fill-column-indicator
  :init
  (setq fci-rule-color "purple")
  (setq fill-column 79)
  (setq fci-rule-column 79)
  (add-hook 'python-mode-hook 'fci-mode)
  (add-hook 'emacs-lisp-mode-hook 'fci-mode)
  (add-hook 'sh-mode-hook 'fci-mode)
  :ensure t)

Corrección con flycheck, mejor que flymake:

(use-package flycheck
  :config
  ;; (setq flycheck-global-modes '(python-mode))
  ;; (global-flycheck-mode)
  (add-hook 'after-init-hook #'global-flycheck-mode)
  (spc-map
     "i" '(nil :which-key "flycheck prefix")
     "in" 'flycheck-next-error
     "ip" 'flycheck-previous-error
     "il" 'flycheck-list-errors)
  :diminish flycheck-mode
  :ensure t)
emacs-lisp
(use-package package-lint
:ensure t)

Miscélaneos

Hacer gifs con camcorder.el
(use-package camcorder
  :ensure t
  :config
  (setq camcorder-recording-command '("recordmydesktop" " --fps 100 --no-sound --windowid " window-id " -o " file)))
Paleta de colores
(use-package palette
  :ensure t)
Rainbow-mode

Muestra los colores de paletas HTML (hexadecimal) con el color que representa.

(use-package rainbow-mode
  :ensure t)
i3wm-config-mode

Muestra colores para la configuración de i3.

(add-to-list 'el-get-sources '(:name i3wm-config-mode
				     :type github
				     :pkgname "Alexander-Miller/i3wm-Config-Mode"))

(if (not (el-get-package-installed-p 'i3wm-config-mode))
    (el-get 'sync 'i3wm-config-mode))

(use-package i3wm-config-mode
  :load-path "el-get/i3wm-config-mode")
ansible-doc
(use-package ansible-doc
  :ensure t
  :config
  (add-hook 'yaml-mode-hook #'ansible-doc-mode))
Lorem Ipsum

Inserta Lorem Ipsum.

(if (not (el-get-package-installed-p 'lorem-ipsum))
    (el-get 'sync 'lorem-ipsum))

(use-package lorem-ipsum
  :load-path "el-get/lorem-ipsum")
csv-mode
(use-package csv-mode :ensure t)
lua-mode
(use-package lua-mode :ensure t)
rainbow-mode
(use-package rainbow-mode :ensure t)
ox-reveal
(use-package ox-reveal :ensure t)
terraform-mode
(use-package terraform-mode
  :ensure t
  :config
  (add-hook 'terraform-mode-hook 'terraform-format-on-save-mode))
ledger-mode
(use-package ledger-mode
  :ensure t
  :init
  (use-package flycheck-ledger :ensure t :mode "\\.ldg\\'")
  :mode "\\.ldg\\'")
groovy-mode
(use-package groovy-mode :ensure t)
json

Los archivos cuyo nombre termine por los mencionados abajo, usarán json-mode.

(use-package json-mode
  :mode "\\.json\\'"
  :ensure t)
Haskel

Lo usé un tiempo para xmonad, pero ya no está activo.

(use-package haskell-mode
  :config
  (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
  (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
  (add-hook 'haskell-mode-hook 'haskell-font-lock-symbols t)
  (put 'downcase-region 'disabled nil)
  :ensure t)
Markdown
  (use-package markdown-mode
    :init
    :config
    (setq markdown-xhtml-header-content "<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />")
    :mode "\\.md\\'"
    :ensure t)

Crear un TOC:

(use-package markdown-toc
  :ensure t
  :config
  (setq markdown-toc-header-toc-title "# Índice"))
DockerFile

Editar archivos DockerFile.

(use-package dockerfile-mode
  :mode "Dockerfile\\'"
  :ensure t)
kivy-mode

Si el paquete no está instalado, lo instala mediante el-get.

(use-package kivy-mode
  :mode "\\.kv\\'"
  :ensure t)
gnu-social-mode

No está activo, lo cargo de private-literate.org.

#+name:gnu-social

(add-to-list 'el-get-sources '(:name gnu-social-mode
                                     :description "gnu-social client"
                                     :type github
                                     :pkgname "bashrc/gnu-social-mode"))

(if (not (el-get-package-installed-p 'gnu-social-mode))
    (el-get 'sync 'gnu-social-mode))

(use-package gnu-social-mode
  :load-path "el-get/gnu-social-mode/"
  :init
  (setq gnu-social-server-textlimit 140
	gnu-social-server "quitter.se"
	gnu-social-username "drymer"
	gnu-social-password "lolazing"
	gnu-social-new-dents-count 1
	gnu-social-status-format "%i %s,  %@:\n  %h%t\n\n"
	gnu-social-statuses-count 200)

  (defhydra hydra-gnu-social (:color blue :hint nil)
    "
                                                                                 ╭────────────┐
            Posts                      User                 Groups               │ GNU social │
   ╭─────────────────────────────────────────────────────────────────────────────┴────────────╯
       _k_  [_t_] Post            _p_  [_f_] Follow                  ^_J_^ Join group        [_q_] Quit
       ^↑^  [_X_] Delete post     ^↑^  [_F_] Unfollow                ^_L_^ Leave Group
       ^↓^  [_r_] Repost          ^↓^  [_i_] Profile (browser)
       _j_  [_b_] Favorite        _n_   ^ ^
       ^ ^  [_RET_] Reply         ^ ^   ^ ^
       ^ ^  [_T_] Show Conversation
   --------------------------------------------------------------------------------------------
  "
    ("C-o"        keyboard-quit "Back")
    ("q"          keyboard-quit)
    ("j"          gnu-social-goto-next-status :color red)
    ("k"          gnu-social-goto-previous-status :color red)
    ("g"          beginning-of-buffer)
    ("G"          end-of-buffer)
    ("t"          gnu-social-update-status-interactive)
    ("X"          gnu-social-delete-notice)
    ("RET"        gnu-social-reply-to-all)
    ("r"          gnu-social-repeat)
    ("u"          gnu-social-current-timeline)
    ("b"          gnu-social-favorite)
    ("f"          gnu-social-follow)
    ("F"          gnu-social-unfollow)
    ("i"          gnu-social-view-user-page)
    ("T"          gnu-social-conversation-timeline)
    ("o"          gnu-social-click)
    ("n"          gnu-social-goto-next-status-of-user :color red)
    ("p"          gnu-social-goto-previous-status-of-user :color red)
    ("a"          gnu-social-toggle-activate-buffer)
    ("J"          gnu-social-group-join)
    ("L"          gnu-social-group-leave))

  :config
  (bind-keys :map gnu-social-mode-map
	     ("C-o" . hydra-gnu-social/body)
	     ("q" . gnu-social-kill-buffer)
	     ("Q" . gnu-social-edit-mode)
	     ("j" . gnu-social-goto-next-status)
	     ("k" . gnu-social-goto-previous-status)
	     ("h" . gnu-social-switch-to-next-timeline)
	     ("l" . gnu-social-switch-to-previous-timeline)
	     ("g" . beginning-of-buffer)
	     ("G" . end-of-buffer)
	     ("t" . gnu-social-update-status-interactive)
	     ("X" . gnu-social-delete-status)
	     ("RET" . gnu-social-reply-to-all)
	     ("r" . gnu-social-repeat)
	     ("u" . gnu-social-current-timeline)
	     ("b" . gnu-social-favorite)
	     ("f" . gnu-social-follow)
	     ("F" . gnu-social-unfollow)
	     ("i" . gnu-social-view-user-page)
	     ("T" . gnu-social-conversation-timeline)
	     ("o" . gnu-social-click)
	     ("n" . gnu-social-goto-next-status-of-user)
	     ("p" . gnu-social-goto-previous-status-of-user)
	     ("a" . gnu-social-toggle-activate-buffer)))
po-mode
(use-package po-mode
  :ensure t
  :config
  ;; Fuente: https://www.emacswiki.org/emacs/PoMode
  (defun po-wrap ()
    "Filter current po-mode buffer through `msgcat' tool to wrap all lines."
    (interactive)
    (if (eq major-mode 'po-mode)
	(let ((tmp-file (make-temp-file "po-wrap."))
	      (tmp-buf (generate-new-buffer "*temp*")))
	  (unwind-protect
	      (progn
		(write-region (point-min) (point-max) tmp-file nil 1)
		(if (zerop
		     (call-process
		      "msgcat" nil tmp-buf t (shell-quote-argument tmp-file)))
		    (let ((saved (point))
			  (inhibit-read-only t))
		      (delete-region (point-min) (point-max))
		      (insert-buffer tmp-buf)
		      (goto-char (min saved (point-max))))
		  (with-current-buffer tmp-buf
		    (error (buffer-string)))))
	    (kill-buffer tmp-buf)
	    (delete-file tmp-file))))))
mail-mode

Para abrir mails con mutt:

(add-to-list 'auto-mode-alist '(".*mutt-" . mail-mode))
lisp
Paredit
(use-package paredit
  :ensure t)
package-lint

Comprueba fallos y convenciones.

(use-package package-lint
  :ensure t)
rainbow-delimiters
(use-package rainbow-delimiters
  :ensure t
  :config
  (add-to-list 'auto-mode-alist '("\\.el\\'" . rainbow-delimiters-mode)))
compile-mode

Varias herramientas usan el modo compile, como molecule.el o elpy:

;; Fuente: https://stackoverflow.com/questions/13397737/ansi-coloring-in-compilation-mode
(use-package compile
  :config
  (defun colorize-compilation-buffer ()
    (let ((inhibit-read-only t))
      (ansi-color-apply-on-region (point-min) (point-max))))
  (add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
  (setq compilation-scroll-output t)
  :bind (
	 ("C-," . recompile)))
diminish

Hay ciertos modos cuya existencia no necesito que se me recuerde. Este paquete hace que no se muestren en el modeline:

(use-package diminish
  :ensure t)
elasticsearch-mode
(use-package es-mode
  :ensure t
  :mode "\\.es\\'"
  :config
  (add-to-list 'org-babel-load-languages '((elasticsearch . t))))
ob-http
(use-package ob-http
  :ensure t
  :config
  (add-to-list 'org-babel-load-languages '(http . t)))
speed-type
(use-package speed-type
  :ensure t)
google-translate
(use-package google-translate
  :ensure t
  :config
  (setq google-translate-translation-directions-alist
      '(("es" . "en") ("en" . "es"))))

(spc-map
    "T" 'google-translate-at-point
    "t" 'google-translate-smooth-translate)

Funciones personalizadas

Recargar todos los buffers abiertos

Es útil cuando los archivos se suelen sincronizar y se deja el pc abierto. Los archivos que esten abiertos y hayan cambiado, se refrescaran.

(defun daemons/reload-all-buffers ()
  "Recargar todos los buffers abiertos."
  (interactive)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (file-exists-p (buffer-file-name)) (not (buffer-modified-p)))
        (revert-buffer t t t) )))
  (message "Refreshed open files."))

Insertar cabeceras para org-mode

#+name:insertar-cabeceras

(defun org-mode-insert-header (language)
  "Make a template at point."
  (interactive
     (let ((languages '("Generic" "HTML" "LaTeX" )))
       (list (ido-completing-read "To which export: " languages))
       )
     )

  (when (string= language "Generic")
    (progn
      (insert (format "#+TITLE:\n"))
      (insert (format "#+AUTHOR:\n"))
      (insert (format "#+LANGUAGE: es \n"))
      (insert (format "#+OPTIONS: toc:1\n"))
      (insert (format "#+TOC: headlines 3\n"))
      (insert (format "#+STARTUP: indent\n\n"))
        )
    )

  (when (string= language "HTML")
    (progn
      (insert (format "#+TITLE:\n"))
      (insert (format "#+AUTHOR:\n"))
      (insert (format "#+LANGUAGE: ca\n"))
      (insert (format "#+OPTIONS:   toc:1\n"))
      (insert (format "#+TOC: headlines 3\n"))
      (insert (format (concat "#+SETUPFILE: " user-emacs-directory "/css/org-html-themes/setup/theme-readtheorg.setup\n\n")))
      )
    )

  (when (string= language "LaTeX")
    (progn
      (insert (format "#+Title:\n"))
      (insert (format "#+Author:\n"))
      (insert (format "#+LANGUAGE: es\n"))
      (insert (format "#+LATEX_CLASS: article\n"))
      (insert (format "#+LATEX_CLASS_OPTIONS: [spanish,a4paper]\n"))
      (insert (format "#+LATEX_HEADER: \\usepackage{color}\n"))
      (insert (format "#+LATEX_HEADER: \\usepackage[spanish]{babel}\n\n"))

      )
    )
  )

Insertar bloque src para org-mode

Además, funciona tanto sin ninguna región activa cómo con esta. De haber región activa, la envuelve.

#+name:insertar-bloque

(defun insert-org-src-block (choice)
  "Insert src code blocks."
  (interactive
     (if (org-at-table-p)
         (call-interactively 'org-table-rotate-recalc-marks)
       (let ((choices '("emacs-lisp" "python" "shell" "css" "ledger" "latex" "lisp" "sqlite")))
         (list (ido-completing-read "Source code type: " choices)))))

  (cond
   ((region-active-p)
    (let ((start (region-beginning))
	  (end (region-end)))
      (progn
	(goto-char end)
	(insert "\n#+END_SRC\n")
	(goto-char start)
	(insert (format "#+BEGIN_SRC %s\n" choice)))
      )
    )

   (t
    (insert (format "#+BEGIN_SRC %s\n" choice))
    (save-excursion (insert "\n#+END_SRC")))))

Insertar bloque src para markdown

(defun insert-src-markdown (choice)
  "Insert src code blocks."
  (interactive
     (if (org-at-table-p)
         (call-interactively 'org-table-rotate-recalc-marks)
       (let ((choices '("bash" "python" "css" "ledger" "latex" "lisp" "sqlite")))
         (list (ido-completing-read "Source code type: " choices)))))

  (cond
   ((region-active-p)
    (let ((start (region-beginning))
	  (end (region-end)))
      (progn
	(goto-char end)
	(insert "```\n")
	(goto-char start)
	(insert (format "```%s\n" choice)))
      )
    )

   (t
    (insert (format "```%s\n" choice))
    (save-excursion (insert "```\n")))))

Insertar org-entities

Más información aquí.

#+name:insertar-entidades

(setq org-pretty-entities t)

(defun modi/org-entity-get-name (char)
  "Return the entity name for CHAR. For example, return \"ast\" for *."
  (let ((ll (append org-entities-user
                    org-entities))
        e name utf8)
    (catch 'break
      (while ll
        (setq e (pop ll))
        (when (not (stringp e))
          (setq utf8 (nth 6 e))
          (when (string= char utf8)
            (setq name (car e))
            (throw 'break name)))))))

(defun modi/org-insert-org-entity-maybe (orig-fun &rest args)
  "When the universal prefix C-u is used before entering any character,
insert the character's `org-entity' name if available."
  (let ((pressed-key (char-to-string (elt (this-single-command-keys) 0)))
        entity-name)
    (when (and (listp args) (eq 4 (car args)))
      (setq entity-name (modi/org-entity-get-name pressed-key))
      (when entity-name
        (setq entity-name (concat "\\" entity-name "{}"))
        (insert entity-name)
        (message (concat "Inserted `org-entity' "
                         (propertize entity-name
                                     'face 'font-lock-function-name-face)
                         " for the symbol "
                         (propertize pressed-key
                                     'face 'font-lock-function-name-face)
                         "."))))
    (when (null entity-name)
      (apply orig-fun args))))

(advice-add 'org-self-insert-command :around #'modi/org-insert-org-entity-maybe)

Añadir soporte para editar archivos en docker

Lo siguiente lo mantengo por razones historicas, pero no lo tengo activo. Usar del siguiente modo: /docker:drunk_bardeen:/etc/passwd. Sacado de la wiki de emacs. Se puede usar el siguiente alias en bash para ver el nombre del container en ejecución:

alias dname="docker ps | perl -we 'use strict; $_ = <>; m/^(.*)NAMES/ or die; my $offset = length($1); while(<>) {substr($_, 0, $offset, q()); chomp; for(split m/\\W+/) {print qq($_:\n)} }'"

Desactivado de momento, no tengo docker en este pc.

#+name:docker-tramp

(push
 (cons
  "docker"
  '((tramp-login-program "docker")
    (tramp-login-args (("exec" "-it") ("%h") ("/bin/sh")))
    (tramp-remote-shell "/bin/sh")
    (tramp-remote-shell-args ("-i") ("-c"))))
 tramp-methods)

(defadvice tramp-completion-handle-file-name-all-completions
  (around dotemacs-completion-docker activate)
  "(tramp-completion-handle-file-name-all-completions \"\" \"/docker:\" returns
    a list of active Docker container names, followed by colons."
  (if (equal (ad-get-arg 1) "/docker:")
      (let* ((dockernames-raw (shell-command-to-string "docker ps | awk '$NF != \"NAMES\" { print $NF \":\" }'"))
             (dockernames (cl-remove-if-not
                           #'(lambda (dockerline) (string-match ":$" dockerline))
                           (split-string dockernames-raw "\n"))))
        (setq ad-return-value dockernames))
    ad-do-it))

Insertar fecha de hoy

Esta la he cogido de emacswiki:

(defun emacswiki/insert-current-date ()
  (interactive)
  (shell-command-to-string "echo -n $(date +%Y-%m-%d)"))

Siguiendo la misma tonica…:

(defun emacswiki/insert-current-week-number ()
  (interactive)
  (shell-command-to-string "echo -n $(date +%V)"))

Abrir eshell aquí

Sacada de la web Howardism.

(defun howardism/eshell-here ()
  "Opens up a new shell in the directory associated with the
current buffer's file. The eshell is renamed to match that
directory to make multiple eshell windows easier."
  (interactive)
  (let* ((parent (if (buffer-file-name)
                     (file-name-directory (buffer-file-name))
                   default-directory))
         (height (/ (window-total-height) 3))
         (name   (car (last (split-string parent "/" t)))))
    (split-window-vertically (- height))
    (other-window 1)
    (eshell "new")
    (rename-buffer (concat "*eshell: " name "*"))

    (insert (concat "ls"))
    (eshell-send-input)))

Reabrir buffer con sudo

Fuente: http://emacsredux.com/blog/2013/04/21/edit-files-as-root/">http://emacsredux.com/blog/2013/04/21/edit-files-as-root/ Fuente: http://stackoverflow.com/a/16408592">http://stackoverflow.com/a/16408592

Es una mezcla de ambas fuentes. #+name:abrir-sudo

(defadvice purpose-find-file-overload (after find-file-sudo activate)
  "Find file as root if necessary."
  (unless (and buffer-file-name
               (file-writable-p buffer-file-name))

    (let* ((buffer-file (buffer-file-name))
	   (coincidence (string-match-p "@" buffer-file))
	   (hostname)
	   (buffer-name))
      (if coincidence
	  (progn
	    (setq hostname (substring buffer-file (+ coincidence 1)
				      (string-match-p ":" buffer-file      (+ coincidence 1))))
	    (setq buffer-name
		  (concat
		   (substring buffer-file 0 coincidence) "@"
		   (replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
					     buffer-file nil nil nil (+ coincidence 1))))
	    (find-alternate-file buffer-name))
	  (find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))

(defadvice counsel-find-file (after find-file-sudo activate)
  "Find file as root if necessary."
  (unless (and buffer-file-name
               (file-writable-p buffer-file-name))

    (let* ((buffer-file (buffer-file-name))
	   (coincidence (string-match-p "@" buffer-file))
	   (hostname)
	   (buffer-name))
      (if coincidence
	  (progn
	    (setq hostname (substring buffer-file (+ coincidence 1)
				      (string-match-p ":" buffer-file      (+ coincidence 1))))
	    (setq buffer-name
		  (concat
		   (substring buffer-file 0 coincidence) "@"
		   (replace-regexp-in-string ":" (concat "|sudo:" hostname ":")
					     buffer-file nil nil nil (+ coincidence 1))))
	    (find-alternate-file buffer-name))
	  (find-alternate-file (concat "/sudo:root@localhost:" buffer-file))))))

(defadvice find-file (after find-file-sudo activate)
  "Find file as root if necessary."
  (unless (and buffer-file-name
               (file-writable-p buffer-file-name))
    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))

Antes usaba esto, ahora desactivado:

#+name:abrir-sudo-viejo

(defun sudo-edit (&optional arg)
  "Edit currently visited file as root.

With a prefix ARG prompt for a file to visit.
Will also prompt for a file to visit if current
buffer is not visiting a file."
  (interactive "P")
  (if (or arg (not buffer-file-name))
      (find-file (concat "/sudo:root@localhost:"
                         (ido-read-file-name "Find file(as root): ")))
    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))

Cutre-funciones de kanban

(defun daemons/update-kanban ()
  (interactive)
      (beginning-of-buffer)
      (re-search-forward "\+BEGIN: kanban" nil t)
      (recenter-top-bottom)
      (org-beginning-of-line)
      (org-ctrl-c-ctrl-c))

(defun daemons/goto-kanban ()
  (interactive)
  (switch-to-buffer "trabajo.org")
  (daemons/update-kanban))

(global-set-key (kbd "C-c g") 'daemons/goto-kanban)

ace-link-other-window

(use-package ace-link
  :ensure t
  :config
  (defun ace-link-other-window()
    (interactive)
    (switch-window)
    (ace-link)
    (switch-window)))

No matar buffer scratch

;; credits to stefan monier (GNU Emacs mantainer)
;; http://lists.gnu.org/archive/html/help-gnu-emacs/2017-02/msg00074.html
(with-current-buffer (get-buffer "*scratch*")
  (add-hook 'kill-buffer-hook
            (lambda () (error "DENIED! don't kill my precious *scratch*!!"))
            nil t)) ;; Append at the end of the hook list? no. Buffer-local? yes.

Copiar path del fichero

(defun ninrod/add-filename-to-kill-ring ()
  "Add current buffer filename to the kill-ring."
  (interactive)
  (let ((filename (if (equal major-mode 'dired-mode)
                      (expand-file-name (dired-copy-filename-as-kill))
                    (buffer-file-name))))
    (when filename
      (kill-new filename)
      (message "Added buffer filename '%s' to the kill-ring." filename))))

Fuente: https://github.com/ninrod/dotfiles/blob/master/emacs/boot.org#ninrodadd-filename-to-kill-ring

Pretty print xml

(require 'sgml-mode)

(defun ninrod/reformat-xml ()
  (interactive)
  (save-excursion
    (sgml-pretty-print (point-min) (point-max))
    (indent-region (point-min) (point-max))))

Fuente: https://github.com/ninrod/dotfiles/blob/master/emacs/boot.org#pretty-print-xml

Clonar y inicializar repositorio

(defun daemons/git-clone-and-init ()
  "Clone a git repository and set some variables on it."
  (interactive)
  (let* ((daemons-git-url (read-string "Clone repository: "))
	 (daemons-git-directory (read-directory-name
                "Clone to: " nil nil nil
                (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$"
				   daemons-git-url)
                     (match-string 1 daemons-git-url))))
	 (daemons-git-http-url (replace-regexp-in-string ":" "/"
							 daemons-git-url))
	 (daemons-git-http-url (replace-regexp-in-string "git@" "https://"
							 daemons-git-http-url))
	 (daemons-git-http-url (replace-regexp-in-string ".git$" "/"
							 daemons-git-http-url))
	 (output)
	 (result))
    (async-start
     `(lambda()
    	,(async-inject-variables "\\(daemons-git-\\)")
	(setq output (shell-command-to-string (format "git clone %s %s"
						      daemons-git-url
						      daemons-git-directory)))
	(setq default-directory daemons-git-directory)
	(shell-command-to-string (concat "git config --local orgit.status "
					 daemons-git-http-url))
	output)
     (lambda (result)
       (if (cl-search result "already exists and is not an empty directory.")
	   (message result)
	 (message "Git repository cloned!"))))))