Skip to content

Latest commit

 

History

History
1516 lines (1300 loc) · 64.1 KB

emacs-init.org

File metadata and controls

1516 lines (1300 loc) · 64.1 KB

Mi configuración de GNU Emacs

Actiones nostras tibi comítimus, Dómine, ut ad maiorem gloriam tuam repleamur. (Te encomendamos, Señor, nuestras actividades para que las realicemos a mayor gloria tuya.)

Configuración de GNU Emacs en un archivo de org-mode

He decidido mover mi configuración a un sólo archivo. Anteriormente mi configuración estaba dividida en varios archivos .el, esto no era malo, sin embargo debo estar visitando diferentes archivos si deseo realizar varios cambios en mi configuración creándome una plétora de buffers en Emacs. Además, con org-mode me es posible documentar varios aspectos de mi configuración, sí, sí… ya sé que esto se puede hacer con comentarios en el código. Otro beneficio de usar org-mode y babel es la capacidad de contraer o expandir varias secciones de la configuración, o navegar rápidamente entre secciones (cosa que aun no sé hacer), además, con Babel no me veo restringido a ejecutar solamente código elisp ¡también puedo correr código Python!.

La Configuración

Pasemos a la materia. Esta configuración se carga de la siguiente manera desde el archivo ~/.emacs.d/init.el:

;; init.el para esta configuración. Tu Emacs debe ser versión 24.
(package-initialize)
(require 'ob-tangle)
(org-babel-load-file
 (expand-file-name "emacs-init.org"
                   user-emacs-directory))

activamos algunas opciones para depuración en caso de que Emacs falle en cargar la configuración.

;;(toggle-debug-on-error)
;;(toggle-debug-on-quit) ;; Se activa cuando el usuario presiona C-g

Información personal

(setf user-full-name "Jorge Araya Navarro"
      user-mail-address "[email protected]")

Repositorio de paquetes

Desde la versión 24 Emacs permite la instalación de paquetes de la misma manera como se realiza en distribuciones de GNU/Linux.

El sistema de paquetes de Emacs no es perfecto, para que algunos paquetes funcionen como deben, aun debes poner algunas cosas en tu configuración de Emacs y tal. Lo posible es que las mismas instrucciones estén dadas en la descripción del paquete.

(setf package-archives (list (quote ("gnu" . "http://elpa.gnu.org/packages/"))
                             (quote ("mermelade" . "http://marmalade-repo.org/packages/"))
                             (quote ("melpa" . "http://melpa.milkbox.net/packages/"))
                             (quote ("org" . "http://orgmode.org/elpa/"))))

Para ver que paquetes hay disponibles, y cuales desea instalar, puede hacer uso del comando M-x package-list-pactares

Listado, revisión e instalación de paquetes con Melpa

La situación es la siguiente: Quiero poder usar mi configuración en muchas partes, o quizás otros usuarios de GNU Emacs desean usar mi configuración. Sin embargo, no cuento con una lista de paquetes que tengo instalado en mi Emacs, y si alguien desea usar mi configuración puede tener errores debido a que no tiene los paquetes instalados que yo tengo.

Solución: usar org-babel para correr un trozo de código Python que genere un código Elisp que se encargue del problema :D.

Pero primero nos aseguramos de decirle a babel que nos habilite Python para usar ejecutar desde el archivo org!

(org-babel-do-load-languages
 'org-babel-load-languages
 '(
   (emacs-lisp . t)
   (python . t)
   (sh . t)
   )
)

script generador de la lista de paquetes a instalar

import os

if os.path.isdir(os.path.expanduser("~/.emacs.d/elpa/")):
    melpapackages = os.listdir(os.path.expanduser("~/.emacs.d/elpa/"))
    packagestoinstall = []
    for package in melpapackages:
        if os.path.isdir(os.path.expanduser("~/.emacs.d/elpa/") + package):
            index = package.rfind("-")
            if index >= 0:
                name = package[:index]
            else:
                name = package
                
            if not name.startswith("archives") and not name.startswith("gnupg"):
                packagestoinstall.append(
                    "(ignore-errors (use-package {0}\n  :ensure {0}))".format(
                        name))

    # Remove any repeated package. This can happen if different directories
    # with the same package name exists in the elpa/ directory
    packagestoinstall = list(set(packagestoinstall))

    # Sort things, please!
    packagestoinstall.sort()
    print("\n".join(packagestoinstall))

Y cargamos ese archivo :)

(unless (file-exists-p (expand-file-name "elpa/archives/melpa" user-emacs-directory))
  (package-refresh-contents))

