Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (II – Edición de código)


Suelo utilizar Emacs para editar código fuente para todos mis programas, tanto proyectos grandes como pequeños. Y, para crear muchos de los ejemplos que pongo en el blog (Aunque a veces la indentación no se copia bien). Por eso, es muy importante, tener herramientas para poder utilizar sin problemas y cómodamente el código en nuestro editor.

En este post, como ya empecé hace unos días (ver aquí Mi configuración personalizada para Emacs, primera parte) seguiré comentando punto por punto mi configuración actual de Emacs, con las utilidades a mi gusto. Aunque la configuración actualizada la tengo en GitHub, vamos a ver con detalle las partes dedicadas a ayuda de edición de código, orientado sobre todo a hacer más llevadera la programación con utilidades que mejoran nuestra experiencia de usuario y sesiones.

init.el

La configuración que muestro aquí está dividida en varios Archivos está dividida en múltiples archivos divididos por categorías. En el post anterior vemos más detalles sobre el árbol de directorios y el contenido de init.el así como la forma en la que tenemos que incluir los archivos que presento aquí.

De todas formas, este código puede ser evaluado con M-x eval-expression / M-x eval-region (dependiendo de dónde lo escribamos). Incluso es recomendable abrir un buffer nuevo (o *scratch*) para practicar y probar cosas.

Gestión de sesiones – init-sessions.el

En este archivo:

  • Establecemos configuración de las sesiones y bloqueos. En mi caso, dependiendo del directorio desde el que se abra Emacs. Así como el auto-salvado de la sesión, a los 10 minutos (600 segundos)
  • Sobreescribo funciones de lectura del desktop para mostrar el tiempo invertido en restaurar el desktop.
  • Hacemos que se restauren más aspectos de la sesión de Emacs con el session-mode.
  • Se establecen valores por defecto del tamaño de los historiales que guardará Emacs. No los pongo ilimitados para que se optimice un poco el uso de la memoria y las búsquedas sean más rápidas.
  • Configuramos las copias de seguridad. Éstas utilizarán el modo backup-by-copying, aunque es el más lento, de otro modo, la copia de seguridad se hace renombrando y en algunos sistemas de archivos puede dar problemas. Por otro lado, se mantendrán varias versiones de los archivos y todas las copias de seguridad se harán en el directorio ./.__backups__ dentro del directorio actual. Muchos prefieren guardar las copias de seguridad en otro sitio, podemos darle una ruta absoluta si queremos guardar todas las copias de seguridad juntas.
  • También me gusta la forma en la que Emacs ofrece salvado automático de archivos aunque podremos establecer el directorio que deseemos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
;; From https://github.com/purcell/emacs.d/blob/master/lisp/init-sessions.el
;; Using some settings from https://github.com/alexott/emacs-configs/blob/master/rc/emacs-rc-desktop.el
;; save a list of open files in ~/.emacs.d/.emacs.desktop

(setq-default desktop-missing-file-warning nil)

