summaryrefslogtreecommitdiffhomepage
path: root/es-es/elisp-es.html.markdown
blob: a6cd3934b6b70457b41c606f2a5ff6f0f19eed29 (plain)
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
---
language: elisp
contributors:
    - ["Bastien Guerry", "http://bzg.fr"]
translators:
    - ["Guillermo Vayá", "http://willyfrog.es"]
lang: es-es
filename: learn-emacs-lisp-es.el
---

```scheme
;; Introduccion a Emacs Lisp en 15 minutos (v0.2d)
;;
;; Autor: Bastien / @bzg2 / http://bzg.fr
;; Traducción: Guillermo Vayá / @Driadan / http://willyfrog.es
;;
;; Antes de nada, lee este texto de Peter Norvig:
;; Traducido: http://loro.sourceforge.net/notes/21-dias.html
;; Original: http://norvig.com/21-days.html
;;
;; Ahora instala GNU Emacs 24.3:
;;
;; Debian: apt-get install emacs 
;; (o sigue las instrucciones de tu distribución preferida)
;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; Puedes encontrar información general sobre Emacs en:
;; http://www.gnu.org/software/emacs/#Obtaining

;; Aviso importante:
;;
;; Seguir este tutorial no provocará daños en tu ordenador a menos que
;; te enfades tanto que que acabes tirándolo al suelo. En tal caso 
;; declino cualquier responsabilidad. ¡A divertirse!


;; "N. del. T.": Algunos términos comunes de la informática se han dejado 
;; sin traducir ya que es mucho más probable que el lector los conozca en 
;; su forma en inglés, siendo la versión en español de muy raro uso.
;; Además "sexps" se ha decidido traducir por sexpresión.
;; Por último, añadir que no se han traducido los ejemplos de código ya que no 
;; es necesario entender qué dice el string para comprender el funcionamiento
;; y podría llevar a error.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;; Inicia Emacs.
;;
;; Pulsa la tecla `q' para pasar el mensaje de bienvenida.
;;
;; Mira a la línea gris en la parte inferior de la ventana:
;;
;; "*scratch*" es el nombre del espacio editable donde estás.
;; A este espacio editable se le llama "buffer".
;;
;; Scratch es el buffer por defecto cuando abres Emacs.
;; En Emacs nunca editas ficheros, sino que editas buffers que 
;; posteriormente pueden grabarse a un fichero.
;; can save to a file.
;; 
;; "Lisp interaction" indica el conjunto de ordenes disponibles.
;; 
;; Emacs dispone de un set de comandos disponibles en cualquier buffer
;; ("built-ins") y aparte varios conjuntos de ordenes disponibles 
;; según el modo específico que esté activo. En nuestro caso 
;; estamos usando `lisp-interaction-mode', el cual incluye las
;; ordenes necesarias para evaluar y navegar código Elisp.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Un punto y coma comienza un comentario. Pueden ponerse en cualquier 
;; posicion de la linea.
;;
;; Los programas en Elisp se componen de expresiones simbólicas
;; tambien llamadas "sexps":
(+ 2 2)

;; Esta expresión simbólica se lee tal que "Suma 2 y 2"

;; Las sexpresiones se rodean por paréntesis, y pueden anidarse:
(+ 2 (+ 1 1))

;; Una expresion simbólica está formada bien por átomos o bien por otras 
;; expresiones simbólicas. En el ejemplo de arriba, 1 y 2 son átomos, 
;; mientras que (+ 2 (+ 1 1)) y (+ 1 1) son expresiones simbólicas.

;; Gracias a `lisp-interaction-mode' puedes evaluar las sexpresiones.
;; Coloca el cursor justo despues del paréntesis de cierre y 
;; mantén pulsada la tecla Control y la j (para abreviar usaremos "C-j").

(+ 3 (+ 1 2))
;;           ^ pon aquí el cursor
;; `C-j' => 6

;; `C-j' añade el resultado de la evaluación al buffer.

;; `C-xC-e' muestra el mismo resultado pero en la linea inferior
;; la cual se llama "minibuffer".  Este será el metodo que usaremos 
;; normalmente para no llenar el buffer con texto inútil.

;; `setq' guarda un valor en una variable:
(setq my-name "Bastien")
;; `C-xC-e' => "Bastien" (aparece en el mini-buffer)

;; `insert' añade "Hello!" en el punto donde esté tu cursor:
(insert "Hello!")
;; `C-xC-e' => "Hello!"

;; Aunque hemos usado `insert' con solo un parámetro "Hello!", se
;; pueden pasar más. Por ejemplo, en esta otra sexpresión usamos dos:

(insert "Hello" " world!")
;; `C-xC-e' => "Hello world!"

;; Se pueden usar variables en lugar de strings:
(insert "Hello, I am " my-name)
;; `C-xC-e' => "Hello, I am Bastien"

;; Puedes combinar sexpresiones en funciones:
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' => hello

;; Evaluemos la funcion:
(hello)
;; `C-xC-e' => Hello, I am Bastien

;; Los parentesis vacios en la definicion de una funcion indican
;; que no acepta parámetros. En cualquier caso, usar `my-name' siempre
;; es aburrido, asi que vamos a hacer que la función accepte un parámetro
;; (en este caso el parametro se llama "name"):
(defun hello (name) (insert "Hello " name))
;; `C-xC-e' => hello

;; Ahora vamos a llamar a la funcion con el string "you" como valor para 
;; el único parámetro que posee.
(hello "you")
;; `C-xC-e' => "Hello you"

;; ¡Genial!

;; Descansa un poco y respira.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Ahora cambiaremos al nuevo buffer, llamado "*test*", en una nueva ventana.

(switch-to-buffer-other-window "*test*")
;; `C-xC-e'
;; => [La pantalla ahora tiene dos ventanas y el cursor está en el buffer *test*]

;; Mueve el ratón sobre la ventana superior y pulsa el boton izdo. para volver. 
;; Otra forma es usando `C-xo' (pulsa simultaneamente control y x y luego la o)
;; para ir a la otra ventana.

;; Se pueden combinar varias sexpresiones mediante `progn':
(progn
  (switch-to-buffer-other-window "*test*")
  (hello "you"))
;; `C-xC-e'
;; => [De las dos ventanas de la pantalla, el cursor está en la marcada como *test*]

;; A partir de ahora, si no te importa, dejaremos de decir que pulses `C-xC-e': 
;; tendrás que hacerlo para ejecutar cada sexpresión que siga.

;; También tendrás que volver al buffer *scratch* bien con el ratón o con `C-xo'.

;; En ocasiones será util limpiar el buffer:
(progn
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello "there"))

;; O volver a la ventana anterior:
(progn
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello "you")
  (other-window 1))

;; Puedes enlazar un valor a una variable local con `let':
(let ((local-name "you"))
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello local-name)
  (other-window 1))

;; En este caso, no hace falta añadir `progn' ya que `let' permite combinar 
;; varias sexpresiones.

;; Vamos a darle formato a un string:
(format "Hello %s!\n" "visitor")

;; Cada %s indica la posicion donde irá un string, el cual será reemplazado 
;; por "visitor". "\n" es el caracter de nueva línea.

;; Mejoremos nuestra funcion usando `format':
(defun hello (name)
  (insert (format "Hello %s!\n" name)))

(hello "you")

;; Creemos una nueva funcion que utililce `let':
(defun greeting (name)
  (let ((your-name "Bastien"))
    (insert (format "Hello %s!\n\nI am %s."
                    name       ; the argument of the function
                    your-name  ; the let-bound variable "Bastien"
                    ))))

;; Y ahora la evaluamos:
(greeting "you")

;; Algunas funciones son interactivas:
(read-from-minibuffer "Enter your name: ")

;; Al evaluar esta función, ésta devuelve lo que hayas introducido.

;; Ahora hagamos nuestra función `greeting' preguntar por tu nombre:
(defun greeting (from-name)
  (let ((your-name (read-from-minibuffer "Enter your name: ")))
    (insert (format "Hello!\n\nI am %s and you are %s."
                    from-name ; the argument of the function
                    your-name ; the let-bound var, entered at prompt
                    ))))

(greeting "Bastien")

;; Y ahora la completamos mostrando el resultado en la otra ventana:
(defun greeting (from-name)
  (let ((your-name (read-from-minibuffer "Enter your name: ")))
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    (insert (format "Hello %s!\n\nI am %s." your-name from-name))
    (other-window 1)))

;; Probémosla:
(greeting "Bastien")

;; Descansa un poco y respira.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Creemos una lista de nombres:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))

;; Para coger el primer elemento de la lista usaremos `car':
(car list-of-names)