(when (not (package-installed-p 'use-package))
  (package-install 'use-package))

(require 'use-package)
(load-file (expand-file-name "paquetes.el" user-emacs-directory))

Así es como, por el momento y de manera no muy elegante, resolvemos esta deficiencia! Código elisp para la instalación de los paquetes extraído de ésta otra configuración de Emacs.

Cargamos paquetes que no se instalan con ELPA.

;; carga un agregado para cuando se escriben correos usando mu4e
(load-file (expand-file-name "site-packages/u-vm-color/u-vm-color.el" user-emacs-directory))

Ubicación de temas personalizados

Emacs ofrece la posibilidad de tener una carpeta exclusiva para colocar temas personalizados o de terceros a traves de una variable llamada custom-theme-load-path. Todos los temas iran en la carpeta themes dentro de la carpeta raíz de Emacs.

(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))

Paquetes requeridos con require

Existen algunos paquetes que deben ser “requeridos” para la correcta activación de algunos modos mayores, funcionalidades, y demás cosas proveídas por Emacs o paquetes instalados en Emacs.

(require 'uniquify)
(require 'helm)
(require 'helm-config)
(require 'helm-files)
(require 'helm-grep)
(require 'helm-buffers)
(require 'helm-org)
(require 'helm-descbinds)
(require 'htmlize)
(require 'company)
(require 'hlinum)
(require 'fixmee)
(require 'expand-region)
(require 'web-mode)
(require 'epa-file)
(require 'visual-regexp)
(require 'visual-regexp-steroids)
(when (file-exists-p "/usr/share/emacs/site-lisp/go-mode.el")
  (require 'go-mode-load))

(require 'company-go)
(require 'org)
(require 'org-page)
(require 'undo-tree)
(require 'dired+)
(require 'muse-mode)
(require 'muse-project)
(require 'muse-docbook)
(require 'muse-book)
(require 'eyebrowse)
(require 'mediawiki)
(load "flymake")

Códigos elisp

funciones de Emacs lisp escritas por mi u otras personas (y que yo he recolectado para mi propio beneficio)

función para insertar etiquetas <kbd>

Gracias a Malabarba en su respuesta desde Emacs.stackexchange.

(defun endless/insert-key (key)
  "Ask for a key then insert its description.
Will work on both org-mode and any mode that accepts plain html."
  (interactive "kType key sequence: ")
  (let* ((is-org-mode (derived-mode-p 'org-mode))
         (tag (if is-org-mode
                  "@@html:<kbd>%s</kbd>@@"
                "<kbd>%s</kbd>")))
    (if (null (equal key "\r"))
        (insert
         (format tag (help-key-description key nil)))
      (insert (format tag ""))
      (forward-char (if is-org-mode -8 -6)))))

funciones con expresiones regulares que uso a menudo en edición de texto

estas son funciones que uso muy a menudo durante la edición de texto, tenerlos como comandos interactivos me ahorra tiempo escribiendo las expresiones regulares una y otra vez.

(defun shackra/regexp-una-sola-linea (start end)
  "Elimina todos los saltos de linea en la selección"
  (interactive "r")
  (vr/replace "\n+" " " start end)
  )

(defun shackra/regexp-un-solo-espacio (start end)
  "Elimina todos los espacios en blanco seguidos en la selección"
  (interactive "r")
  (vr/replace " +" " " start end)
  )

(defun shackra/muse-regexp-un-solo-marcado (start end)
  "Elimina los * que existan entre espacios en blanco en la selección para formar un solo termino marcado"
  (interactive "r")
  (vr/replace "\* \*" " " start end)
  )

reemplazo para comment-dwim

;; Original idea from
;; http://www.opensubscriber.com/message/[email protected]/10971693.html
(defun comment-dwim-line (&optional arg)
  "Replacement for the comment-dwim command.
        If no region is selected and current line is not blank
        and we are not at the end of the line, then comment
        current line.  Replaces default behaviour of
        comment-dwim, when it inserts comment at the end of the
        line."
  (interactive "*P")
  (comment-normalize-vars)
  (if (and (not (region-active-p)) (not (looking-at "[ \t]*$")))
      (comment-or-uncomment-region (line-beginning-position) (line-end-position))
    (comment-dwim arg)))

find-file y switch-buffer personalizados

Problema: Cuando estoy dentro de un proyecto con Projectile-mode, me gusta visitar archivos y buffers relacionados con el proyecto en el cual estoy trabajando. Projectile-helm es de mucha ayuda, sin embargo la combinación de teclas es muy extensa y la mayoría de veces no las uso.

Solución: Crear mis funciones personalizadas para find-file y switch-buffer.

find-file personalizado

(defun shackra:find-file ()
  (interactive)
  (call-interactively (if (equal current-prefix-arg '(4))
                          'find-file
                        ;; si no se llamo a la función con el argumento
                        ;; universal C-u. El comando se comporta normalmente
                        (if (projectile-project-p)
                            'helm-projectile-find-file
                          'find-file))))

switch-buffer personalizado

(defun shackra:switch-buffer ()
  (interactive)
  (call-interactively (if (equal current-prefix-arg '(4))
                          'helm-mini
                        ;; si no se llamo a la función con el argumento
                        ;; universal C-u. El comando se comporta normalmente
                        (if (projectile-project-p)
                            'helm-projectile-switch-to-buffer
                          'helm-mini))))

abrir archivos que estén en modo de solo lectura como root

Código sacado de aquí, según éste post en Emacs Redux.

(defun find-file-sudo ()
  "Reopen the current file with sudo privileges."
  (when (and buffer-file-name
           (not (file-writable-p buffer-file-name)))
    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))

Encierra los bloques _SRC de org en etiquetas <pre><code>

Le pedimos a org-mode que no meta las patas cuando exporta archivos a HTML. Nosotros manejaremos el marcado de sintaxis de código fuente.

Muchas gracias a chen bin por los trozos de código sacados de su propio proyecto :)

(defun org2html-trim-string (string)
  (replace-regexp-in-string "\\`[ \t\n]*" "" (replace-regexp-in-string "[ \t\n]*\\'" "" string)))

(defun org2html--char-to-string (ch)
  (let ((chspc 32)
        (chsq 39)
        (ch0 48)
        (ch9 57)
        (cha 97)
        (chz 122)
        (chA 65)
        (chZ 90)
        (chdot 46)
        (chminus 45)
        (chunderscore 95)
        rlt)
    (cond
     ((or (and (<= ch0 ch) (<= ch ch9))
          (and (<= cha ch) (<= ch chz))
          (and (<= chA ch) (<= ch chZ))
          (= chunderscore ch)
          (= chminus ch)
          )
      (setq rlt (char-to-string ch)))
     ((or (= chspc ch) (= chsq ch) (= chdot ch))
      (setq rlt "-")))
    rlt
    ))

(defun org2html-get-slug (str)
  (let (slug )
    (setq slug (mapconcat 'org2html--char-to-string str ""))
    ;; clean slug a little bit
    (setq slug (replace-regexp-in-string "\-\-+" "-" slug))
    (setq slug (replace-regexp-in-string "^\-+" "" slug))
    (setq slug (replace-regexp-in-string "\-+$" "" slug))
    (setq slug (org2html-trim-string slug))
    (setq slug (downcase slug))
    slug))

(defun org2html-replace-pre (html)
  "Replace pre blocks with sourcecode shortcode blocks.
shamelessly copied from org2blog/wp-replace-pre()"
  (save-excursion
    (let (pos code lang info params header code-start code-end html-attrs pre-class)
      (with-temp-buffer
        (insert html)
        (goto-char (point-min))
        (save-match-data
          (while (re-search-forward "<pre\\(.*?\\)>" nil t 1)

            ;; When the codeblock is a src_block
            (unless
                (save-match-data
                  (setq pre-class (match-string-no-properties 1))
                  (string-match "example" pre-class))
              ;; Replace the <pre...> text
              (setq lang (replace-regexp-in-string ".*src-\\([a-zA-Z0-9]+\\).*" "\\1" pre-class)  )

              (replace-match "")
              (setq code-start (point))

              ;; Go to end of code and remove </pre>
              (re-search-forward "</pre.*?>" nil t 1)
              (replace-match "")
              (setq code-end (point))
              (setq code (buffer-substring-no-properties code-start code-end))

              ;; Delete the code
              (delete-region code-start code-end)
              ;; Stripping out all the code highlighting done by htmlize
              (setq code (replace-regexp-in-string "<.*?>" "" code))

              ;; default is highlight.js, it's the best!
              (insert (concat "\n<pre><code class=\"lang-"
                              lang
                              "\">\n"
                              code
                              "</code></pre>\n"))

              )))

        ;; Get the new html!
        (setq html (buffer-substring-no-properties (point-min) (point-max))))
      ))
  html)

(defun org2html--render-subtree ()
  "Render current subtree"
  (let ((org-directory default-directory)
         html-file
         tags
         title
         post-slug
         html-text)

    ;; set title
    (setq title (nth 4 (org-heading-components)))

    ;; set POST_SLUG if its does not exist
    (setq post-slug (org2html-get-slug title))
    ;; html file
    (setq html-file (concat (file-name-as-directory default-directory) post-slug ".html"))
    (setq html-text (org2html-export-into-html-text))

    (save-excursion
      (setq html-text (org2html-replace-pre html-text)))

    (with-temp-file html-file
      (insert html-text))
    (message "%s created" html-file)
    ))

(defun org2html-export-into-html-text ()
  (let (html-text b e)

    (save-excursion
      (org-mark-element)
      (forward-line) ;; donot export title
      (setq b (region-beginning))
      (setq e (region-end))
      )

    ;; org-export-as will detect active region and narrow to the region
    (save-excursion
      (setq html-text
            (cond
             ((version-list-< (version-to-list (org-version)) '(8 0 0))
              (if (fboundp 'org-export-region-as-html)
                  (org-export-region-as-html b e t 'string)))
             (t
              (if (fboundp 'org-export-as)
                  (org-export-as 'html t nil t)))
             )))
    html-text))

(defun org2html-export-subtree ()
  "Export current first level subtree into HTML"
  (interactive)
  (let ((org-directory default-directory)
        html-file
        tags
        title
        post-slug
        html-text)

    ;; just goto the root element
    (condition-case nil
        (outline-up-heading 8)
      (error
       (message "at the beginning ...")))

    ;; should be nil
    (org2html--render-subtree)
    ))


(defun org2html-wrap-blocks-in-code (src backend info)
  (if (org-export-derived-backend-p backend 'html)
      (org2html-replace-pre src)))

Recrea el blog para probar el diseño

Llamamos al comando op/do-publication con algunos parámetros para ahorrarnos el procedimiento manual de publicar el blog a una carpeta

(defun shackra:ppp ()
  "Llama op/do-publication con una serie de parámetros predeterminados. Útil cuando se esta diseñando un tema"
  (interactive)
  (op/do-publication t t "/tmp/blog" nil))

Generación del blog y sincronización con RacketSpace

(defun shackra:syncblog ()
  "Sincroniza el blog generado con el contenedor en Racketspace"
  (interactive)
  ;; usa rclone para hacer la re-sincronización
  (start-process "sync rclone" (get-buffer-create "*rclone*") "rclone"
                 "sync"
                 (expand-file-name "~/Documentos/deshackra.com/elblog.deshackra.com")
                 "rscf:elblog.deshackra.com")
  )

(defun shackra:genblog ()
  "Genera y sincroniza el blog"
  (interactive)
  ;; borra el directorio con los datos antiguos y vuelve a generar el blog
  (delete-directory (expand-file-name "~/Documentos/deshackra.com/elblog.deshackra.com") t nil)
  (op/do-publication t nil "~/Documentos/deshackra.com/elblog.deshackra.com/" nil)
  ;; sincroniza
  (shackra:syncblog))

Emacs, no hagas éstas cosas… AKA “sane defaults”

Una colección de sentencias para cambiar algunas cosas de Emacs que son poco sanas, de ahí el nombre de “sane defaults” u opciones sanas predeterminadas. Debido a que esta sección de mi configuración se estaba llenando innecesariamente de entras decidí colocar todas las opciones dentro de un sólo bloque de código elisp.

(setf ;;solarized-high-contrast-mode-line t
      solarized-distinct-fringe-background t
      solarized-use-more-italic t
      solarized-scale-org-headlines t)
;;(load-theme 'jazz t) ;; enviaremos el tema a vacaciones por un tiempo
(load-theme 'solarized-dark t)
;;(powerline-center-theme)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1)
(recentf-mode 1)
(savehist-mode 1)
(set-frame-font "SourceCodePro 11")
(add-to-list (quote default-frame-alist) (quote (font . "SourceCodePro-11")))
(fset 'yes-or-no-p 'y-or-n-p)
(global-auto-revert-mode 1)
(column-number-mode 1)
(global-subword-mode 1)
(global-font-lock-mode 1)
(show-paren-mode t)
(delete-selection-mode 1)

(setf
 ;; hace que el buffer inicial al abrir un nuevo cuadro de Emacs sea la agenda
 ;; de org-mode
 initial-buffer-choice "~/org/cosasporhacer.org"
 x-underline-at-descent-line t ;; la linea que subraya es puesta en la base de
                               ;; la tipografía en lugar de en la linea base.
 load-prefer-newer t
 bookmark-default-file (expand-file-name "bookmarks" user-emacs-directory)
 bookmark-save-flag 1
 inhibit-startup-message t
 inhibit-startup-echo-area-message "jorge"
 initial-scratch-message nil
 line-spacing 1
 make-backup-files nil
 global-auto-revert-non-file-buffers t
 auto-revert-verbose nil
 echo-keystrokes 0.1
 shift-select-mode nil
 byte-compile-warnings '(not nresolved
                           free-vars
                           callargs
                           redefine
                           obsolete
                           noruntime
                           cl-functions
                           interactive-only)
 fill-column 80
 blink-matching-paren nil
 uniquify-buffer-name-style (quote forward)
 recentf-max-saved-items 100
 history-length 1000
 x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)
 enable-recursive-minibuffers t
 gc-cons-percentage 0.125
 undo-tree-mode-lighter ""
 ediff-diff-options "-w"
 ediff-split-window-function 'split-window-horizontally
 ediff-window-setup-function 'ediff-setup-windows-plain
 )

(set-default 'indent-tabs-mode nil)
(set-default 'indicate-empty-lines t)
(setq-default truncate-lines t)

(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)

(if
    (boundp 'buffer-file-coding-system)
    (setq-default buffer-file-coding-system 'utf-8)
  (setf default-buffer-file-coding-system 'utf-8))

;;(eval-after-load "yasnippet" '(diminish 'yas/minor-mode))
(eval-after-load "button-lock" '(diminish 'button-lock-mode))
(eval-after-load "org-indent" '(diminish 'org-indent-mode))
(eval-after-load "helm-mode" '(diminish 'helm-mode))
(eval-after-load "fixmee" '(diminish 'fixmee-mode))
(eval-after-load "elpy" '(diminish 'elpy-mode))
(eval-after-load "highlight-indentation" '(diminish 'highlight-indentation-mode))
(eval-after-load "autopair" '(diminish 'autopair-mode))
(eval-after-load "flycheck" '(diminish 'flycheck-mode))
(eval-after-load "flyspell" '(diminish 'flyspell-mode))
(eval-after-load "simple" '(diminish 'auto-fill-function))
(eval-after-load "company" '(diminish 'company-mode))
(eval-after-load "magit" '(diminish 'magit-auto-revert-mode))
(eval-after-load "eyebrowse" '(diminish 'eyebrowse-mode))
(eval-after-load "subword-mode" '(diminish 'subword-mode))
(eval-after-load "visual-line-mode" '(diminish 'visual-line-mode))

Mover el cursos de manera inteligente al inicio de la linea

He tenido el problema, desde que no uso auto-indent-mode, que al presionar M-a el cursor va a la columna 0 en lugar de posicionarse en el primer carácter no-blanco de la linea, que es un comportamiento deseado cuando se esta programando. En Stackoverflow hay una respuesta para el problema :)

(defun smart-beginning-of-line ()
  "Move point to first non-whitespace character or beginning-of-line.

Move point to the first non-whitespace character on this line.
If point was already at that position, move point to beginning of line."
  (interactive)
  (let ((oldpos (point)))
    (back-to-indentation)
    (and (= oldpos (point))
       (beginning-of-line))))

(global-set-key [home] 'smart-beginning-of-line)
(global-set-key (kbd "C-a") 'smart-beginning-of-line)

EN-ESPERA Modificación de los caracteres en el mode-line

  • State “EN-ESPERA” from “” [2015-02-20 vie 18:24]
    Tengo que liarme con `powerline’ primero para poder tocar siquiera la variable `mode-line-format’

Los caracteres en el mode-line de Emacs pueden ser modificados ¿No es genial? (según The Cliffs of Inanity, también lunarsite. referencias sobre mode-line-format en la referencia de Elisp)

;; Si usas `powerline', editar la variable mode-line-format es algo complicado,
;; pero no imposible

Asociación de archivos a modos mayores

Aquí se definen código para definir la asociación de algunas extensiones de archivo con algunos modos mayores

(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.gohtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.gtl\\'" . web-mode))

Customize

El archivo customize sera éste. Cualquier modificación de Emacs que se haga a través de customize ira en éste archivo:

(setf custom-file (expand-file-name "custom.el" user-emacs-directory))

Me da la impresión que estas modificaciones pueden ser sobre-escritas si se cargan al puro inicio. De ahí que sean movidas a la ultima parte de la configuración.

Y cargamos el archivo, ¡No lo olvide!.

(load custom-file)

Otras configuraciones

Existen ciertos cambios que no tienen cabida en otra parte, y ciertamente colocarlos debajo de Modos de Emacs no es una opción… porque lo veo como algo desordenado.

Desata algunas teclas rápidas y sus respectivos comandos

C-z es una combinación de teclas que no me sirven para algo, así que lo desato de su comando suspend-frame para darle un mejor uso. También M-z puede tener un mejor uso que ejecutar el comando de borrado zap-to-char

(global-unset-key (kbd "C-z"))
(global-unset-key (kbd "M-z"))

Modos de Emacs

La configuración especifica a cada modo mayor, menor, o paquete con funcionalidades. Dividió por secciones.

Después de que Emacs cargue la configuración por completo

modos que se activan luego de que emacs carga

(add-hook (quote after-init-hook)
          (lambda ()
       (helm-mode 1)
       (helm-descbinds-mode)
       (projectile-global-mode)
       (helm-projectile-on)
       (global-flycheck-mode)
       (global-pretty-mode t)
       (global-company-mode)
       (global-fixmee-mode 1)
       (global-undo-tree-mode 1)
       (unkillable-scratch 1)
       ))

(defalias 'redo 'undo-tree-redo)

(global-set-key (kbd "C-ç") 'undo)
(global-set-key (kbd "M-ç") 'redo)
(global-set-key (kbd "M-¡") 'text-scale-increase)
(global-set-key (kbd "M-'") 'text-scale-decrease)
(define-key global-map (kbd "M-o") 'other-window)
(define-key global-map (kbd "M-p") 'ace-window)
;; find-file y switch-to-buffer personalizados
(define-key global-map (kbd "C-x C-f") 'shackra:find-file)
(define-key global-map (kbd "C-x b") 'shackra:switch-buffer)
(setf aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
;; salta a la nueva ventana creada despues de dividir la actual
(global-set-key "\C-x2" (lambda () (interactive)(split-window-vertically) (other-window 1)))
(global-set-key "\C-x3" (lambda () (interactive)(split-window-horizontally) (other-window 1)))

Org-mode

  • State “TERMINADO” from “POR-HACER” [2014-10-15 mié 17:38]
  • State “POR-HACER” from “EN-REVISIÓN” [2014-10-11 sáb 00:16]
    probar las capturas de anotaciones implementadas. Pasar a los nuevos archivos las tareas en otros archivos.
  • State “EN-REVISIÓN” from “EN-REVISIÓN” [2014-10-10 vie 00:19]
    El error parece provenir de la sentencia org-blank-before-new-entry t en la configuración. Todo lo demás permanece sin comentar y aun así org-capture funciona como debe.
  • State “EN-REVISIÓN” from “” [2014-10-08 mié 20:19]
    No puedo hacer uso de la función para capturar anotaciones, en el stack exchange de Emacs estoy tratando de conseguir ayuda para este problema

¡Organiza tu vida usando Emacs!

Se cambio la combinación de teclas para er/expand-region a C-¡ debido a que org-mode usa la combinación C-’ para otra cosa.

(setf org-footnote-auto-adjust t
      org-html-htmlize-output-type 'css
      org-html-htmlize-font-prefix "org-"
      org-habit-graph-column 55
      org-directory (expand-file-name "~/org")
      org-archive-location (concat org-directory "/archivado.org::* Entradas viejas y archivadas")
      org-special-ctrl-k t
      org-ctrl-k-protect-subtree t ;; al usar C-k, evitamos perder todo el subarbol
      org-catch-invisible-edits 'show
      org-return-follow-link t
      ;;org-blank-before-new-entry t
      org-startup-indented t
      org-startup-folded nil
      org-imenu-depth 5
      org-log-done 'time
      org-clock-persist 'history
      org-default-notes-file (concat org-directory "/diario.org")
      
      org-agenda-files (list (concat org-directory "/cosasporhacer.org")
                             (concat org-directory "/agenda.org"))

      org-mobile-directory "~/orgmobile/"
      
      org-capture-templates `(("p" "Cosas por hacer" entry (file+headline ,(concat org-directory "/cosasporhacer.org") "Tareas")
                               "* POR-HACER %^{breve descripcion}\n%?\nAgregado: %U\nEn: %a" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("d" "Escribir una nota en el diario" plain (file org-default-notes-file)
                               "%?\n\nEscrito el: %U\nEn: %a" :empty-lines 1)
                              ("x" "Proyectos de clientes en PeoplePerHour" entry (file+headline ,(concat org-directory "/cosasporhacer.org") "Proyectos en PeoplePerHour") 
                               "* POR-HACER %^{Titulo del proyecto}\n%^{cliente}p\n%^{ID}p\nDescripción: %?" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("c" "Calendario" entry (file+headline ,(concat org-directory "/cosasporhacer.org") "Calendario")
                               "* %^{Nombre del evento}\n SCHEDULED: %:date" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("a" "Cumpleaños y aniversarios" entry (file+headline ,(concat org-directory "/agenda.org") "Cumpleaños y aniversarios")
                               "* %^{Nombre del cumpleañero o aniversario}\n SCHEDULED: %:date\n %?" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("g" "Algún día/Tal vez" entry (file+headline ,(concat org-directory "/quizas.org") "En 'veremos'")
                               "* %^{breve descripcion}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("l" "Algún día/Tal vez (Libros)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Libros por leer")
                               "* Leer %^{titulo del libro} por %^{autor o autores}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("v" "Algún día/Tal vez (Peliculas)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Películas por ver")
                               "* Ver la pelicula %^{titulo de la pelicula}\n %?\n Added: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("m" "Algún día/Tal vez (Música)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Música por escuchar")
                               "* Escuchar cierta(s) cancion(es) de %^{artista}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("b" "Algún día/Tal vez (Blogs)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Blogs por leer")
                               "* Leer [[%:url][%^{titulo de la entrada de blog}]] por %^{autor}\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("z" "Algún día/Tal vez (Por hacer)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Cosas por hacer")
                               "* %^{breve descripcion de la tarea}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("w" "Algún día/Tal vez (Aprender)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Cosas por aprender")
                               "* %^{breve descripcion}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              ("n" "Algún día/Tal vez (Nuevo proyecto)" entry (file+olp ,(concat org-directory "/quizas.org") "En 'veremos'" "Nuevos proyectos")
                               "* %^{breve descripcion}\n %?\nAdded: %U" :clock-in nil :clock-keep nil :clock-resume nil)
                              )
      
      org-todo-keywords '((sequence "POR-HACER(p)" "EN-PROGRESO(g)" "EN-ESPERA(e@/!)" "EN-REVISIÓN(r@/!)" "|" "CANCELADO(c@)" "TERMINADO(t!)"))
      org-todo-keyword-faces '(
                               ("POR-HACER" . (:foreground "black" :background "#ff4500" :weight bold))
                               ("EN-PROGRESO" . (:foreground "black" :background "#ffa500" :weight bold))
                               ("EN-ESPERA" . (:foreground "black" :background "#0000ff" :weight bold))
                               ("EN-REVISIÓN" . (:foreground "black" :background "#ffff00" :weight bold))
                               ("TERMINADO" . (:foreground "black" :background "#32cd32" :weight bold))
                               ("CANCELADO" . (:foreground "black" :background "#8b0000" :weight bold))
                               )
      )

(global-set-key (kbd "C-c l") 'org-store-link)
(global-set-key (kbd "C-c a") 'org-agenda)
(define-key global-map (kbd "C-c c") 'org-capture)
(define-key org-mode-map (kbd "C-¡") 'er/expand-region)
(define-key org-mode-map (kbd "C-c k") #'endless/insert-key)

(org-clock-persistence-insinuate)

;; sacado de http://emacs.stackexchange.com/a/2103/690
(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_EXAMPLE" . "#\\+END_EXAMPLE"))

(add-hook 'org-mode-hook (lambda ()
                           (progn 
                             (auto-fill-mode -1)
                             (visual-fill-column-mode))))

Org-page

Genera un blog estático con org-page. la variable op/category-config-alist fue redefinida (o al menos eso creo) porque de verdad quiero castellanizar los enlaces y sus títulos en el blog.

(setf op/repository-directory "/home/jorge/Documentos/elblog.deshackra.com/"
      op/repository-org-branch "master"
      op/repository-html-branch nil
      op/site-domain "http://elblog.deshackra.com"
      op/site-main-title "El blog de Shackra"
      op/site-sub-title "No seas tan abierto de mente o tu cerebro se caerá"
      op/personal-github-link "https://github.com/shackra"
      op/theme-root-directory (expand-file-name "org-page-themes" user-emacs-directory)
      op/theme 'shackra
      org-html-htmlize-output-type nil
)

(eval-after-load 'ox
  '(progn
     (add-to-list 'org-export-filter-src-block-functions
                  'org2html-wrap-blocks-in-code)
     ))

text-mode

Esta configuración afecta a todos los modos texto en los buffers.

(add-hook 'text-mode-hook
           (lambda ()
             ;;(turn-on-auto-fill)
             (turn-on-visual-line-mode)
             (flyspell-mode)
             (set (make-local-variable 'fill-column) 110)
             ))

HELM

Es un paquete que esta en su propia liga. Éste paquete te ayudara a aumentar tu productividad, reducir tu calvicie y hará que tu ex-novia sexy que te dejo hace 20 años vuelva muerta de amor por vos ;)

Acá se definen primero los keybindings para Helm, todo en un solo sitio.

(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))
(define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) ; rebind tab to do persistent action
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action) ; make TAB works in terminal
(define-key helm-map (kbd "C-z")  'helm-select-action) ; list actions using C-z
(global-set-key (kbd "C-x f") 'helm-recentf)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(global-set-key (kbd "C-c i") 'helm-imenu)
(global-set-key (kbd "C-x C-f") 'helm-find-files)
(global-set-key (kbd "C-x b") 'helm-mini)
(global-set-key (kbd "C-c h o") 'helm-occur)
(global-set-key (kbd "C-h SPC") 'helm-all-mark-rings)
(global-set-key (kbd "C-c h x") 'helm-register)
(global-set-key (kbd "C-c h g") 'helm-google-suggest)
(define-key minibuffer-local-map (kbd "C-c C-l") 'helm-minibuffer-history)
(define-key shell-mode-map (kbd "C-c C-l") 'helm-comint-input-ring)
(define-key helm-grep-mode-map (kbd "<return>")  'helm-grep-mode-jump-other-window)
(define-key helm-grep-mode-map (kbd "n")  'helm-grep-mode-jump-other-window-forward)
(define-key helm-grep-mode-map (kbd "p")  'helm-grep-mode-jump-other-window-backward)

Y acá el resto de la configuración de Helm

(when (executable-find "curl")
  (setf helm-google-suggest-use-curl-p t))

(setf
 helm-split-window-in-side-p t          ; open helm buffer inside current window, not
                                        ; occupy whole other window
 helm-move-to-line-cycle-in-source t    ; move to end or beginning of source when
                                        ; reaching top or bottom of source.
 helm-ff-search-library-in-sexp t       ; search for library in `require' and
                                        ; `declare-function' sexp.
 helm-scroll-amount 8                   ; scroll 8 lines other window using M-<next>/M-<prior>
 helm-ff-file-name-history-use-recentf t
 helm-locate-command "locate %s -e -A --regex %s"
 helm-locate-fuzzy-match t
 helm-M-x-fuzzy-match t
 helm-buffers-fuzzy-matching t
 helm-recentf-fuzzy-match    t
 helm-boring-buffer-regexp-list '("\\` "
                                  "\\*helm"
                                  "\\*helm-mode"
                                  "\\*Echo Area"
                                  "\\*Minibuf"
                                  "\\*monky-cmd-process\\*"
                                  "\\*epc con"
                                  "\\*Compile-Log\\*"
                                  "\\*monky-process\\*"
                                  "\\*CEDET CScope\\*"
                                  "\\*Messages\\*"
                                  "\\*Flycheck error"
                                  "\\*Elpy"
                                  "\\*elpy-rpc"
                                  "\\*.+(.+)"
                                  "\\*fsm-debug\\*"
                                  "elpa/.+"
                                  "tramp/.+"
                                  "\\*Gofmt Errors\\*")
 
 helm-boring-file-regexp-list (quote
                               ("\\.git$" "\\.hg$" "\\.svn$" "\\.CVS$"
                                "\\._darcs$" "\\.la$" "\\.o$" "~$"
                                "\\.pyc$" "\\.elc$" "TAGS" "\#*\#"
                                "\\.exe$" "\\.jar$" "\\.img$" "\\.iso$"
                                "\\.xlsx$" "\\.epub$" "\\.docx$"))
 helm-ff-skip-boring-buffers t
 helm-truncate-lines t
 helm-projectile-sources-list '(helm-source-projectile-files-list))

;; Instalar ack o ack-grep
(when (executable-find "ack")
  (setq helm-grep-default-command "ack -Hn --no-group --no-color %e %p %f"
        helm-grep-default-recurse-command "ack -H --no-group --no-color %e %p %f"))

;; en caso de que ack-grep sea el programa disponible
(when (executable-find "ack-grep")
  (setq helm-grep-default-command "ack-grep -Hn --no-group --no-color %e %p %f"
        helm-grep-default-recurse-command "ack-grep -H --no-group --no-color %e %p %f"))
(add-to-list 'helm-sources-using-default-as-input 'helm-source-man-pages)
(add-hook 'helm-goto-line-before-hook 'helm-save-current-pos-to-mark-ring)

Projectile

Es un paquete que nos permite el manejo de archivos en proyectos. Un proyecto, por definición, puede ser cualquier repositorio de código fuente de software, como mercurial, git, etc. También es posible definir un proyecto en una carpeta dejando caer en él un archivo .projectile, dentro de este archivo se puede definir qué archivos/carpetas ignorar y cuales no. Para más información ver la pagina del proyecto.

(setf
 projectile-completion-system 'helm
 projectile-file-exists-remote-cache-expire (* 10 60)
 projectile-globally-ignored-files (quote ("TAGS" "\#*\#" "*~" "*.la"
                                     "*.o" "~" "*.pyc" "*.elc" "*.exe"
                                     "*.zip" "*.tar.*" "*.rar" "*.7z"))
 projectile-switch-project-action  'helm-projectile-find-file
 )

Multi-term

Ofrece un excelente emulador de terminal dentro de Emacs

(setf multi-term-buffer-name "shell-"
      multi-term-program "/bin/bash"
      term-bind-key-alist (list (cons "C-c C-c" 'term-interrupt-subjob)
                                (cons "C-p" 'previous-line)
                                (cons "C-n" 'next-line)
                                (cons "M-f" 'term-send-forward-word)
                                (cons "M-b" 'term-send-backward-word)
                                (cons "C-c C-j" 'term-line-mode)
                                (cons "C-c C-k" 'term-char-mode)
                                (cons "M-DEL" 'term-send-backward-kill-word)
                                (cons "M-d" 'term-send-forward-kill-word)
                                (cons "<C-left>" 'term-send-backward-word)
                                (cons "<C-right>" 'term-send-forward-word)
                                (cons "C-r" 'term-send-reverse-search-history)
                                (cons "M-p" 'term-send-raw-meta)
                                (cons "M-y" 'term-send-raw-meta)
                                (cons "C-y" 'term-send-raw)))
(add-hook 'term-mode-hook
          (lambda ()
            (yas-minor-mode -1)
            )
          )

(global-set-key [f1] 'multi-term)
(global-set-key [C-next] 'multi-term-next)
(global-set-key [C-prior] 'multi-term-prev)

company

El paquete da funcionalidades de auto completado. Esta opcion es cada día más popular como remplazo a auto-complete.

(setf company-idle-delay 0.3
      company-tooltip-limit 20
      company-minimum-prefix-length 2
      company-echo-delay 0
      company-auto-complete nil)

(add-to-list 'company-backends 'company-dabbrev t)
(add-to-list 'company-backends 'company-ispell t)
(add-to-list 'company-backends 'company-files t)
(add-to-list 'company-backends 'company-yasnippet t)

Python

Configuraciones para mi modo estrella: Python-mode! Estoy omitiendo usar auto-indent-mode debido a un fallo en el modo Python. Por lo tanto, estoy reuniendo la tecla RET con la función newline-and-indent que funciona de lo más bien.

(elpy-enable)
(setf python-indent-guess-indent-offset nil
      python-indent 4
      python-indent-offset 4)
(add-hook 'python-mode-hook
          (lambda ()
            ;; esto puede que no funcione en emacs 24.3 y anteriores
            (electric-indent-local-mode -1)
            (nlinum-mode)
            (hlinum-activate)))
(define-key python-mode-map (kbd "C-M-,") 'comment-dwim-line)
(define-key python-mode-map (kbd "C-c <right>") 'python-indent-shift-right)
(define-key python-mode-map (kbd "C-c <left>") 'python-indent-shift-left)
(define-key python-mode-map (kbd "C-c ,") 'iedit-mode-toggle-on-function)

iedit-mode

iedit-mode es un modo que permite editar un termino repetido en varios lugares a la vez en el buffer actual, es como multiple-cursors, pero sin la tener que marcar un area y luego llamar al modo mayor. En Python se llama a iedit-mode-toggle-on-function con @@html:<kbd>C</kbd>@@@@html:<kbd>c</kbd>@@ @@html:<kbd>,</kbd>@@.

Cuando iedit-mode esta activo, presionar la tecla @@html:<kbd>RET</kbd>@@ hará que se desactive, al igual que sucede con multiple-cursors.

(define-key iedit-mode-keymap (kbd "RET") 'iedit-mode)

discover-my-major

Éste paquete nos muestra las combinaciones de teclas posibles para el modo mayor en el que estamos actualmente, todo lo que hay que hacer es recordar una combinación especifica de teclas.

Esta combinación por defecto es C-h C-m ;)

(global-set-key (kbd "C-h C-m") 'discover-my-major)

Expand-region

Provee una manera fácil de hacer selección de elementos en el buffer con presionar solo una tecla. Puede ver éste paquete en acción en este episodio de Emacs Rocks.

(global-set-key (kbd "C-'") 'er/expand-region)

multiple-cursos

Marca varias partes del buffer dependiendo de la selección que hagas.

(define-key global-map (kbd "C-+") 'mc/mark-next-like-this)
(define-key global-map (kbd "M-+") 'mc/mark-previous-like-this)
(define-key global-map (kbd "C-M-+") 'mc/mark-all-like-this)
;; Para diseñadores web, marca la etiqueta de apertura y cierre
;;(define-key sgml-mode-map (kbd "C-'") 'mc/mark-sgml-tag-pair) ;;Symbol's value as variable is void: sgml-mode-map

este paquete puedes tener configuraciones de teclas muy variadas, lo mejor es que visites la pagina del proyecto en Github para más información. Las teclas usadas reflejan la reducida cantidad que existen en mi laptop.

flycheck-mode

revisión-al-vuelo de la sintaxis mientras editas código. Hace una selección automática del mejor revisor de sintaxis que dispongas.

Tiene soporte para muchos lenguajes. Lo recomiendo por encima de flymake.

(setf
 flycheck-disabled-checkers '(emacs-lisp-checkdoc) ;; deshabilita el majadero revisor de documentación
 flycheck-indication-mode 'right-fringe
 )

web-mode

Un modo mayor autónomo que permite la edición de plantillas web: documentos HTML con partes embebidas (CSS/Javascript) y bloques (del lado de cliente/servidor)

(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[gj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)) ;; para plantillas de Django.
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) ;; para editar archivos HTML

(add-hook 'web-mode-hook (lambda ()
                           (progn
                             (auto-fill-mode -1)
                             (electric-indent-local-mode t)
                             ;; (progn
                             ;;   ;; según https://github.com/capitaomorte/yasnippet/issues/396#issuecomment-46340904
                             ;;   ;; hace yasnippet funcionar con web-mode
                             ;;   (yas-activate-extra-mode 'html-mode)
                             ;;   (yas-minor-mode-on))
                             (emmet-mode)
                             )))

mu4e

Un versátil cliente de correo electrónico. Éste paquete se carga de manera condicional si esta instalado en el sistema del usuario. Desgraciadamente no puedes instalarlo desde Melpa o algún otro repositorio de paquetes de Emacs.

Correos electrónicos y otros datos son traídos de un archivo secreto ;)

(defun shackra/render-html-message ()
  "Render a HTML message with eww, see http://emacs.stackexchange.com/a/3052/690"
  (let ((dom (libxml-parse-html-region (point-min) (point-max))))
    (erase-buffer)
    (shr-insert-document dom)
    (goto-char (point-min))))

Para saber como configurar mu4e para escribir correos con diferentes cuentas de correo, puedes mirar la documentación es aconsejable que esa configuración viva en el archivo secreto…

(when (file-exists-p "/usr/share/emacs/site-lisp/mu4e/")
  (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e/")
  (autoload 'mu4e "mu4e" "Mail client based on mu (maildir-utils)." t)

  (require 'mu4e-contrib)
  (require 'org-mu4e)
  (setf mu4e-view-show-images t)
  (global-set-key (kbd "<f7>") 'mu4e)
  (when (fboundp 'imagemagick-register-types)
    (imagemagick-register-types))

  (setf
   ;; html2text es un paquete que debe estar instalado en tu sistema
   mu4e-confirm-quit nil
   mu4e-html2text-command 'mu4e-shr2text
   mu4e-get-mail-command "offlineimap"
   mu4e-maildir "/home/jorge/correo"
   mu4e-update-interval nil
   mu4e-auto-retrieve-keys t
   mu4e-headers-leave-behavior 'apply
   mu4e-headers-visible-lines 7
   mu4e-hide-index-messages t
   message-kill-buffer-on-exit t
   mu4e-attachment-dir  "~/Descargas"
   mu4e-maildir       "~/correo" ;; top-level Maildir
   mu4e-sent-folder   "/principal/INBOX/Sent" ;; folder for sent messages
   mu4e-drafts-folder "/principal/INBOX/Drafts" ;; unfinished messages
   mu4e-trash-folder  "/principal/INBOX/Trash"  ;; trashed messages
   mu4e-refile-folder "/principal/INBOX/Archives" ;; Mensajes salvados
   smtpmail-stream-type  'ssl
   smtpmail-smtp-service 465
   message-send-mail-function 'smtpmail-send-it
   )
  (if (daemonp)
      (ignore-errors
        (load (expand-file-name "mu4e-conf.secret.gpg" user-emacs-directory) t)))

  ;; funcion para seleccionar la cuenta con la que se va a responder a un email
  (defun my-mu4e-set-account ()
    "Set the account for composing a message."
    (let* ((account
            (if mu4e-compose-parent-message
                (let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir)))
                  (string-match "/\\(.*?\\)/" maildir)
                  (match-string 1 maildir))
              (completing-read (format "Componer correo con la cuenta: (%s) "
                                       (mapconcat #'(lambda (var) (car var))
                                                  my-mu4e-account-alist "/"))
                               (mapcar #'(lambda (var) (car var)) my-mu4e-account-alist)
                               nil t nil nil (caar my-mu4e-account-alist))))
           (account-vars (cdr (assoc account my-mu4e-account-alist))))
      (if account-vars
          (mapc #'(lambda (var)
                    (set (car var) (cadr var)))
                account-vars)
        (error "Cuenta de correo no encontrada"))))

  ;; y enganchamos la funcion
  (add-hook 'mu4e-compose-pre-hook 'my-mu4e-set-account)
  )

dired y dired+

Extiende funcionalidades de dired. Se agrega una función personalizada que mata el buffer al presionar q, porque verdaderamente no quiero saber nada más de esa carpeta en caso de desear salir de ella.

(defun dired-quit-window-kill-buffer ()
  "Además de matar el buffer, cierra la ventana"
  (interactive)
  (let ((win-curr (selected-window))
        (win-other (next-window)))
    (select-window win-other)
    (kill-this-buffer)
    (select-window win-curr)))

(setf dired-dwim-target t)
(define-key ctl-x-map   "d" 'dired)
(define-key ctl-x-4-map "d" 'diredp-dired-for-files-other-window)
(define-key dired-mode-map (kbd ".") 'dired-up-directory)
(define-key dired-mode-map (kbd "q") 'dired-quit-window-kill-buffer)

ace-jump

hace que el cursor se mueva por todo el buffer con presionar pocas teclas.

(global-set-key (kbd "C-z") 'ace-jump-word-mode)
(global-set-key (kbd "C-S-z") 'ace-jump-line-mode)
(global-set-key (kbd "C-M-z") 'ace-jump-char-mode)
(global-set-key (kbd "M-z") 'ace-jump-mode-pop-mark)
(setf ace-jump-mode-case-fold t)

magit

Git en Emacs.

A decir verdad, amo a Mercurial y odio a Git.

(define-key global-map [C-f12] 'magit-status)

monky

Mercurial en Emacs

Amo Mercurial ;)

(define-key global-map [f12] 'monky-status)
(setf monky-process-type 'cmdserver)

Smart modeline

el modeline, pero más inteligente.

(sml/setup)
(sml/apply-theme 'respectful)

(add-to-list 'sml/replacer-regexp-list '("^~/coders/" ":Código:") t)
(add-to-list 'sml/replacer-regexp-list '("^:Código:PPH/clientes/" ":PPH:") t)

Visual-regexp y Visual-regexp-steroids

expresiones regulares con algo más moderno que lo ofrecido por Emacs:

(define-key global-map (kbd "C-c r") 'vr/replace)
(define-key global-map (kbd "C-c q") 'vr/query-replace)
(define-key global-map (kbd "C-c m") 'vr/mc-mark)
(define-key esc-map (kbd "C-r") 'vr/isearch-backward) ;; C-M-r
(define-key esc-map (kbd "C-s") 'vr/isearch-forward) ;; C-M-s

Para todos los modos mayores de programación

En lo personal, me gustaría que al escribir los comentarios en mi código fuente, las lineas se rompan al llegar a la columna 79.

(add-hook 'prog-mode-hook
          (lambda ()
            (set (make-local-variable 'fill-column) 79)
            (set (make-local-variable 'comment-auto-fill-only-comments) t)
            (auto-fill-mode t)
            (highlight-numbers-mode)
            (hes-mode)
            ;;(highlight-blocks-mode)
            (electric-pair-mode)
            (rainbow-turn-on)
            (flyspell-prog-mode)))

;; redefinimos la tecla RET para que inserte un salto de linea y la
;; idente de manera adecuada.
(define-key prog-mode-map (kbd "RET") 'newline-and-indent)

golang

configuración para golang en emacs.

(add-hook 'go-mode-hook (lambda ()
                          (local-set-key (kbd "C-c C-r") 'go-remove-unused-imports)
                          (local-set-key (kbd "C-c i") 'go-goto-imports)
                          (local-set-key (kbd "M-.") 'godef-jump)
                          (set (make-local-variable 'company-backends) '(company-go))
                          (go-eldoc-setup)
                          (nlinum-mode)
))

rustlang

configuración para rustlang en Emacs. Yo aun no olvido lo hipócrita que es Mozilla y “su web abierta” por lo que le hicieron (o no hicieron, si quiere) con Brendan Eich. LAS PERSONAS TIENEN EL DERECHO A FINANCIAR CON SU DINERO AQUELLAS CAMPAÑAS EN FAVOR DEL MATRIMONIO Y LA FAMILIA, NO HAY RAZÓN PARA QUE SEAN PERSEGUIDAS Y PIERDAN SUS TRABAJOS PORQUE LOS FASCISTAS DEL MOVIMIENTO LGTB QUIEREN QUE QUIENES PIENSAN DISTINTOS DE ELLOS SE MANTENGAN IGNORANTES SOBRE QUÉ ES EL MATRIMONIO EN REALIDAD Y CUAL ES SU FUNDAMENTO. ¡Mozilla, hipócrita, cuanta tolerancia y respeto hacía los demás!.

;;nada por agregar, aun...

C++

configuración para habilitar auto-completado en Emacs para la programación en el lenguaje C++

(require 'cmake-project)

(defun maybe-cmake-project-hook ()
  (if (file-exists-p "CMakeLists.txt") (cmake-project-mode)))

(defun my-irony-mode-hook ()
  (define-key irony-mode-map [remap completion-at-point]
    'irony-completion-at-point-async)
  (define-key irony-mode-map [remap complete-symbol]
    'irony-completion-at-point-async))

(add-hook 'c++-mode-hook
          (lambda ()
            (irony-mode)
            (set (make-local-variable 'company-backends) '(company-c-headers 
                                                           company-irony
                                                           company-yasnippet
                                                           ))
            (maybe-cmake-project-hook)
))

(add-hook 'irony-mode-hook 
          (lambda ()
            (company-irony-setup-begin-commands)
            (my-irony-mode-hook)
))

CMake

configuración de CMake para Emacs

(require 'cmake-mode)

(setq auto-mode-alist
      (append
       '(("CMakeLists\\.txt\\'" . cmake-mode))
       '(("\\.cmake\\'" . cmake-mode))
       auto-mode-alist))

(add-hook 'cmake-mode-hook 
          (lambda ()
            (set (make-local-variable 'company-backends) '(company-cmake
                                                           company-yasnippet))
            ))

Muse

Configuración para Muse, un modo mayor en Emacs para la escritura y publicación de libros a varios formatos.

(add-hook 'muse-mode-hook (lambda ()
                            (auto-fill-mode -1)
                            (visual-line-mode)
                            )
          )

gancho para antes de guardar el archivo

puede que gustemos de hacer algo con el archivo antes de guardarlo. Acá se enganchan un par de funciones.

(add-hook 'before-save-hook 'py-autopep8-before-save)
(add-hook 'before-save-hook 'web-beautify-html-buffer t t)
(add-hook 'before-save-hook 'gofmt-before-save)

EN-REVISIÓN langtool

  • State “EN REVISIÓN” from “” [2014-10-27 lun 15:26]
    al momento de usar los comandos, da errores

Language Tool es una herramienta de software libre para revisión gramatical, ortográfica y de estilo.

(require 'langtool)
(setf langtool-language-tool-jar "/usr/share/java/languagetool/languagetool-commandline.jar"
      langtool-mother-tongue "es")

(global-set-key (kbd "C-x 4 w") 'langtool-check)
(global-set-key (kbd "C-x 4 W") 'langtool-check-done)
(global-set-key (kbd "C-x 4 l") 'langtool-switch-default-language)
(global-set-key (kbd "C-x 4 4") 'langtool-show-message-at-point)
(global-set-key (kbd "C-x 4 c") 'langtool-correct-buffer)

Jabber

  • State “TERMINADO” from “EN-REVISIÓN” [2015-01-14 mié 02:20]
  • State “EN-REVISIÓN” from “TERMINADO” [2014-11-03 lun 14:47]
    las notificaciones no pueden ser enviadas por dbus o libnotify
  • State “TERMINADO” from “EN REVISIÓN” [2014-11-03 lun 13:47]
  • State “EN-REVISIÓN” from “” [2014-10-27 lun 15:27]
    iniciar sesión únicamente si Emacs se inicia como demonio

Chat de jabber desde Emacs!!

(setf
 jabber-history-enabled t
 jabber-use-global-history nil
 jabber-backlog-number 40
 jabber-backlog-days 30
 jabber-alert-presence-message-function (lambda (who oldstatus newstatus statusnext) nil)
 jabber-invalid-certificate-servers '("chat.deshackra.com")
 jabber-default-status "«Faith is always at a disadvantage; it is a perpetually defeated thing which survives all of its conquerors» ~G. K. Chesterton."
)

(defun my-jabber-chat-delete-or-bury ()
  (interactive)
  (if (eq 'jabber-chat-mode major-mode)
      (condition-case e 
          (delete-frame)
        (error 
         (if (string= "Attempt to delete the sole visible or iconified frame" 
                      (cadr e))
             (bury-buffer))))))

(if (daemonp)
    ;; nos conecta a todas las cuentas jabber!
    (progn
      (ignore-errors
        (load-file (expand-file-name "jabber.secret.gpg" user-emacs-directory)))
      (ignore-errors 
        (jabber-connect-all))))

(add-hook 'jabber-chat-mode-hook (lambda ()
                                   (turn-off-auto-fill)
                                   (turn-on-visual-line-mode)
                                   (flyspell-mode)))

GNU TLS

Una implementación libre de los protocolos SSL, TLS y DTLS. Interado con Emacs

(setf gnutls-min-prime-bits 1024)

EN-REVISIÓN eyebrowse

  • State “EN-REVISIÓN” from “” [2014-12-15 lun 00:34]
    Aun no sé si en el estado actual funciona como deberia

permite cambiar entre disposiciones de ventanas en emacs

(define-key eyebrowse-mode-map (kbd "C-c C-w z") 'eyebrowse-prev-window-config)
(define-key eyebrowse-mode-map (kbd "C-c C-w x") 'eyebrowse-next-window-config)

notify.el

  • State “TERMINADO” from “EN-REVISIÓN” [2015-01-14 mié 02:20]
  • State “EN-REVISIÓN” from “” [2014-11-03 lun 14:13]
    el método definido no es multiplataforma

Permite a emacs enviar notificaciones por DBus o diferentes medios

(setf notify-method 'notify-via-libnotify)

MediaWiki

Acceso para Emacs a sitios que usan Wikimedia

(if (daemonp)
    (ignore-errors
      (load-file (expand-file-name "mediawiki.secret.gpg" user-emacs-directory))))
(define-key mediawiki-mode-map (kbd "C-c o") 'mediawiki-browse)

adoc-mode

Un modo mayor de Emacs para editar documentos AsciiDoc

(add-to-list 'auto-mode-alist (cons "\\.txt\\'" 'adoc-mode))

skewer-mode

(add-hook 'js2-mode-hook 'skewer-mode)
(add-hook 'css-mode-hook 'skewer-css-mode)
(add-hook 'html-mode-hook 'skewer-html-mode)
(add-hook 'web-mode-hook 'skewer-html-mode)

TRAMP

Un paquete para la edición de archivos remotos

(setf tramp-default-method "ssh")

(add-to-list 'tramp-default-method-alist '("\\`localhost\\'" "\\`root\\'" "su"))

js2-mode

Un modo mayor para editar JavaScript

(add-to-list 'auto-mode-alist '("\\.js\\'" .  js2-mode))

find-file

(add-hook 'find-file-hook 'find-file-sudo)

httpd-mode

Servidor web dentro de Emacs

(setf httpd-port 9300)

recentf

Mantiene una lista de archivos visitados recientemente

(add-to-list 'recentf-exclude ".git/")
(add-to-list 'recentf-exclude ".hg/")
(add-to-list 'recentf-exclude "elpa/")
(add-to-list 'recentf-exclude "\\.emacs.d/org-clock-save.el\\'")
(add-to-list 'recentf-exclude "INBOX/")