Configuración de emacs a través de org-mode

Índice

Esta es mi configuración de emacs, la cuál pongo a disposición para que todo aquel que esté interesando pueda tomarla como referencia o usarla para su uso propio. Esta configuración corresponde a lo que va en mi ~/.emacs.d/init.el.

1 Instrucciones de intalación

Para hacer uso de esta configuración, necesitas lo siguiente:

  • Una copia de este documento.
  • Emacs 24 (> 24.3)
  • Org-mode (> 8.2)

Algo que no puedo asegurar, es el correcto funcionamiento de esta configuración en otros sistemas operativos distintos de linux.

Una vez que tengas la copia de este documento, tu puedes copiarla en ~/.emacs.d/init.org. Entonces dentro de emacs teclea M-x org-babel-load-file. M-x significa Alt y x presionados al mismo tiempo, seguido de la Instrucción org-babel-load-file en el sub-buffer de emacs. Esto debería de evaluar todo el código emacs-lisp que se encuentra en este documento.

Si eventualmente hay cambios sobre el código de este documento, basta con presionar C-c i.

2 Repositorios

Lo primero es definir las fuentes de donde obtendremos nuestros paquetes. He definido 4 fuentes:

(require 'package)
(add-to-list 'package-archives
             '("marmalade" . "http://marmalade-repo.org/packages/") t)
(add-to-list 'package-archives
             '("tromey" . "http://tromey.com/elpa/") t)
(add-to-list 'package-archives
             '("elpa" . "http://elpa.gnu.org/packages/") t)
(add-to-list 'package-archives
            '("melpa" . "http://melpa.milkbox.net/packages/") t)

Una vez añadidos los repositorios de nuestros paquetes, hay que definir cuales van a ser los paquetes que vamos a utilizar y como los vamos a cargar de manera automática.

(package-initialize)
(when (not package-archive-contents)
  (package-refresh-contents))
(defvar my-packages
  '(auto-package-update
    nyan-mode
    nyan-prompt
    rainbow-delimiters
    flymake
    column-enforce-mode
    diminish
    saveplace
    highlight-chars
    neotree
    auto-complete
    apropos-fn+var
    autopair
    yasnippet
    flycheck
    paredit
    magit
    ido-ubiquitous
    smex
    find-file-in-repository
    projectile
    auctex
    ac-math
    auto-complete-auctex
    xml-rpc
    metaweblog
    org2blog
    htmlize
    netrc
    tagedit
    deferred
    python-mode
    ipython
    jedi
    ein
    ein-mumamo
    clojure-mode
    clojure-mode-extra-font-locking
    cider
    web-mode
    php-mode
    coffee-mode
    markdown-mode
    markdown-mode+
    ack
    cdlatex
    ob-sml
    jabber
    alert
    interleave
))
(dolist (p my-packages)
  (when (not (package-installed-p p))
    (package-install p)))

3 Interfaz gráfica

Algo que siempre me recriminan es la cuestión de que emacs se ve muy viejo. ¡El problema es qué ellos no saben que altamente configurable y personalizable!

Entonces, después de configurar hay que añadir los siguientes paquetes para comenzar a jugar con la interfaz de emacs.

(require 'flymake)
(require 'nyan-mode)
(require 'nyan-prompt)
(require 'rainbow-delimiters)
(require 'column-enforce-mode)

Establecemos el tamaño que tendrá al iniciar emacs.

(when window-system (set-frame-size (selected-frame) 80 36))

Establecemos una fuente agradable

(set-frame-font "Monofur 14")

Indicamos que queremos ver el número de lineas.

(global-linum-mode)

Indicamos que durante la edición podamos el número de linea y el número de columna en el que estamos trabajando

(setq column-number-mode t)

Cargamos los temas que vamos a aplicarle a emacs.

(add-to-list 'custom-theme-load-path "~/.emacs.d/temas")
(add-to-list 'load-path "~/.emacs.d/temas")
(load-theme 'tomorrow-night-bright t)

Indicamos que el título de la ventana va a ser el path del archivo que estamos editando en el buffer actual.

(setq-default frame-title-format "%b (%f)")

Una de las características que menos me gusta, es que el cursor se encuentre parpadeando, por lo que lo vamos a quitar. Así como que cada vez que hace una evaluación campaneé.

(blink-cursor-mode 0)
(setq ring-bell-function 'ignore)

Indicamos que resalte la linea actual

(global-hl-line-mode 1)

Quéremos que resalte los paréntesis y sus matchs.

(show-paren-mode 1)
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)

Inhabilitamos la barra de menús y de herramientas

(menu-bar-mode -1)
(when (fboundp 'scroll-bar-mode)
  (scroll-bar-mode -1)
  (tool-bar-mode -1))

Definimos una función para ingresar a pantalla completa.

(defun fullscreen ()
  "TO-DO."
  (interactive)
  (set-frame-parameter nil 'fullscreen
                       (if (frame-parameter nil 'fullscreen) nil 'fullboth)))
(global-set-key [f11] 'fullscreen)

Quiero que me enseñe el estado de la batería de la laptop, así como la hora actual.

(display-battery-mode t)
(display-time-mode)

Utilizamos a Nyan-Cat como indicador de la posición en el buffer.

(nyan-mode t)
(nyan-start-animation)
(setq nyan-wavy-trail t)

Limpiamos el mode-line

(defvar mode-line-cleaner-alist
  `((auto-complete-mode . " α")
    (yas/minor-mode . " υ")
    (paredit-mode . " π")
    (eldoc-mode . "")
    (column-enforce-mode . " 80")
    (abbrev-mode . "")
    (lisp-interaction-mode . " λ")
    (hi-lock-mode . "")
    (python-mode . " Π")
    (emacs-lisp-mode . " ε")
    (nxhtml-mode . " nx")
    (fundamental-mode . " F")
    (latex-mode . " Φ")
    (flycheck-mode . " Γ")
    (magit-auto-revert-mode . " gR")
    (yas-global-mode . " ψ")
    (yas-minor-mode . " ψ")
    (projectile-mode . " ρ"))
  "Una lista para 'clean-mode-line'.")

(defun clean-mode-line ()
  "TO-DO."
  (interactive)
  (loop for cleaner in mode-line-cleaner-alist
        do (let* ((mode (car cleaner))
                 (mode-str (cdr cleaner))
                 (old-mode-str (cdr (assq mode minor-mode-alist))))
             (when old-mode-str
                 (setcar old-mode-str mode-str))
             (when (eq mode major-mode)
               (setq mode-name mode-str)))))
(add-hook 'after-change-major-mode-hook 'clean-mode-line)

(defalias 'flymake-report-status 'flymake-report-status-slim)
(defun flymake-report-status-slim (e-w &optional status)
  "Show \"slim\" flymake status in mode line. E-W as. STATUS as."
  (when e-w
    (setq flymake-mode-line-e-w e-w))
  (when status
    (setq flymake-mode-line-status status))
  (let* ((mode-line " Φ"))
    (when (> (length flymake-mode-line-e-w) 0)
      (setq mode-line (concat mode-line ":" flymake-mode-line-e-w)))
    (setq mode-line (concat mode-line flymake-mode-line-status))
    (setq flymake-mode-line mode-line)
    (force-mode-line-update)))

4 Edición

Agregamos todos los paquetes que vayamos a necesitar

(require 'saveplace)
(require 'highlight-chars)
(require 'neotree)
(require 'auto-complete)
(require 'autopair)
(require 'yasnippet)
(require 'flycheck)
(require 'apropos)
(require 'auto-complete-config)
(require 'iso-transl)
(require 'undo-tree)

Verificamos la sintaxis de código al vuelo.

(global-flycheck-mode t)

No usamos tabs duros.

(setq-default indent-tabs-mode nil)

Configuramos a emacs de tal forma que pueda compartir el clipboard con el sistema operativo.

(setq
 x-select-enable-clipboard t
 x-select-enable-primary t
 save-interprogram-paste-before-kill t
 apropos-do-all t
 mouse-yank-at-point t)

Configuramos la búsqueda en el buffer.

(global-set-key (kbd "C-s") 'isearch-forward-regexp)
(global-set-key (kbd "C-r") 'isearch-backward-regexp)
(global-set-key (kbd "C-M-s") 'isearch-forward)
(global-set-key (kbd "C-M-r") 'isearch-backward)

Una característica que me gustaba de mis anteriores editores es el duplicar una linea de código.

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")

Creamos respaldos automáticos y la posición donde te quedaste en cada uno de los archivos.

(setq backup-directory-alist
      `(("." . ,(concat user-emacs-directory "backups"))))
(setq auto-save-default nil)
(setq-default save-place t)
(setq save-place-file (concat user-emacs-directory "places"))

Una buena práctica es evitar dejar espacios en blanco innecesarios. A continuación la configuración para quitar esos espacios al guardar.

(add-hook 'font-lock-mode-hook 'hc-highlight-trailing-whitespace)
(add-hook 'LaTeX-mode-hook 'hc-highlight-trailing-whitespace)
(add-hook 'latex-mode-hook 'hc-highlight-trailing-whitespace)
(add-hook 'python-mode-hook 'hc-highlight-trailing-whitespace)
(add-hook 'prog-mode-hook 'hc-highlight-trailing-whitespace)
(add-hook 'prog-mode-hook
           (lambda ()
             (add-to-list 'write-file-functions 'delete-trailing-whitespace)))
(add-hook 'LaTeX-mode-hook
           (lambda ()
             (add-to-list 'write-file-functions 'delete-trailing-whitespace)))
(add-hook 'LaTeX-mode-hook
          (lambda ()
            (add-to-list 'write-file-functions 'delete-blank-lines)))
(add-hook 'prog-mode-hook
          (lambda ()
            (add-to-list 'write-file-functions 'delete-blank-lines)))

Resaltado de caracteres a partir de la columna 80.

(add-hook 'LaTeX-mode-hook 'column-enforce-mode)
(add-hook 'python-mode-hook 'column-enforce-mode)
(add-hook 'prog-mode-hook 'column-enforce-mode)

Comentarios

;; Comentarios
(defun toggle-comment-on-line ()
  "Comenta o descomenta la línea actual."
  (interactive)
  (comment-or-uncomment-region (line-beginning-position) (line-end-position)))
(global-set-key (kbd "C-;") 'toggle-comment-on-line)

Otros

(defun die-tabs ()
  "Usa sólo 2 espacios para los tabs."
  (interactive)
  (set-variable 'tab-width 2)
  (mark-whole-buffer)
  (untabify (region-beginning) (region-end))
  (keyboard-quit))
(global-set-key [f8] 'neotree-toggle)
(put 'downcase-region 'disabled nil)
(setq create-lockfiles nil)
(setq inhibit-startup-message t)
(defvar ack-history nil
  "History for the `ack' command.")
(defun revert-buffer-no-confirm ()
    "Revert buffer without confirmation."
    (interactive)
    (revert-buffer t t))
(global-set-key (kbd "C-c r") 'revert-buffer-no-confirm)
(global-undo-tree-mode)
(global-set-key (kbd "C-c _") 'undo-tree-visualize)

Autocompletado

(add-to-list 'ac-dictionary-directories "~/.emacs.d/custom/dict")
(set-default 'ac-sources
             '(ac-source-abbrev
               ac-source-dictionary
               ac-source-yasnippet
               ac-source-words-in-buffer
               ac-source-words-in-same-mode-buffers
               ac-source-semantic))

(ac-config-default)

(dolist (m '(c-mode c++-mode java-mode org-mode))
  (add-to-list 'ac-modes m))

(global-auto-complete-mode t)
;; auto-complete mode extra settings
(setq ac-auto-start 2)
(setq ac-use-overriding-local-map nil)
(setq ac-use-menu-map t)
(setq ac-candidate-limit 20)

Paredit

(autoload 'enable-paredit-mode "paredit"
  "Turn on pseudo-structural editing of Lisp code." t)
(add-hook 'emacs-lisp-mode-hook       #'enable-paredit-mode)
(add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
(add-hook 'ielm-mode-hook             #'enable-paredit-mode)
(add-hook 'lisp-mode-hook             #'enable-paredit-mode)
(add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
(add-hook 'scheme-mode-hook           #'enable-paredit-mode)
(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
(add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)

Soporte para org-mode

(require 'org)
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(setq org-log-done t)
(setq org-agenda-files (list "~/org/alimentarias.org"
                             "~/org/estacionamiento.org"
                             "~/org/casa.org"
                             "~/org/IngenieríaSoftware.org"
                             "~/org/labsom.org"
                             "~/org/todo.org"))
(defvar count-words-buffer
  nil
  "*Number of words in the buffer.")
(defun wicked/update-wc ()
  "Whatever."
  (interactive)
  (setq count-words-buffer (number-to-string (count-words-buffer)))
  (force-mode-line-update))
(unless count-words-buffer
(run-with-idle-timer 1 t 'wicked/update-wc))
(unless (memq 'count-words-buffer global-mode-string)
  (add-to-list 'global-mode-string "words: " t)
  (add-to-list 'global-mode-string 'count-words-buffer t))
(defun count-words-buffer ()
  "Count the number of words in the current paragraph."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((count 0))
      (while (not (eobp))
        (forward-word 1)
        (setq count (1+ count)))
      count)))
(defun wicked/org-update-checkbox-count (&optional all)
  "Update the checkbox statistics in the current section.
This will find all statistic cookies like [57%] and [6/12] and update
them with the current numbers.  With optional prefix argument ALL,
do this for the whole buffer."
  (interactive "P")
  (save-excursion
    (let* ((buffer-invisibility-spec (org-inhibit-invisibility))
           (beg (condition-case nil
                    (progn (outline-back-to-heading) (point))
                  (error (point-min))))
           (end (move-marker
                 (make-marker)
                 (progn (or (outline-get-next-sibling) ;; (1)
                            (goto-char (point-max)))
                        (point))))
           (re "\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)")
           (re-box
            "^[ \t]*\\(*+\\|[-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)")
           b1 e1 f1 c-on c-off lim (cstat 0))
      (when all
        (goto-char (point-min))
        (or (outline-get-next-sibling) (goto-char (point-max))) ;; (2)
        (setq beg (point) end (point-max)))
      (goto-char beg)
      (while (re-search-forward re end t)
        (setq cstat (1+ cstat)
              b1 (match-beginning 0)
              e1 (match-end 0)
              f1 (match-beginning 1)
              lim (cond
                   ((org-on-heading-p)
                    (or (outline-get-next-sibling) ;; (3)
                        (goto-char (point-max)))
                    (point))
                   ((org-at-item-p) (org-end-of-item) (point))
                   (t nil))
              c-on 0 c-off 0)
        (goto-char e1)
        (when lim
          (while (re-search-forward re-box lim t)
            (if (member (match-string 2) '("[ ]" "[-]"))
                (setq c-off (1+ c-off))
              (setq c-on (1+ c-on))))
          (goto-char b1)
          (insert (if f1
                      (format "[%d%%]" (/ (* 100 c-on)
                                          (max 1 (+ c-on c-off))))
                    (format "[%d/%d]" c-on (+ c-on c-off))))
          (and (looking-at "\\[.*?\\]")
               (replace-match ""))))
      (when (interactive-p)
        (message "Checkbox statistics updated %s (%d places)"
                 (if all "in entire file" "in current outline entry")
                 cstat)))))
(defadvice org-update-checkbox-count (around wicked activate)
  "Fix the built-in checkbox count to understand headlines."
  (setq ad-return-value
        (wicked/org-update-checkbox-count (ad-get-arg 1))))

Fecha: [2015-03-27 vie 14:30]

Autor: Miguel Angel Piña Avelino

Email: miguel_pinia@ciencias.unam.mx

Validate