;; Para coger todos menos el primer elemento de la lista 
;; usaremos `cdr':
(cdr list-of-names)

;; Para añadir un elemento al comienzo de la lista utilizamos `push':
(push "Stephanie" list-of-names)

;; OJO: `car' y `cdr' no modifican la lista, mientras que `push' sí.
;; ¡Es una diferencia importante! Algunas funciones no tienen efectos 
;; colaterales (como `car') mientras que otras sí (como `push').
;; "N. del T.": estos efectos colaterales se les llama `side-effects' en 
;; las distintas variantes de lisp.

;; Llamemos a `hello' con cada elemento de `list-of-names':
(mapcar 'hello list-of-names)

;; Retocamos `greeting' para que salude a todos los que estén en `list-of-names':
(defun greeting ()
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    (mapcar 'hello list-of-names)
    (other-window 1))

(greeting)

;; ¿Te acuerdas de la función `hello' definida un poco más arriba?
;; Recibía un parámetro: `name'. Así que `mapcar' llama a `hello' con cada 
;; elemento de `list-of-names' como parámetro de `hello'.

;; Ahora ordenaremos un poco lo que tenemos en el buffer:

(defun replace-hello-by-bonjour ()
    (switch-to-buffer-other-window "*test*")
    (goto-char (point-min))
    (while (search-forward "Hello")
      (replace-match "Bonjour"))
    (other-window 1))

;; (goto-char (point-min)) mueve el cursor al principio del buffer.
;; (search-forward "Hello") busca un string "Hello".
;; (while x y) evalua la/s sexpresion/es y mientras que x devuelva
;; alguna cosa.
;; En el momento que x devuelva `nil' (es decir nada), sale del 
;; bucle `while'.

(replace-hello-by-bonjour)

;; Observamos que todas las veces que teníamos la palabra "Hello" en el buffer *test*
;; han sido reemplazadas por "Bonjour".

;; Y además, hemos obtenido un error: "Search failed: Hello".
;;
;; Para evitar este error, hay que decirle a `search-forward' si debería dejar de 
;; buscar en el buffer en algún momento y si debería fallar sin quejarse cuando 
;; no encuentra nada.

;; (search-forward "Hello" nil t) justo hace eso:

;; El argumento `nil' significa que la busqueda no está ligada a ninguna posición.
;; Y el argumento `t' le pide que no diga nada si no encuentra el string.

;; Usaremos esta sexpresión en la función siguiente, la cual ya 
;; no muestra ningún error:

(defun hello-to-bonjour ()
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    ;; Say hello to names in `list-of-names'
    (mapcar 'hello list-of-names)
    (goto-char (point-min))
    ;; Replace "Hello" by "Bonjour"
    (while (search-forward "Hello" nil t)
      (replace-match "Bonjour"))
    (other-window 1))

(hello-to-bonjour)

;; Añadamos algo de color a los nombres:

(defun boldify-names ()
    (switch-to-buffer-other-window "*test*")
    (goto-char (point-min))
    (while (re-search-forward "Bonjour \\(.+\\)!" nil t)
      (add-text-properties (match-beginning 1)
                           (match-end 1)
                           (list 'face 'bold)))
    (other-window 1))

;; Esta función nos presenta `re-search-forward': en vez de 
;; buscar el string "Bonjour" exacto, se busca por un patrón
;; usando una "expresión regular" (lo cual se muestra abreviado 
;; en el prefijo "re-" del inglés "Regular Expression").

;; La expresión regular a utilizar es "Bonjour \\(.+\\)!" y se traduce como:
;; el string "Bonjour ", seguido de 
;; un grupo de           | representado por \\( ... \\)
;;   cualquier caracter  | representado por .
;;   al menos una vez    | representado por +
;; y el string "!".

;; ¿Preparado?  ¡Probemoslo!

(boldify-names)

;; `add-text-properties' añade propiedades al texto, como una fuente.

;; ¡Hale! ¡Ya lo tenemos! ¡Feliz hacking!

;; Si quieres saber más sobre una función o una variable:
;;
;; C-h v la-variable RET
;; C-h f la-funcion RET
;;
;; Si quieres leer el manual de Emacs Lisp desde dentro de Emacs:
;;
;; C-h i m elisp RET
;;
;; Para leer una introducción en linea de Emacs Lisp:
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html

;; Me gustaría agradecer a las siguientes personas su feedback y sugerencias:
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
;; - LinXitoW
;; - Aaron Meurer
```