(setq emacs-sessions-directory (expand-file-name "sessions/" user-emacs-directory))
(setq emacs-desktop-file (concat "emacs_" (secure-hash 'md5 default-directory) ".desktop"))
(setq emacs-desktop-lock (concat "lock_" (secure-hash 'md5 default-directory)))
(setq desktop-path (list emacs-sessions-directory)
      desktop-base-file-name      emacs-desktop-file
      desktop-base-lock-name      emacs-desktop-lock
      desktop-save                t
      desktop-files-not-to-save   "^$" ;reload tramp paths
      desktop-auto-save-timeout 600)
(desktop-save-mode 1)

(defadvice desktop-read (around time-restore activate)
    (let ((start-time (current-time)))
      (prog1
          ad-do-it
        (message "Desktop restored in %.2fms"
                 (float-time (time-subtract (current-time)
                emacs-start-time))))))

(defadvice desktop-create-buffer (around time-create activate)
  (let ((start-time (current-time))
        (filename (ad-get-arg 1)))
    (prog1
        ad-do-it
      (message "Desktop: %.2fms to restore %s"
               (float-time (time-subtract (current-time)
                  emacs-start-time))
               (when filename
         (abbreviate-file-name filename))))))

;;----------------------------------------------------------------------------
;; Restore histories and registers after saving
;;----------------------------------------------------------------------------
(setq-default history-length 1000)
(savehist-mode t)

(require-package 'session)

(setq session-save-file (expand-file-name ".session" user-emacs-directory))
(setq session-name-disable-regexp "\\(?:\\`'/tmp\\|\\.git/[A-Z_]+\'\\)")
(add-hook 'after-init-hook 'session-initialize)

;;----------------------------------------------------------------------------
;; Histories configuration
;;----------------------------------------------------------------------------
;; save a bunch of variables to the desktop file
;; for lists specify the len of the maximal saved data also
(setq desktop-globals-to-save
      (append '((comint-input-ring        . 50)
                (compile-history          . 30)
                desktop-missing-file-warning
                (dired-regexp-history     . 20)
                (extended-command-history . 30)
                (face-name-history        . 20)
                (file-name-history        . 100)
                (grep-find-history        . 30)
                (grep-history             . 30)
                (ido-buffer-history       . 100)
                (ido-last-directory-list  . 100)
                (ido-work-directory-list  . 100)
                (ido-work-file-list       . 100)
                (ivy-history              . 100)
                (magit-read-rev-history   . 50)
                (minibuffer-history       . 50)
                (org-clock-history        . 50)
                (org-refile-history       . 50)
                (org-tags-history         . 50)
                (query-replace-history    . 60)
                (read-expression-history  . 60)
                (regexp-history           . 60)
                (regexp-search-ring       . 20)
                register-alist
                (search-ring              . 20)
                (shell-command-history    . 50)
                tags-file-name
                tags-table-list)))

(when (eval-when-compile (and (>= emacs-major-version 24)
                              (version emacs-version "24.3.50")
                              ))
  (unless (boundp 'desktop-restore-frames)
    (require-package 'frame-restore)
    (frame-restore)))

;;----------------------------------------------------------------------------
;; Backups and auto-save
;;----------------------------------------------------------------------------
;; Backups management (file~)
(setq backup-by-copying t)
(setq backup-directory-alist '(("." . ".__backups__")))
(setq delete-old-versions t
      kept-new-versions 6
      kept-old-versions 2
      version-control t)

;; Autosave backups management (#file#) Emacs Wiki, https://www.emacswiki.org/emacs/AutoSave
(defconst emacs-tmp-dir (expand-file-name (format "emacs%d" (user-uid)) temporary-file-directory))
(setq auto-save-file-name-transforms
        `((".*" ,emacs-tmp-dir t)))
    (setq auto-save-list-file-prefix
          emacs-tmp-dir)


(myemacs/elapsed-time)
(provide 'init-sessions)

init-cedet.el


CEDET (Collection of Emacs Development Environment Tools o Colección de Herramientas de Entorno de Desarrollo de Emacs) es una de las joyas de Emacs que permiten aumentar la funcionalidad de este editor a otro nivel. En CEDET tenemos muchas utilidades que harán que programemos mucho más rápido. Algunos de los módulos que encontramos en CEDET son:

  • Semantic: Analiza nuestro código para ofrecernos autocompletado inteligente, resaltar declaraciones de funciones, buscar implementaciones, navegar dentro de nuestro código, buscar errores, etc.
  • EDE: Emacs Development Environment (Entorno de Desarrollo de Emacs), nos proporciona un entorno de gestión de proyectos.
  • SRE: Gestor de plantillas
  • ECB: Emacs Code Browser (Navegador de Código de Emacs). Nos presentará una configuración de ventanas en la que incluirá un navegador de archivos y directorios, un navegador de objetos dentro de nuestro código y un historial además de la ventana de nuestro código. Es más o menos lo que se ve en la imagen de este apartado.
  • Otros: Podemos instalar una barra de acceso rápido a elementos (Speedbar), tenemos un módulo para crear diagramas (COGRE), y muchas funciones Lisp que pueden utilizar otros módulos para Emacs.

Nuestro archivo init-cedet.el será el siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
;; Based on Alex Ott's minimal-cedet-config : https://gist.github.com/alexott/3930120
;; and others

;; Use builtin CEDET instead of installing new CEDET version
(require 'cedet)
;; Load contrib directory
(add-to-list 'load-path (file-name-as-directory (expand-file-name "site-lisp/cedet-contrib/" user-emacs-directory)) "contrib")

;; Workarounds for Emacs
(when (eval-when-compile (version "25" emacs-version))
  (setq fixes-root-path (file-name-as-directory (expand-file-name "lisp/fixes/" user-emacs-directory)))
  (load-file (concat fixes-root-path "hideif.el")))

;; SemanticDB installed by default
(add-to-list 'semantic-default-submodes 'global-semanticdb-minor-mode t)
;; Buffer parsing when idle
(add-to-list 'semantic-default-submodes 'global-semantic-idle-scheduler-mode 1)
;; Display current function on header
(add-to-list 'semantic-default-submodes 'global-semantic-stickyfunc-mode 1)
;; Highlight the declaration of current function
(add-to-list 'semantic-default-submodes 'global-semantic-highlight-func-mode 1)
;; Display function info in minibuffer
(add-to-list 'semantic-default-submodes 'global-semantic-idle-summary-mode t)
;; srecode!!
(add-to-list 'semantic-default-submodes 'global-srecode-minor-mode t)
;; Show parser status when parsing lasts long
(add-to-list 'semantic-default-submodes 'global-show-parser-state-mode t)
;; Decorates some parts of the file due to the position where we are
(add-to-list 'semantic-default-submodes 'global-semantic-decoration-mode t)
;; Underline in red everything it cannot parse
(add-to-list 'semantic-default-submodes 'global-semantic-show-unmatched-syntax-mode)
;; Most Recently Used tags/functions fast jump
(add-to-list 'semantic-default-submodes 'global-semantic-mru-bookmark-mode)

(setq-default semantic-idle-scheduler-idle-time 5) ;I'm idle when I've been 5 seconds out
(setq-default semantic-idle-scheduler-verbose-flag 't) ;Tell me when you are working

(semantic-mode)

;; These may be automatically required, but I had them from previous versions
(require 'semantic/bovine/c)
(require 'semantic/bovine/gcc)
(require 'semantic/bovine/grammar)
(require 'semantic/bovine/make)
(require 'semantic/bovine/scm)
(require 'semantic/idle)
(require 'semantic/db)
(require 'semantic/ia)
(require 'semantic/analyze)
(require 'eassist)

;; customisation of modes
(defun gasparfm/cedet-hook ()
  (local-set-key [(control return)] 'semantic-ia-complete-symbol-menu)
  (local-set-key "\C-c?" 'semantic-ia-complete-symbol)
  ;;
  (local-set-key "\C-c>" 'semantic-complete-analyze-inline)
  (local-set-key "\C-c=" 'semantic-decoration-include-visit)
  ;; C-c+j = Fast jump
  (local-set-key "\C-cj" 'semantic-ia-fast-jump)
  ;; C-c+q = Show doc
  (local-set-key "\C-cq" 'semantic-ia-show-doc)
  ;; C-c+s Show Summary
  (local-set-key "\C-cs" 'semantic-ia-show-summary)
  ;; C-c+p = Toggle between prototype and function
  (local-set-key "\C-cp" 'semantic-analyze-proto-impl-toggle)
  ;; C-c+m = Switch MRU tags
  (local-set-key "\C-cp" 'semantic-mrub-switch-tags)
  )

(add-hook 'c-mode-common-hook 'gasparfm/cedet-hook)
(add-hook 'lisp-mode-hook 'gasparfm/cedet-hook)
(add-hook 'scheme-mode-hook 'gasparfm/cedet-hook)
(add-hook 'emacs-lisp-mode-hook 'gasparfm/cedet-hook)
(add-hook 'erlang-mode-hook 'gasparfm/cedet-hook)

(add-to-list 'semantic-dependency-system-include-path '/usr/include/c++/5/bits)
(semanticdb-enable-gnu-global-databases 'c-mode t)
(semanticdb-enable-gnu-global-databases 'c++-mode t)

;; SRecode
;; Delete ~/.emacs.d/srecode-map.el if any problems loading
(require 'srecode)
(global-srecode-minor-mode 1)

;; EDE
(require 'ede)
(global-ede-mode 1)
(ede-enable-generic-projects)

(require-package 'ecb)
(setq-default ecb-tip-of-the-day nil)

(myemacs/elapsed-time)
(provide 'init-cedet)

Lo primero que hacemos es cargar el módulo cedet que viene con Emacs. Aunque podemos descargarlo de Internet, con muchos módulos y más completo, el que viene con Emacs suele ser más nuevo y compatible con nuestra versión de Emacs. Puede que si lo descargamos, aunque sea desde la página oficial, tengamos ciertos problemas para echarlo a andar.

Luego cargamos en el load-path de Emacs el contenido de site-lisp/cedet-contrib. Dentro de este directorio (que podemos ver en el GitHub de mi configuración) he incluido algunos archivos que vienen con la instalación original de CEDET y no vienen en el core, pero que son interesantes.

Además, incluyo un archivo hideif.el que suele venir con Emacs y, tiene un bug en versiones inferiores a Emacs 25 (creo que en la 24.5 ya lo arreglaron, pero no llegué a probarlo). CEDET utiliza este módulo internamente y puede provocar algunos avisos, incluso hacer que no inicie Emacs correctamente.

Una vez cargado el módulo, vemos qué partes vamos a configurar. En mi caso, me quedo con Semantic, EDE, SREcode, ECB y EAssist (parte de los módulos de contrib que usan CEDET por debajo).

Semantic, que parsea el contenido de mis archivos de código leyendo variables, funciones, clases, espacios de nombres y demás lo suelo usar para asistirme mientras codifico. Esta asistencia suele ser el autocompletado inteligente, que me da opciones relativas a lo que estoy escribiendo. Puede darme opciones tanto del propio lenguaje como de bibliotecas que esté incluyendo y sean accesibles. Está pensado para C y C++, aunque para otros lenguajes también funciona bien y me permite trabajar rápidamente. Aunque está hecho en un lenguaje interpretado funciona muy rápido, e incluso hay formas de hacer que funcione más rápido aún, ayudándonos de aplicaciones externas, yo prefiero que mi configuración de Emacs sea lo más portable posible, y llevándome el directorio .emacs.d o incluso clonándolo de GitHub sea suficiente. También se usa para que ECB muestre información sobre los elementos que se encuentran en el código y pueda ir directamente a funciones, variables o estructuras determinadas o, por ejemplo, para que cuando programo en C o C++ pueda saltar directamente de un archivo de cabecera a uno de código sin tener que hacerlo a mano, dirigiéndome directamente al número de línea concreto donde está una función, una llamada, etc.

Aunque Semantic tiene muchas posibles configuraciones, en mi configuración personal incluiré:

  • semanticdb-minor-mode. Como parsear archivos de código fuente es una tarea pesada que puede dejar a Emacs colgado durante varios segundos o minutos. Haremos que Semantic sólo lea los archivos cuando haya cosas nuevas, almacenando en caché los elementos que ya ha leído y optimizando así su funcionamiento.
  • global-semantic-idle-scheduler-mode. Analiza archivos cuando no estoy directamente trabajando con Emacs. Porque es muy incómodo que, mientras estás trabajando, el editor se pare y no te deje hacer nada, aunque sea durante unos segundos. Por eso, aunque a veces, cuando utilizamos el autocompletado puede forzarse un parseo de los archivos, es interesante que, mientras no estemos trabajando se vayan completando ciertas partes del mismo. Personalmente, lo suelo configurar con semantic-idle-scheduler-idle-time indicando que se considere que no hago nada cuando lleve 5 segundos sin utilizar Emacs, y semantic-idle-scheduler-verbose-flag para que me indique en pantalla cuándo está trabajando Semantic.
  • global-semantic-stickyfunc-mode coloca en la parte superior del buffer el prototipo de la función dentro de la que estamos. Es muy útil cuando las funciones son muy grandes, o nuestra pantalla muy pequeña, para tener siempre presente el nombre de la función y los argumentos de entrada.
  • global-semantic-highlight-func-mode. Resalta llamadas o declaraciones de funciones mientras tenemos el cursor encima. Así sabemos dónde se llama, y dónde se declara una función.
  • global-semantic-idle-summary-mode. Nos muestra la cabecera de las funciones en el minibuffer ayudándonos a ver los argumentos de una función, método o llamada de un vistazo.
  • srecode-minor-mode. Activa el sistema de plantillas SREcode.
  • global-show-parser-state-mode. Cuando esté realizando un parseo de archivos fuente, decirnos el progreso del parseo en el minibuffer. Siempre es algo más lento decir cuánto lleva completado de una tarea e ir actualizando ese progreso, pero desespera menos al que pacientemente está mirando pasmado la pantalla esperando que se realice la tarea.
  • global-semantic-decoration-mode. Aplica una decoración a cada palabra clave del código.
  • global-semantic-show-unmatched-syntax-mode. Nos avisa cuando hay errores de sintaxis según el parseador. Puede que algo no sea un error de sintaxis propiamente dicho, en códigos muy complejos, tal vez el parser no llegue a lo que nosotros queremos, pero generalmente funciona bien.
  • global-semantic-mru-bookmark-mode. Nos permite saltar entre etiquetas (variables, funciones, etc) para dirigirnos a la parte del código donde se declaran/definen/llaman con M-n, M-p
  • También establecemos algunas teclas rápidas para llamar algunos métodos de semantic. Podemos verlo al final del post, en teclas rápidas y se añaden a un hook de determinados lenguajes.

Tras esto, se añaden algunas características para mejorar el parseo de las bibliotecas de C y C++.

Utilidades de edición (init-editing-utils.el)

Ahora vamos a ver algunas utilidades que nos ayudarán a utilizar nuestro entorno de programación, o configurarlo de manera fina, a nuestro gusto. Nota: El gusto de cada uno puede variar, aunque aquí tenéis un punto de partida.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
;; From : https://github.com/purcell/emacs.d/blob/master/lisp/init-editing-utils.el
;; and others

(require-package 'diminish)
(require-package 'unfill)
(require-package 'focus)

;; Automatic pairs open symbols (, {, [...
;; (when (fboundp 'electric-pair-mode)
;;   (electric-pair-mode))
(when (eval-when-compile (version "24.4" emacs-version))
  (electric-indent-mode 1))

;;----------------------------------------------------------------------------
;; Some basic preferences
;;----------------------------------------------------------------------------
(setq-default
 blink-cursor-interval 0.4
 bookmark-default-file (expand-file-name ".bookmarks.el" user-emacs-directory)
 buffers-menu-max-size 30
 case-fold-search t
 column-number-mode t
 delete-selection-mode t
 ediff-split-window-function 'split-window-horizontally
 ediff-window-setup-function 'ediff-setup-windows-plain
 indent-tabs-mode t
 make-backup-files t
 auto-save-interval 180                                 ;Auto save every 180 secs
 mouse-yank-at-point t
 save-interprogram-paste-before-kill t
 scroll-preserve-screen-position 'always
 set-mark-command-repeat-pop t
 tooltip-delay 0.5
 truncate-lines nil
 truncate-partial-width-windows nil)

(global-auto-revert-mode)
(setq global-auto-revert-non-file-buffers t
      auto-revert-verbose nil)

(transient-mark-mode t)

;;; Newline behaviour
(defun sanityinc/newline-at-end-of-line ()
  "Move to end of line, enter a newline, and reindent."
  (interactive)
  (move-end-of-line 1)
  (newline-and-indent))

(when (eval-when-compile (string "24.3.1" emacs-version))
  ;; https://github.com/purcell/emacs.d/issues/138
  (after-load 'subword
    (diminish 'subword-mode)))

;; Some bugs with indent-guide-mode and autocomplete-mode
;; (when (maybe-require-package 'indent-guide)
;;   (add-hook 'prog-mode-hook 'indent-guide-mode)
;;   (after-load 'indent-guide
;;     (diminish 'indent-guide-mode)))

;;(require-package 'nlinum)

(when (require-package 'rainbow-delimiters)
  (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))

(when (fboundp 'global-prettify-symbols-mode)
  (global-prettify-symbols-mode))

(require-package 'undo-tree)
(global-undo-tree-mode)
(diminish 'undo-tree-mode)


(require-package 'highlight-symbol)
(dolist (hook '(prog-mode-hook html-mode-hook css-mode-hook))
  (add-hook hook 'highlight-symbol-mode)
  (add-hook hook 'highlight-symbol-nav-mode))
(add-hook 'org-mode-hook 'highlight-symbol-nav-mode)
(after-load 'highlight-symbol
  (diminish 'highlight-symbol-mode)
  (defadvice highlight-symbol-temp-highlight (around sanityinc/maybe-suppress activate)
    "Suppress symbol highlighting while isearching."
    (unless (or isearch-mode
                (and (boundp 'multiple-cursors-mode) multiple-cursors-mode))
      ad-do-it)))

;;----------------------------------------------------------------------------
;; Zap *up* to char is a handy pair for zap-to-char
;;----------------------------------------------------------------------------
(autoload 'zap-up-to-char "misc" "Kill up to, but not including ARGth occurrence of CHAR.")
(global-set-key (kbd "M-Z") 'zap-up-to-char)

;;----------------------------------------------------------------------------
;; Browse kill ring
;;----------------------------------------------------------------------------
(require-package 'browse-kill-ring)
(setq browse-kill-ring-highlight-inserted-item 'pulse)
(setq browse-kill-ring-highlight-current-entry t)
(setq browse-kill-ring-show-preview t)
(setq browse-kill-ring-separator "\f")
(global-set-key (kbd "s-Y") 'browse-kill-ring)
(after-load 'browse-kill-ring
  (define-key browse-kill-ring-mode-map (kbd "C-g") 'browse-kill-ring-quit)
  (define-key browse-kill-ring-mode-map (kbd "M-n") 'browse-kill-ring-forward)
  (define-key browse-kill-ring-mode-map (kbd "M-p") 'browse-kill-ring-previous)
  (define-key browse-kill-ring-mode-map (kbd "") 'browse-kill-ring-forward)
  (define-key browse-kill-ring-mode-map (kbd "") 'browse-kill-ring-previous)
  (define-key browse-kill-ring-mode-map (kbd "") 'browse-kill-ring-previous


This post first appeared on Poesía Binaria - Programación, Tecnología Y Sof, please read the originial post: here

Share the post

Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (II – Edición de código)

×

Subscribe to Poesía Binaria - Programación, Tecnología Y Sof

Get updates delivered right to your inbox!

Thank you for your subscription

×