Emacs: Mi fichero de configuración 2021
2021-07-05
Índice
- init.el
- config-org
- Información del usuario
- Fuentes de Paquetes
- Puesta en marcha
- Ficheros a usar para la autenticación
- Mis valores por defecto
- Recogida de basura
- ibuffer
- Configuraciones estóticas
- Actualiza automáticamente paquetes
- Ortografía
- Hacer/deshacer
- Espacios en Blanco
- Paróntesis
- Autorevert
- Usando el propio navegador de Emacs por defecto
- Emojify
- Añadiendo números de líneas
- Archivos recientes
- Buffer
- Ditaa
- Complementos
- eshell
- Org
- Programación-Web
Al igual que hice con las extensiones que utilizo en Gnome Shell, voy a repasar mi actual fichero de configuración que utilizo en Emacs en este año 2021.
Como suele ser habitual cuando empiezas en Emacs, cuando necesitamos una determinada características recurrimos a copiar trozos de otros ficheros de configuración de otros usuarios, buscas lo que necesitas, copias y pegas.
Normalmente esto suele funcionar pero presenta un problema, y es que sabes que funciona pero no sabes porquó funciona y además muchas veces, por lo menos en mi caso, terminas copiando funciones o características que no necesitas.
Así que este es un fichero de configuración sencillo, ya que no utilizo Emacs para programar, simplemente está pensado para llevar mi agenda, diario, listas de tareas (TODO) y tambión para hacer este blog mediante org-static-blog, todo ello gracias a org-mode, por que no esperes encontrar un gran fichero de configuración, además mis conocimientos sobre Emacs y org-mode se limitan a lo que he comentado.
Despuós de soltarte todo el rollo, veamos mi fichero de configuración, bueno realmente son dos, config.org e init.el
init.el
Este fichero básicamente se encarga de instalar el paquete use-package
, necesario para poder instalar los paquetes que vamos a configurar en el archivo config.org, leer el archivo ~/.emacs.d/config.org y gracias a la magia de org-mode, cargar los bloques de código lisp, que contienen las variables de configuración y los paquetes a instalar para Emacs.
(require 'package)
(setq package-enable-at-startup nil)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
(package-initialize)
;; Bootstrap `use-package'
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(org-babel-load-file (expand-file-name "~/.emacs.d/config.org"))
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(initial-frame-alist '((fullscreen . maximized)))
'(package-selected-packages
'(aggressive-indent flyspell-correct-ivy auto-package-update nimbus-theme use-package)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
config-org
En este fichero vamos a configurar las variables que nos permitirán modificar el entono de Emacs e instalar los paquetes que vamos a utilizar.
* Esta configuración pasa por ser una configuración simple, que se adapta a mi día a día, es decir, TODOS, notas, diario, organización de agenda y blog
Otras configuraciones las he sacado de los respectivos sitios de los paquetes que configuro.
Información del usuario
;;
;; with this variable set the name and e-mail of user
;;
(setq user-full-name "Carlos M."
user-mail-address "hefistion.arroba.mail.com"
calendar-latitude 40.2375052
calendar-longitude -3.6967718
calendar-location-name "Pinto, Madrid")
Fuentes de Paquetes
Las fuentes de paquetes que vamos a necesitar para las instalaciones.
;;;
;;;;; install the melpa repository
;;
(setq package-archives (append package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/"))))
;;("org" . "http://orgmode.org/elpa/") necesario para instalar org-mode nesario
;; para org-contacts, si no lo vas a utilizar lo puedes borrar
Puesta en marcha
Ficheros a usar para la autenticación
Pongo mi archivo authinfo.gpg
en una carpeta que luego sincronizo para poder usar fácilmente mi configuración en otros dispositivos.
(setq auth-sources '("~/.gnupg/shared/authinfo"))
Mis valores por defecto
Desactiva las barras de menús y desplazamiento, arranca Emacs en pantalla completa y algunos otros cambios para los valores por defecto.
(tool-bar-mode -1) ; disable bar-mode
(toggle-scroll-bar -1) ; disablescroll-mode
(tooltip-mode -1) ; Desactiva tooltips
(menu-bar-mode -1) ; desactiva barra menu
(fset 'yes-or-no-p 'y-or-n-p) ; sustituye yes/no por y/n
(display-time) ; muestra el rekoj
(line-number-mode t) ;;
(column-number-mode t) ;; mode line settings
(size-indication-mode t) ;;
(add-to-list 'default-frame-alist '(fullscreen . maximized)) ; pantalla completa
(global-set-key (kbd "C-+") 'text-scale-increase) ; Incrementa el tamaño de la funete
(global-set-key (kbd "C--") 'text-scale-decrease) ; Decrementa el tamaño de la funete
(size-indication-mode t) ; Muestra el tamaño del archivo
(custom-set-variables
'(initial-frame-alist (quote ((fullscreen . maximized))))) ; Fullscreen
(setq
inhibit-startup-screen t ; disable startup screen
display-time-24hr-format t ; Muestra el reloj en formato 24 hrs
display-time-format "%H:%M" ; Le da formato a la hora
ring-bell-function 'ignore ; Elimina el sonido de la campana
load-prefer-newer t ; Prefiere la versión más reciente de un archivo.
select-enable-clipboard t ; Sistema de fusión y portapapeles de Emacs.
use-package-always-ensure t ; Evita la clave :ensure para cada paquete
vc-follow-symlinks t ; Siempre sigue los enlaces simbólicos.
make-backup-files nil ; No realiza backups de ficheros
auto-save-default nil ; Deshabilita #file#
;org-footnote-section "Referencias:" ; cambio footnotes por referencias
global-hl-line-mode t ; Highlight current line
kill-ring-max 128 ; Longitud máxima del anillo de matar
create-lockfiles nil ; Impido la creación de ficheros .#
)
Recogida de basura
;; reduce the frequency of garbage collection by making it happen on
;; each 50MB of allocated data (the default is on every 0.76MB)
(setq gc-cons-threshold 50000000)
;; warn when opening files bigger than 100MB
(setq large-file-warning-threshold 100000000)
ibuffer
Ibuffer es un programa que mejora el manejo de los buffers por parte de Emacs.
;; replace buffer-menu with ibuffer
(use-package ibuffer
:ensure t
:config
(global-set-key (kbd "C-x C-b") #'ibuffer))
Vamos a añadir un pequeño código con algunas mejoras donde principalmente haremos que los buffers se agrupen en ciertos grupos dependiendo de lo que contengan unas pequeñas mejoras más.
(setq ibuffer-saved-filter-groups
(quote (("default"
("dired" (mode . dired-mode))
("org" (name . "^.*org$"))
("web" (or (mode . web-mode) (mode . js2-mode)))
("shell" (or (mode . eshell-mode) (mode . shell-mode)))
("mu4e" (name . "\*mu4e\*"))
("programming" (or
(mode . python-mode)
(mode . c++-mode)))
("emacs" (or
(name . "^\\*scratch\\*$")
(name . "^\\*Messages\\*$")))
))))
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-auto-mode 1)
(ibuffer-switch-to-saved-filter-groups "default")))
;; don't show these
;;(add-to-list 'ibuffer-never-show-predicates "zowie")
;; Don't show filter groups if there are no buffers in that group
(setq ibuffer-show-empty-filter-groups nil)
;; Don't ask for confirmation to delete marked buffers
(setq ibuffer-expert t)
Configuraciones estóticas
-
Cambiando el tema
(use-package nimbus-theme :ensure t :config (load-theme 'nimbus t))
-
Fuente
;; cambio la fuente (set-face-attribute 'default nil :height 130 :weight 'normal :width 'normal)
Actualiza automáticamente paquetes
Actualiza los paquetes cada 4 días, sustituye antiguas versiones por la nuevas
(use-package auto-package-update
:ensure t
:config
(setq auto-package-update-delete-old-versions t
auto-package-update-interval 4)
(auto-package-update-maybe))
Ortografía
-
Corrector ortográfico
Añado el corrector de ortografía en español, has de tener instalado aspell en el sistema
(setq ispell-program-name "aspell") (setq ispell-local-dictionary "espanol") (setq ispell-local-dictionary-alist '(("espanol" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil nil nil utf-8)))
-
Fly Spell
flyspell
habilita la revisión ortográfica sobre la marcha en Emacs.(use-package flyspell :defer 1 :delight :custom (flyspell-abbrev-p t) (flyspell-issue-message-flag nil) (flyspell-issue-welcome-flag nil) (flyspell-mode 1)) (use-package flyspell-correct-ivy :after flyspell :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-word-generic)) :custom (flyspell-correct-interface 'flyspell-correct-ivy)) ;; Activar Flyspell en modo texto y modos relacionados (add-hook 'text-mode-hook '(lambda () (flyspell-mode 1)))
-
Alternar entre diccionario en español e ingles
Habitualmente necesito cambiar entre el diccionario English y Spanish, uso esta función:
(defun fd-switch-dictionary() (interactive) (let* ((dic ispell-current-dictionary) (change (if (string= dic "espanol") "english" "espanol"))) (ispell-change-dictionary change) (message "Dicionario cambiado desde %s a %s" dic change) )) (global-set-key (kbd "<f6>") 'fd-switch-dictionary)
Hacer/deshacer
En lugar de tratar el deshacer/rehacer como una secuencia lineal de cambios, el modo undo-tree-mode trata el historial de deshacer como una rama de cambios, similar a la forma en que Vim lo maneja.
(use-package undo-tree
:delight
:bind ("C-d" . undo-tree-redo)
:init (global-undo-tree-mode 1)
:custom
(undo-tree-visualizer-timestamps t)
(undo-tree-visualizer-diff t))
Espacios en Blanco
(use-package whitespace
:ensure
:defer 1
:hook (before-save . delete-trailing-whitespace))
(use-package hungry-delete
:ensure t
:defer 0.7
:delight
:config (global-hungry-delete-mode))
Paróntesis
Muestra el padre y colorea los grupos de paróntesis de diferente color
(show-paren-mode 1) ; Mostrar al padre
(use-package rainbow-delimiters
:defer 1
:hook (prog-mode . rainbow-delimiters-mode))
(use-package smartparens
:defer 1
:delight
:custom (sp-escape-quotes-after-insert nil)
:config (smartparens-global-mode 1))
Autorevert
Recarga los archivos al ser modificados
(use-package autorevert
:ensure nil
:diminish
:hook (after-init . global-auto-revert-mode))
Usando el propio navegador de Emacs por defecto
Por defecto, Emacs que se adapta muy bien al entorno donde estós trabajando abrirá el navegador que tengas configurado en tu escritorio por defecto cuando quieras abrir un enlace. Si en vez de que abra el navegador por defecto quieres que no salga de Emacs y use su propio navegador en modo texto añadiremos la siguiente línea de configuración a nuestro fichero de configuración
(setq browse-url-browser-function 'eww-browse-url)
Emojify
Representación de los emojis
(use-package emojify
:ensure t)
Añadiendo números de líneas
En emacs tenemos mucha información en el mini-buffer como el nombre del archivo, el modo en el que está, los modos menores y la línea en la que estamos, pero hay que reconocer que muchas veces es más cómodo tener los números de línea a la izquierda del documento, junto a las líneas del documento. Para ello tenemos el paquete nlinum
Así que tendremos que instalarlo y añadirlo a nuestra configuración. Asignado a la tecla de función F9
(use-package nlinum
:ensure t
:config
(global-set-key (kbd "<f9>") #'nlinum-mode))
Archivos recientes
Proporciona un acceso rápido a los archivos recientes.
(use-package recentf
:defer 2
:bind ("C-c r" . recentf-open-files)
:init (recentf-mode)
:custom
(recentf-max-menu-items 10)
(recentf-max-saved-items 50)
(recentf-exclude (list "COMMIT_EDITMSG"
"~$"
"/scp:"
"/ssh:"
"/sudo:"
"diario.*"
"recentf*"
"bookmark*"
"/archivo*"
"birthday*"
"*elpa/*"
"/tmp/"
"public/*"
"~/.emacs.d/s*"))
:config (run-at-time nil (* 5 60) 'recentf-save-list))
Buffer
No pregunta antes de matar un buffer.
(global-set-key [remap kill-buffer] #'kill-this-buffer)
(kill-buffer "*scratch*")
Ditaa
Convierte texto ASCII a grafico, ubicacion del binario
(setq org-ditaa-jar-path "/usr/bin/ditaa")
Complementos
Paquetes complementarios para facilitar mi trabajo en Emacs
Control de Versión
Magit es una interfaz para el sistema de control de versiones Git, implementado como un paquete Emacs. Mientras no podamos (todavía) afirmar que Magit envuelve y mejora todos y cada uno de los comandos de Git, es lo suficientemente completo como para permitir que incluso los usuarios experimentados de Git realicen casi todos sus tareas diarias de control de versiones directamente desde Emacs
git-gutter
Además de eso, me gusta ver las líneas que se están modificando en el archivo mientras lo estoy editando.
Finalmente, git-timemachine~
lo utilizo para ver fácilmente los cambios realizados en commits anteriores.
(use-package magit
:ensure
:bind
("C-x g" . magit-status))
(use-package git-gutter
:ensure t
:defer 0.3
:delight
:init (global-git-gutter-mode))
(use-package git-timemachine
:defer 1
:delight)
Autopair y company
Vamos a instalar dos paquetes muy intersantes para escribir código. El autopair que sirve para que nos termine paróntesis, llaves, etc, y el paqute company para el autocompletado. Podemos ir primeramente a las webs de autopair y company.
(use-package autopair
:ensure t
:config (autopair-global-mode))
(use-package company
:ensure t
:config
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 3)
(global-company-mode t))
(add-hook 'after-init-hook 'global-company-mode)
Ivy y counsel
Ahora vamos a instalar una serie de paquetes que nos van a hacer la vida más fácil a la hora de trabajar con Emacs.
Por un lado tenemos a Ivy. Ivy es un sistema que autocompletado en diversos contextos como son menús, en el mini-buffer, código, etc. Lo mejor es verlo funcionar y ver como nos ayuda mucho a trabajar con Emacs.
Al mismo tiempo que Ivy vamos a instalar dos paquetes más que son swiper y counsel. Ambos ayudan mucho al trabajo con Emacs. Swiper ayuda a la búsqueda de texto dentro de un fichero y counsel ayuda a la búsqueda de comandos dentro del mini-buffer.
(use-package ivy
:ensure t
:config
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d) "))
(use-package swiper
:ensure t
:config
(global-set-key (kbd "C-s") 'swiper))
(use-package counsel
:ensure t
:config
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "<f1> f") 'counsel-describe-function)
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
(global-set-key (kbd "<f1> l") 'counsel-find-library)
(global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<f2> u") 'counsel-unicode-char))
Añadiendo neo-tree para la navegación a travós de los ficheros
Aunque es muy cómodo usar el programar dired para navegar entre los ficheros es muy práctico usar programas como neo-tree que es una versión para Emacs del neovim. Yo lo tengo configurado para que se active con la tecla .
(use-package neotree
:ensure t
:config
(setq neo-theme 'icons)
(global-set-key [f2] 'neotree-toggle))
Instalando projectile
Projectile es un gestor de proyectos. Lo instalamos ya que lo pide dashboard.
(use-package projectile
:ensure t
:config
(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(projectile-mode +1))
Añadiendo dashboard para un inicio bonito
Para ponerle una pantalla de inicio bonito usaremos el paquete dashboard que es un paquete que usa Spacemacs en el inicio solo que adaptado para poder ser usado en cualquier Emacs aunque no usemos Spacemacs. Lo activo con la tecla F10. Mi configuración:
;; instala iconos para dashboard
(use-package all-the-icons
:ensure t
:init
(unless (member "all-the-icons" (font-family-list))
(all-the-icons-install-fonts t)))
(use-package dashboard
:ensure t
:custom
(dashboard-banner-logo-title (format "Buen día %s" user-full-name))
(dashboard-startup-banner 'logo)
(dashboard-items '((recents . 4)
(projects . 3)
(agenda . 3)
))
:config
(setq dashboard-set-heading-icons t
dashboard-set-file-icons t
dashboard-set-init-info t
dashboard-set-navigator t)
(setq dashboard-navigator-buttons
`((
(,(when (display-graphic-p)
(all-the-icons-octicon "home" :height 1.1 :v-adjust 0.0))
"Página web" "El Blog de Lázaro"
(lambda (&rest _) (browse-url "https://elblogdelazaro.org")))
(,(when (display-graphic-p)
(all-the-icons-material "home" :height 1.35 :v-adjust -0.24))
"Localhost" "Abrir Hugo localhost"
(lambda (&rest _) (browse-url "http://localhost:8080/")))
(,(when (display-graphic-p)
(all-the-icons-octicon "tools" :height 1.0 :v-adjust 0.0))
"Configuración" "Abrir configuración de emacs (.org)"
(lambda (&rest _) (find-file (expand-file-name "~/.emacs.d/config.org"))))
(,(when (display-graphic-p)
(all-the-icons-octicon "calendar" :height 1.0 :v-adjust 0.0))
"Agenda" "Agenda personal"
(lambda (&rest _)
(interactive)
(if (get-buffer "*Org Agenda*")
(progn
(switch-to-buffer-other-window "*Org Agenda*")
(kill-buffer "*Org Agenda*")
(org-agenda-list))
(split-window-right)
(org-agenda-list))))
)))
:hook
(after-init . dashboard-setup-startup-hook))
(global-set-key (kbd "<f10>") 'open-dashboard) ;F10 para ir al Dashboard
(defun open-dashboard ()
"Open the *dashboard* buffer and jump to the first widget."
(interactive)
(delete-other-windows)
;; Refresh dashboard buffer
(if (get-buffer dashboard-buffer-name)
(kill-buffer dashboard-buffer-name))
(dashboard-insert-startupify-lists)
(switch-to-buffer dashboard-buffer-name))
Instalando Smex y which-key
Finalmente instalaremos dos paquetes que son muy útiles. El primero de ellos es smex el cual consigue que cuando empecemos a escribir un comando tras pulsar M-x los comandos que nos pongan primero gracias a counsel sean los que más hemos usado.
El segundo paquete es which-key y óste vale para cuando empecemos a usar las combinacionesde teclas. Este paquete lo que hace es que a la vez que vamos ejecutando las combinaciones de teclas se nos muestra una lista de quó siguiente combinación de teclas sigue y quó comando ejecutará.
;; iniciamos Smex
(use-package smex
:ensure t
:config
(smex-initialize))
;; iniciamos el paquete which-key
(use-package which-key
:defer 10
:ensure t
:config
(which-key-setup-minibuffer)
(which-key-mode 1))
eshell
Eshell es el emulador de consola de texto que lleva incorporado Emacs. En Emacs podemos ejecutar cualquier shell, sea bash, zsh, tcs, etc, pero lo que hace a Eshell único es que además de las funciones propias de un emulador de consola como comandos unix, alias, etc, tambión puedes ejecutar ordenes escritas en elisp.
El código
Vamos a añadir un pequeño código para mejorar el aspecto y la usabilidad de Eshell
;;; eshell ;;;;;;;;;;;;;;,
(eval-after-load "em-ls"
'(progn
(defun ted-eshell-ls-find-file-at-point (point)
"RET on Eshell's `ls' output to open files."
(interactive "d")
(find-file (buffer-substring-no-properties
(previous-single-property-change point 'help-echo)
(next-single-property-change point 'help-echo))))
(defun pat-eshell-ls-find-file-at-mouse-click (event)
"Middle click on Eshell's `ls' output to open files.
From Patrick Anderson via the wiki."
(interactive "e")
(ted-eshell-ls-find-file-at-point (posn-point (event-end event))))
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") 'ted-eshell-ls-find-file-at-point)
(define-key map (kbd "<return>") 'ted-eshell-ls-find-file-at-point)
(define-key map (kbd "<mouse-2>") 'pat-eshell-ls-find-file-at-mouse-click)
(defvar ted-eshell-ls-keymap map))
(defadvice eshell-ls-decorated-name (after ted-electrify-ls activate)
"Eshell's `ls' now lets you click or RET on file names to open them."
(add-text-properties 0 (length ad-return-value)
(list 'help-echo "RET, mouse-2: visit this file"
'mouse-face 'highlight
'keymap ted-eshell-ls-keymap)
ad-return-value)
ad-return-value)))
(add-hook 'eshell-preoutput-filter-functions 'ansi-color-apply)
Sugerencias para Eshell
Con el paquete esh-autosuggest nos crea Sugerencias basadas en nuestro historial al igual que fish
(use-package esh-autosuggest
:hook (eshell-mode . esh-autosuggest-mode)
;; If you have use-package-hook-name-suffix set to nil, uncomment and use the
;; line below instead:
;; :hook (eshell-mode-hook . esh-autosuggest-mode)
:ensure t)
Usándolo con Ivy
Si usamos Ivy podemos combinarlo de la siguiente forma:
(setq ivy-do-completion-in-region t) ; this is the default
(defun setup-eshell-ivy-completion ()
(define-key eshell-mode-map [remap eshell-pcomplete] 'completion-at-point)
;; only if you want to use the minibuffer for completions instead of the
;; in-buffer interface
(setq-local ivy-display-functions-alist
(remq (assoc 'ivy-completion-in-region ivy-display-functions-alist)
ivy-display-functions-alist)))
(add-hook 'eshell-mode-hook #'setup-eshell-ivy-completion)
Org
Configuraciones básicas para Orgmode
Org mode es una de las mejores maravillas que tiene Emacs. Se le suele llamar una skill app dentro de Emacs. Darían muchos documentos para explicar todo lo que se puede hacer con org-mode pero al menos para empezar podemos hacer que sea agradable a la vista y más cómodo de usar. Para ellos nos basaremos en un artículo de Howard Abrams llamado org-mode como un procesador de texto que podemos encontrar aquí.
De ese artículo podemos sacar la siguiente configuración:
Para que cuando usemos * / o _ para resaltar texto, estos símbolos no aparezcan:
(use-package org
:ensure org-plus-contrib
:delight "Θ "
:config
(setq org-hide-emphasis-markers t))
Para mejorar los bullets y que sean más bonitos
(font-lock-add-keywords 'org-mode
'(("^ +\\([-*]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
Mejorando aún más el aspecto de los bullets gracias al paquete org-bullets
(use-package org-bullets
:ensure t
:config
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
Adaptando el texto a la ventana
Finalmente haremos que cuando se visualice un fichero con extensión .org óste se adapte a la ventana y cuando la línea llegue al final de ósta haga un salto de carro. Para ellos añadiremos la línea
(add-hook 'org-mode-hook 'visual-line-mode);
Autocompletado para Org-mode
Para activar el autocompletado en org instalremos el paquete org-ac y añadiremos la siguiente configuración:
(use-package org-ac
:ensure t
:config
(org-ac/config-default))
Org-general
Org mode es una navaja suiza para Emacs en particular y para la vida en general, para muchos es una killer app que tiene Emacs,de hecho, algunas personas solo usan Emacs por Org mode.
Este solo es uno de los muchos ficheros de configuración que haremos para org mode ya que tiene tantas cosas que si lo hicieramos todo en uno nos saldría un fichero tremendamente largo.
Ficheros a usar
Inicialmente solo vamos a configurar algunas cosas relacionadas con la gestión de tareas y el con org mode.
Vamos a definir quó ficheros van a llevar los ficheros de la agenda y de las notas.
;; definiendo ficheros de agenda
(setq org-agenda-files (quote ("~/.personal/agenda/personal.org"
"~/.personal/agenda/trabajo.org"
"~/.personal/agenda/diario.org"
"~/.personal/agenda/diario-ibx.org")))
;; utilizo mi propio diario para a la agenda, asi que deshabilito el de emacs
(setq org-agenda-include-diary nil)
(setq org-agenda-diary-file "~/.personal/agenda/diario.org")
;; ubicacion de los ficheros cuando son archivados, organizados por fecha
(setq org-archive-location "~/.personal/archivo/%s_archivo.org.gpg::datetree/")
:; exportar
(setq org-export-backends '(ascii html latex md org texinfo))
;; Refile a otros ficheros de la agenda
(setq org-refile-targets (quote (("personal.org" :maxlevel . 1) ("trabajo.org" :level . 1))))
;;(setq org-refile-targets '((org-agenda-files :maxlevel . 1)))
Aspecto y etiquetas de las tareas
Ahora vamos a definir nuestras etiquetas de tareas para que además de los TODO, DONE, que tiene por defecto tenga otros y además le definiremos distintos colores
;; Define a kanban style set of stages for todo tasks
(setq org-todo-keywords
'((sequence "PORHACER(p!)"
"ENPROCESO(e!)"
"BLOQUEADO(b!)"
"|" "HECHO(h!)" "ARCHIVAR(a!)")))
;; Setting Colours (faces) for todo states to give clearer view of work
(setq org-todo-keyword-faces
'(("PORHACER" . org-warning)
("ENPROCESO" . "yellow")
("BLOQUEADO" . "red")
("HECHO" . "green")
("ARCHIVAR" . "blue")))
;; etiquetas que utilizo para mis notas
(setq org-tag-alist '(("@nota" . ?n)
("@casa" . ?c)
("@dinero" . ?d)
("@fecha" . ?f)
("@salud" . ?s)
("@tarea" . ?t)
("@coche" . ?h)
("@trabajo" . ?b)
("crypt" . ?C)))
(setq org-tags-exclude-from-inheritance '("crypt" "project"))
;; Progress Logging
;; When a TODO item enters DONE, add a CLOSED: property with current date-time stamp and into drawer
(setq org-log-done 'time)
(setq org-log-into-drawer "LOGBOOK")
;; Alinea etiquetas
(setq org-tags-column 80)
Teclas rápidas para tareas
Teclas rapidas para gestionar las tareas. Te debes de posicionar al inicio del encabezado y pulsar la tecla rapìda para que la tarea cambie de estado. Se encesita la funcion org-use-speed-commands-for-headings-and-lists
definida en el apartado Funciones propias.
Cuando inicamos el reloj la tarea cambia al estado ENPROCESO y cuando paremos el reloj a BLOQUEADO.
(setq org-use-speed-commands 'my/org-use-speed-commands-for-headings-and-lists)
(add-to-list 'org-speed-commands-user '("$" call-interactively 'org-archive-subtree))
(add-to-list 'org-speed-commands-user '("i" call-interactively 'org-clock-in))
(add-to-list 'org-speed-commands-user '("p" call-interactively 'org-clock-out))
(add-to-list 'org-speed-commands-user '("d" call-interactively 'org-clock-display))
(add-to-list 'org-speed-commands-user '("s" call-interactively 'org-schedule))
(add-to-list 'org-speed-commands-user '("x" org-todo "HECHO"))
(add-to-list 'org-speed-commands-user '("a" org-todo "ARCHIVAR"))
;; Cambiamos el estado de la tarea cuando inicia o para el reloj
(setq org-clock-in-switch-to-state "ENPROCESO")
(setq org-clock-out-switch-to-state "BLOQUEADO")
Personalizando el calendario
Aunque esto requiere un paquete extra, calfw-org, lo añadiró ahora porque con el tendremos un calendario muy resultón donde aparecerán nuestras tareas.
Para acceder a ól escribiremos M-x: cfw-caledario o pulsando la f8
Además vamos a hacerle unos ajustes de aspecto, como poner que empiece el calendario en Lunes, por defecto lo hace en Domingo y además poner los meses y los días de la semana en español.
-
Personalizando los meses y semana
(setq calendar-month-name-array ["Enero" "Febrero" "Marzo" "Abril" "Mayo" "Junio" "Julio" "Agosto" "Septiembre" "Octubre" "Noviembre" "Diciembre"]) (setq calendar-day-name-array ["Domingo" "Lunes" "Martes" "Miórcoles" "Jueves" "Viernes" "Sábado"]) (setq org-icalendar-timezone "Europe/Madrid") ;; timezone (setq calendar-week-start-day 1) ;; la semana empieza el lunes (setq european-calendar-style t) ;; estilo europeo
-
Festivos
Lista de fechas importantes según mi país, España. Es muy probable que algunas fechas sean diferentes en tu país o Comunidad Autónoma, , por lo tanto, adapta la configuración como corresponda.
(setq calendar-holidays '((holiday-fixed 1 1 "Año Nuevo") (holiday-fixed 1 6 "Reyes Magos") (holiday-fixed 4 18 "Jueves Santo") (holiday-fixed 4 19 "Viernes Santo") (holiday-fixed 5 1 "Dia del Trabajo") (holiday-fixed 5 2 "Comunidad de Madrid") (holiday-fixed 5 15 "San Isidro") (holiday-fixed 8 15 "Asunción") (holiday-fixed 10 12 "Día de la Hispanidad") (holiday-fixed 11 01 "Todos los Santos") (holiday-fixed 11 09 "Almudena") (holiday-fixed 12 06 "Constitución") (holiday-fixed 12 08 "Inmaculada") (holiday-fixed 12 25 "Navidad") ))
-
Poniendo una vista chula al calendario
(use-package calfw :config (setq cfw:org-overwrite-default-keybinding t)) ;; atajos de teclado de la agenda org-mode (use-package calfw-org :ensure t :config (setq cfw:org-overwrite-default-keybinding t) :bind ([f8] . cfw:open-org-calendar))
-
Sincronización con Caldav
Para terminar vamos a utilizar org-caldav para la sincronización bidireccional del calendario con servidores CalDav.
:files
son las ficheros que contienen los eventos que se sincronizaran con el calendario remoto,:inbox
es el fichero donde se descargan los eventos del calendario remoto(use-package org-caldav :ensure t :bind ([f4] . org-caldav-sync) :preface :custom ;; Calendarios a utilizar (org-caldav-url "https://servidor_caldav/caldav/carlos") (org-caldav-calendars '((:calendar-id "lfxlzur" :files ("~/.personal/agenda/diario.org") :inbox "~/.personal/agenda/diario-ibx.org") )) (org-caldav-backup-file "~/.personal/calendario/org-caldav-backup.org.gpg") (org-caldav-save-directory "~/.personal/calendario/") (org-icalendar-alarm-time 1) )
-
Sincronizando con vdirsyncer
Utilizo vdirsyncer para sincronizar calendario y agenda ya que tengo problemas con caldav y mi servidor, la tecla de funcoin
f3
llama a la funciónsync-my-diary
En el fichero
diario.org
he añadido una variable local para que cuando se guarde el fichero, al mismo tiempo se exporte en formato .ics para poder utilizarlo con vdirsyncer. Debe ir colocada al inicio del fichero.-*- eval: (add-hook 'after-save-hook 'org-icalendar-export-to-ics nil t) -*- (global-set-key [f3] 'sync-my-diary)
Babel
Configuración de babel para distintos lenguajes, org-babel permitirá evaluar código fuente de varios lenguajes interpretados, para introducirlo en documentos que podemos crear con org-mode y exportarlos en múltiples formatos.
(setq org-confirm-babel-evaluate nil
org-src-fontify-natively t
org-src-tab-acts-natively t)
(org-babel-do-load-languages
'org-babel-load-languages
'((dot . t)
(lisp . t)
(shell . t)
(python . t)
(latex . t)
(ditaa . t)
(org . t)))
Org-indent
Aspecto mejorado al identar
(add-hook 'org-mode-hook 'org-indent-mode)
Funciones propias
Ahora vamos a crear unas funciones muy simples que simplemente nos van a ayudar a acceder fácilmente a nuestros ficheros de Actividades, tareas y notas, escribióndolo en el mini-buffer con M-x
;;
(defun my/org-use-speed-commands-for-headings-and-lists ()
"funcion para que las teclas rapidas trabajen en los encabezados"
"Activa los comandos de velocidad tambión en los elementos de la lista."
(or (and (looking-at org-outline-regexp) (looking-back "^\**"))
(save-excursion (and (looking-at (org-item-re)) (looking-back "^[ \t]*")))))
;;
(defun sync-my-diary ()
"Sync diario.ics file with vdirsyncer external script and delete .ics."
(interactive)
(shell-command "vdirsyncer sync diario_sync")
(shell-command "rm ~/.personal/agenda/*.ics"))
Org-agenda
Vamos a configurar las vistas de agenda y los contactos para poder captura
Contactos
La mejor solución para mantener tus contactos. Suelo usar org-contacts
está disponible en org-plus-contrib
. Los contactos se guuardan en el fichero contactos.ord
(use-package org-contacts
:ensure nil
:after org
:custom
(org-contacts-files '("~/.personal/agenda/contactos.org.gpg")))
Agenda
Es importante tomarte tu tiempo para hacer una configuración que sea fácil de usar y que haga tu vida más fácil con una buena organización.
org-agenda
me permite ser organizado con las tareas diarias. Como resultado, puedo usar mi tiempo al máximo
Sincronizo mis archivos org
mediante Syncthing para poder revisar mi agenda y actualizarla desde varios ordenadores y dispositivos móviles.
La vista de agenda se activa la tecla F7 y tiene asociada dos vistas a las teclas (o) para el trabajo y (p) para la personal.
Las vistas están organizadas por estados
(use-package org-agenda
:ensure nil
:after org
:bind ([f7] . org-agenda)
:custom
(org-agenda-dim-blocked-tasks t)
(org-agenda-include-diary nil)
(org-agenda-inhibit-startup t)
(org-agenda-show-log t)
(org-agenda-skip-deadline-prewarning-if-scheduled 'pre-scheduled)
(org-agenda-span 4)
(org-agenda-start-on-weekday 1)
(org-deadline-warning-days 7)
(org-agenda-sticky nil)
(org-agenda-window-setup 'current-window) ; Sobrescribe la ventana actual con la agenda
(org-agenda-tags-column -100)
(org-agenda-time-grid '((daily today require-timed)))
(org-agenda-use-tag-inheritance t)
(org-enforce-todo-dependencies t)
(org-habit-show-habits-only-for-today nil)
(org-track-ordered-property-with-tag t)
(org-agenda-custom-commands
'(("h" "Habitos" tags-todo "STYLE=\"habit\""((org-agenda-overriding-header "Habitos")
(org-agenda-sorting-strategy
'(todo-state-down effort-up category-keep))))
("o" "Trabajo"
((agenda "" )
(tags-todo "trabajo/PORHACER"
((org-agenda-overriding-header "Tareas por Hacer")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline 'scheduled))
(org-tags-match-list-sublevels t)))
(tags-todo "trabajo/ENPROCESO"
((org-agenda-overriding-header "Tareas en Proceso")
(org-tags-match-list-sublevels t)))
(tags-todo "trabajo/BLOQUEADO"
((org-agenda-overriding-header "Tareas Paradas o Esperando")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline 'scheduled))
(org-tags-match-list-sublevels t)))
(tags "trabajo/HECHO"
((org-agenda-overriding-header "Tareas Hechas")
(org-tags-match-list-sublevels t)))
(tags "trabajo/ARCHIVADO"
((org-agenda-overriding-header "Tareas terminadas sin Archivar")
(org-tags-match-list-sublevels t)))
(tags "reubicar"
((org-agenda-overriding-header "Reubicar")
(org-tags-match-list-sublevels t)))
nil))
;; Reportes personales
("p" "Personal"
((agenda "" )
(tags-todo "personal/PORHACER"
((org-agenda-overriding-header "Tareas por Hacer")
;(org-agenda-skip-function '(org-agenda-skip-deadline-if-not-today))
(org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline 'scheduled))
(org-tags-match-list-sublevels t)))
(tags-todo "personal/ENPROCESO"
((org-agenda-overriding-header "Siguientes en Proceso")
(org-tags-match-list-sublevels t)))
(tags "personal/BLOQUEADO"
((org-agenda-overriding-header "Tareas Paradas o Esperando")
(org-tags-match-list-sublevels t)))
(tags "personal/HECHO"
((org-agenda-overriding-header "Tareas Hechas")
(org-agenda-todo-ignore-deadlines 'future)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-tags-todo-honor-ignore-options t)
(org-tags-match-list-sublevels t)))
(tags "personal/ARCHIVAR"
((org-agenda-overriding-header "Tareas terminadas sin Archivar")
(org-tags-match-list-sublevels t)))
(tags "reubicar"
((org-agenda-overriding-header "Reubicar")
(org-tags-match-list-sublevels t)))
nil))
)))
Notificaciones
Muestra notificaciones de otros paquetes de diversas formas. Por ahora solo lo uso para mostrar notificaciones de escritorio desde el código del paquete.
(require 'appt)
(appt-activate 1)
(use-package notifications
:demand t)
(add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt) ;; update appt list on agenda view
(setq appt-display-format 'window
appt-message-warning-time '5)
(setq appt-disp-window-function
(lambda (nmins curtime msg)
(notifications-notify :title "Recordatorio!!"
:body (format "Tienes una cita %s en %d minutos" msg (string-to-number nmins))
:app-name "Emacs: Org"
:sound-name "alarm-clock-elapsed")))
(display-time) ;; activate time display
(run-at-time "24:01" 3600 'org-agenda-to-appt) ;; update appt list hourly
(setq org-agenda-finalize-hook 'org-agenda-to-appt)
Captura
Las plantillas para org-capture
ahorran mucho tiempo al agregar nuevas entradas. yo las suelo usar para registrar rápidamente tareas, entradas de libro mayor, notas y otra información.
(use-package org-capture
:ensure nil
:after org
:bind ("C-c c" . org-capture)
:preface
(defvar my/org-basic-task-template "* PORHACER %?
Añadido: %U" "Plantilla básica de tareas.")
(defvar my/org-meeting-template "* Cita con %^{CON}
:PROPERTIES:
:SUMMARY: %^{DESCRIPCION ....}
:NOMOBRE: %^{NOMBRE ....}
:LUGAR: %^{DONDE ....}
:DIRECCION: %^{CALLE ....}
:TELEFONO: %^{123-456-789}
:NOTA: %^{NOTAS}
:AÑADIDA: %U
:END:
Fecha de la reunión: %?%T" "Plantilla para programar reuniones.")
(defvar my/org-contacts-template "* %(org-contacts-template-name)
:PROPERTIES:
:EMAIL: %(org-contacts-template-email)
:PHONE: %^{123-456-789}
:HOUSE: %^{123-456-789}
:ALIAS: %^{nick}
:NICKNAME: %^{hefistion}
:IGNORE:
:NOTE: %^{NOTA}
:ADDRESS: %^{Calle Ejemplo 1 2D, 28320, Pinto, Madrid, España}
:BIRTHDAY: %^{yyyy-mm-dd}
:END:" "Plantilla para org-contacts.")
:custom
(org-capture-templates
`(("c" "Contactos" entry (file+headline "~/.personal/agenda/contactos.org.gpg" "Amigos"),
my/org-contacts-template)
("f" "Fecha" entry (file+headline "~/.personal/agenda/reubicar.org" "Fechas"),
my/org-basic-task-template)
("n" "Nota" entry (file+headline "~/.personal/agenda/reubicar.org" "Nota"),
my/org-basic-task-template)
("i" "Cita" entry (file+datetree "~/.personal/agenda/diario.org"),
my/org-meeting-template)
("b" "Blog" entry (file+headline "~/.personal/agenda/reubicar.org.gpg" "Blog"),
my/org-basic-task-template)
("t" "Tarea" entry (file+headline "~/.personal/agenda/reubicar.org.gpg" "Tareas"),
my/org-basic-task-template))))
Cifrado / Descifrado
Para poder habilitar el cifrado y descifrado de archivos .gpg
con org-mode
, necesitaremos instalar gnupg2
.
Una vez hecho esto, simplemente configuramos org-crypt
para aceptar nuestro identificador de clave pública para permitir el cifrado asimótrico.
NOTA: necesitas modificar la variable org-crypt-key
para reemplazar mi identificador de clave por el tuyo (o nil
para permitir el cifrado simótrico).
org-crypt
cifra el texto de una entrada, pero no el título o las propiedades
(use-package org-crypt
:ensure nil
:after org)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt")))
(setq org-crypt-key "[email protected]")
(setq org-crypt-disable-auto-save nil)
Funciones propias
(defun org-agenda-skip-deadline-if-not-today ()
"If this function returns nil, the current match should not be skipped.
Otherwise, the function must return a position from where the search
should be continued."
(ignore-errors
(let ((subtree-end (save-excursion (org-end-of-subtree t)))
(deadline-day
(time-to-days
(org-time-string-to-time
(org-entry-get nil "DEADLINE"))))
(now (time-to-days (current-time))))
(and deadline-day
(not (= deadline-day now))
subtree-end))))
TOC
toc-org
mantendrá una tabla de contenido en el primer encabezado que tiene una etiqueta :TOC:
.
(use-package toc-org
:after org
:hook (org-mode . toc-org-enable))
Programación-Web
Lenguajes de programación y paquete0s necesarios para la creación de blogs
Markdown
Tienes que tener instalado markdown en tu equipo
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "markdown"))
Marcador ancho columna
(use-package fill-column-indicator
:ensure t
:init
(setq fci-rule-color "purple")
(setq fill-column 79)
(setq fci-rule-column 79)
(add-hook 'python-mode-hook 'fci-mode)
(add-hook 'lisp-mode-hook 'fci-mode)
(add-hook 'sh-mode-hook 'fci-mode))
Flycheck
(use-package flycheck
:config
;; (setq flycheck-global-modes '(python-mode))
;; (global-flycheck-mode)
(add-hook 'after-init-hook #'global-flycheck-mode)
:diminish flycheck-mode
:ensure t)
(use-package flycheck
hook
((org-mode
makdown-mode
; python-mode
text-mode) . turn-on-flyspell))
Htmlize
(use-package htmlize
:defer t
:config
(progn
;; It is required to disable `fci-mode' when `htmlize-buffer' is called;
;; otherwise the invisible fci characters show up as funky looking
;; visible characters in the source code blocks in the html file.
;; http://lists.gnu.org/archive/html/emacs-orgmode/2014-09/msg00777.html
(with-eval-after-load 'fill-column-indicator
(defvar modi/htmlize-initial-fci-state nil
"Variable to store the state of `fci-mode' when `htmlize-buffer' is called.")
(defun modi/htmlize-before-hook-fci-disable ()
(setq modi/htmlize-initial-fci-state fci-mode)
(when fci-mode
(fci-mode -1)))
(defun modi/htmlize-after-hook-fci-enable-maybe ()
(when modi/htmlize-initial-fci-state
(fci-mode 1)))
(add-hook 'htmlize-before-hook #'modi/htmlize-before-hook-fci-disable)
(add-hook 'htmlize-after-hook #'modi/htmlize-after-hook-fci-enable-maybe))
;; `flyspell-mode' also has to be disabled because depending on the
;; theme, the squiggly underlines can either show up in the html file
;; or cause elisp errors like:
;; (wrong-type-argument number-or-marker-p (nil . 100))
(with-eval-after-load 'flyspell
(defvar modi/htmlize-initial-flyspell-state nil
"Variable to store the state of `flyspell-mode' when `htmlize-buffer' is called.")
(defun modi/htmlize-before-hook-flyspell-disable ()
(setq modi/htmlize-initial-flyspell-state flyspell-mode)
(when flyspell-mode
(flyspell-mode -1)))
(defun modi/htmlize-after-hook-flyspell-enable-maybe ()
(when modi/htmlize-initial-flyspell-state
(flyspell-mode 1)))
(add-hook 'htmlize-before-hook #'modi/htmlize-before-hook-flyspell-disable)
(add-hook 'htmlize-after-hook #'modi/htmlize-after-hook-flyspell-enable-maybe))))
Org-Static-Blog
Configuración del blog con org-static-blog
(use-package org-static-blog
:ensure t
:init
(setq org-static-blog-publish-title "el blog de lázaro"
org-static-blog-publish-url "https://elblogdelazaro.org/"
org-static-blog-publish-directory "~/Documentos/proyectos/elblogdelazaro.org/public/"
org-static-blog-posts-directory "~/Documentos/proyectos/elblogdelazaro.org/posts"
org-static-blog-drafts-directory "~/Documentos/proyectos/elblogdelazaro.org/drafts"
org-static-blog-rss-file "index.xml"
org-static-blog-rss-max-entries 16
org-static-blog-langcode "es"
org-export-with-toc nil
org-static-blog-enable-tags t
org-export-with-section-numbers nil
org-static-blog-preview-ellipsis "(ver más..)"
org-static-blog-preview-link-p t
org-static-blog-preview-convert-titles nil
org-static-blog-use-preview t)
(setq org-static-blog-rss-extra
(concat
"<generator>"
(format "Emacs %d.%d" emacs-major-version emacs-minor-version) " "
"Org-mode " (org-version) " "
"org-static-blog 1.4.0"
"</generator>\n"
"<webMaster>" user-full-name " (" user-mail-address ") " "</webMaster>\n"
"<image>\n"
"<url>" org-static-blog-publish-url "static/favicon.ico" "</url>\n"
"<title>" org-static-blog-publish-title "</title>\n"
"<link>" org-static-blog-publish-url "</link>\n"
"</image>\n"))
;; This header is inserted into the <head> section of every page:
;; (you will need to create the style sheet at
;; ~/projects/blog/static/style.css
;; and the favicon at
;; ~/projects/blog/static/favicon.ico)
(setq org-static-blog-page-header
"<meta name=\"author\" content=\"Carlos M.\">
<meta name=\"generator\" content=\"org-blog-static\">
<meta name=\"viewport\" content=\"initial-scale=1,width=device-width,minimum-scale=1\">
<link rel=\"shortcut icon\" href=\"static/favicon.ico\" type=\"image/x-icon\">
<link rel=\"icon\" href=\"static/favicon.ico\" type=\"image/x-icon\">
<link href= \"static/style.css\" rel=\"stylesheet\" type=\"text/css\">"
)
;; This preamble is inserted at the beginning of the <body> of every page:
;; This particular HTML creates a <div> with a simple linked headline
(setq org-static-blog-page-preamble
"<header>
<p id=\"blogname\">
<a href=\"index.html\">El Blog de Lázaro</a>
<p/>
<p id=\"catchphrase\">
\"Mis notas sobre tecnología\"
</p>
<div id=\"nav\">
<a href=\"about.html\">Acerca de</a> <span class=\"sep\">|</span>
<a href=\"archive.html\">Archivo</a> <span class=\"sep\">|</span>
<a href=\"tags.html\">Tags</a> <span class=\"sep\">|</span>
<a href=\"index.xml\">Rss</a>
</div>")
;; This postamble is inserted at the end of the <body> of every page:
;; This particular HTML creates a <div> with a link to the archive page
;; and a licensing stub.
(setq org-static-blog-page-postamble
"<footer id=\"footer\">
Creado por <a href=\"https://elblogdelazaro.org\">el blog de lázaro</a> bajo licencia <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"> CC BY-SA 4.0</a>
generado con <a rel=\"org-static-blog\" href=\"https://github.com/bastibe/org-static-blog/\"> org-static-blog</a>
y <a rel=\"Emacs\" href=\"https://www.gnu.org/software/emacs/\">emacs</a>
</footer>"))
Espero que te haya gustado, pasa un gran día…