-
Notifications
You must be signed in to change notification settings - Fork 0
/
yatexgen.el
585 lines (538 loc) · 19.7 KB
/
yatexgen.el
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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
;;; yatexgen.el --- YaTeX add-in function generator(rev.5)
;;; (c)1991-1995,1999,2000 by HIROSE Yuuji.[[email protected]]
;;; Last modified Sat Sep 1 08:10:36 2012 on firestorm
;;; $Id$
;;; Code:
(require 'yatex)
(defmacro YaTeX-setq (var japanese english)
(list 'setq var
(if YaTeX-japan japanese english)))
(put 'YaTeX-setq 'lisp-indent-hook 1)
(YaTeX-setq YaTeX-generate-initial-message
" 自動生成モードへようこそ!!
初めてやる人はこのバッファの例にしたがって指示通りにやって練習してね。
本番の時もこのバッファに出るメッセージを *よく読んで* 操作しないとう
まく関数が作れないよ!!
ではリターンキーを押して下さい。"
" Welcome to auto-generation mode!!
If this is your first trial, exercise this according to example and
following my messages. Then, at making actual function, operate
reading my messages *carefully*, or you'll fail to generate appropriate
function.
Hit return key!")
(YaTeX-setq YaTeX-generate-start-message
"さぁはじめるよ.\n1.登録したい補完をやってみて.
たとえば section 型補完の \\documentstyle だったら \\documentstyle{}
だけをいれてみてね. ちゃんと『~型補完』を使わないとダメよ!。
で、おわったらりたーん!!"
"Let's begin completion for which you want to make add-in function.
If you want to make add-in function for \\documentstyle input only
`\\documentstyle{}' *with* completion of yatex-mode.
If you finish this, please press RET.")
(YaTeX-setq YaTeX-generate-abort-message
"やめた、やめた~いめんどくせ~"
"Aborted.")
(YaTeX-setq YaTeX-generate-same-message
"それじゃ、なにも変わってねぇだろーが! やめた。"
"I found no difference between them. So I'm quitting.")
(YaTeX-setq YaTeX-generate-invalid-message
"それは、ちと無理というものじゃ."
"It's impossible.")
(YaTeX-setq YaTeX-generate-idontknow-message
"う~ん、難しくてよくわからないなぁ。ばかでごめんねェ~"
"Sorry I can't tell your adding method.")
(YaTeX-setq YaTeX-generate-confirm-message
"ということは、付け足したい部分はこれでいいのね"
"Is it additional string of add-in function?")
(YaTeX-setq YaTeX-generate-output-message
"2.じゃ、それにくっつけたいものを *カーソルの位置に* 足してみて.
さっきの \\documentstyle{} の例だと \\documentstyle[12pt]{} とかにするの。
しつこいようだけど、今の位置からカーソル動かしちゃダメよ!!
で、またおわったらりたーん!!"
"2.Then input additional string *at CURSOR POSITION*
According to last example \\documentstyle{},
modify it \\documentstyle[12pt]{}. RET to finish.")
(YaTeX-setq YaTeX-generate-put-arg-message
"3.このうち、キーボードから読み込んで欲しい文字列を順に入れて。
さっきの \\documentstyle[12pt]{} だったら、付加する文字は[12pt]だけど
手で入れたいのは 12pt の部分だけですね。
で、全部入れ終ったら、りたーんだけうってね!!"
"3.In this string, extract string which you want to input from key
board with quiry afterwards. For example, though additional string is
\\documentstyle[12pt]{}, but you want enter only `12pt' by hand.
RET to finish!")
(YaTeX-setq YaTeX-generate-read-prompt-message
"4.では、あとでこれらの文字列を読み込む時に、どういうプロンプトを
出したいですか? 順に入れて下さい。面倒なら単にリターンを打ってね。
さっきの 12pt の部分だったら、『サイズは』とかがおすすめ。"
"4.When you use this add-in function afterwards, what message
do you like to be prompted with to enter these values. In last
example `12pt', typical prompt string may be `Size?: '.")
(YaTeX-setq YaTeX-generate-done-message
"よし! これが、君の作りたかった関数だ。~/.emacs にでも入れてせいぜい
楽してくれ。このバッファ(*ご案内*)を yatex-mode にしておくから
できた関数が本当にお望みの動作をするか確かめてみるといいかもね。
ところで、この関数こんなに簡単だろう? そろそろ自分で書いたらどう?
"
"OK! This is the definition of function you want to make! Add
this description to your ~/.emacs or so. Use this buffer(*Guide*)
for testing of this function please.
But you can see this function quite easy, can't you? You had better
write your most favorite add-in function yourself!
")
(YaTeX-setq YaTeX-generate-nomatch-message
"こらこら、そんな文字列どこにもねーぞ!!"
"No such string in additional string.")
(YaTeX-setq YaTeX-generate-buffer
"*付加関数生成バッファ*"
"*Generate-add-in-function*")
(YaTeX-setq YaTeX-generate-message-buffer
"*ご案内*"
"*Guide*")
(YaTeX-setq YaTeX-generate-bug-message
"ごめ~ん!! ちょっと、このアドイン関数つくるの失敗しちゃったみたい!!
作者まで連絡してくださ~~~い!"
"Sorry I failed to make add-in function for you...
Send bug report to me.")
(YaTeX-setq YaTeX-generate-narrow-message
"画面がせますぎるような気がします。"
"Too narrow screen height.")
(defvar YaTeX-generate-message-height
10 "Window height of YaTeX-generate-message-buffer")
;; Do you need learning for generated function?
;; If you need, please tell me ([email protected])
;;(defvar YaTeX-generate-variables-for-learning nil)
;;(defvar YaTeX-generate-current-completion-table nil)
;;;
;Generate mode.
;;;
(defun YaTeX-generate ()
"Genarate YaTeX add-in function with enquiry."
(interactive)
(if (< (YaTeX-screen-height) (+ YaTeX-generate-message-height 10))
(error YaTeX-generate-narrow-message))
(put 'YaTeX-generate 'disabled t)
(save-window-excursion
(unwind-protect
(let (input output (i 0) (beg 0) end add-in map map1 si str slist
(from (make-marker)) (to (make-marker)))
(delete-other-windows)
(switch-to-buffer YaTeX-generate-message-buffer)
(yatex-mode)
(erase-buffer)
(insert YaTeX-generate-initial-message)
(read-string
(if YaTeX-japan "リターンキーを押して下さい." "Press RETURN."))
(erase-buffer)
(insert YaTeX-generate-start-message)
(pop-to-buffer (get-buffer-create YaTeX-generate-buffer))
(enlarge-window (- (window-height) YaTeX-generate-message-height 1))
(erase-buffer)
(yatex-mode)
(use-local-map (setq map (copy-keymap YaTeX-mode-map)))
(define-key (current-local-map) "\n" 'exit-recursive-edit)
(define-key (current-local-map) "\r" 'exit-recursive-edit)
(define-key (current-local-map) "\C-g" 'abort-recursive-edit)
(setq map1 (copy-keymap map))
(YaTeX-suppress-sparse-keymap map)
;;First get input form.
(recursive-edit)
(setq input (YaTeX-minibuffer-string)
end (1- (length input)))
(if (string= "" input) (error YaTeX-generate-abort-message))
(YaTeX-generate-move-to-add-in-position)
(set-marker from (1- (point))) ;;Can't write before `from'
(set-marker to (1+ (point))) ;;Can't write after `to'
;;Second get output form.
(setq beg (1- (point)));;Cheat begin point!
(YaTeX-generate-display-message YaTeX-generate-output-message)
(use-local-map map1)
(fset 'si (symbol-function 'self-insert-command))
(defun self-insert-command (arg)
(interactive "p")
(if (or (not (equal (buffer-name) YaTeX-generate-buffer))
(and (> (point) (marker-position from))
(< (point) (marker-position to))))
(insert (this-command-keys)) (ding)))
(unwind-protect
(recursive-edit)
(fset 'self-insert-command (symbol-function 'si)))
(setq output (YaTeX-minibuffer-string))
(cond ((string= "" output) (error YaTeX-generate-abort-message))
((string= input output) (error YaTeX-generate-same-message))
((< (length output) (length input))
(error YaTeX-generate-invalid-message)))
;;(while (and (< beg end) (= (aref input beg) (aref output i)))
;; (setq beg (1+ beg) i (1+ i))) ;;for universal use.
(setq i (1- (length output)))
(while (and (>= end beg) (= (aref output i) (aref input end)))
(setq end (1- end) i (1- i)))
(setq add-in (substring output beg
(if (= i (1- (length output))) nil (1+ i))))
(erase-buffer)
(insert add-in)
(if (not (y-or-n-p YaTeX-generate-confirm-message))
(error YaTeX-generate-idontknow-message))
;;Extract arguments.
(YaTeX-generate-display-message YaTeX-generate-put-arg-message)
(setq i 1)
(while (not (string=
"" (setq str (read-string (format "Arg %d: " i)))))
(if (not (string-match (regexp-quote str) add-in))
(progn
(ding)
(YaTeX-generate-display-message
YaTeX-generate-nomatch-message -1))
(setq slist (append slist (list (list str))) i (1+ i)))
);input all of arguments.
;;Compare with output string.
(set-buffer YaTeX-generate-buffer) ;;for safety
(emacs-lisp-mode)
(if (> i 1)
(YaTeX-generate-parse-add-in slist add-in)
(erase-buffer)
(insert "(defun " (YaTeX-generate-function-name) " ()\n")
(insert "\"" (YaTeX-generate-lisp-quote add-in) "\")\n")
(indent-region (point-min) (point-max) nil)
(message (if YaTeX-japan
"このくらいの関数手で書け!!"
"You don't need me to make such easy function.")))
);let
(put 'YaTeX-generate 'disabled nil)
(put 'YaTeX-addin 'disabled nil)
))
(YaTeX-generate-display-message YaTeX-generate-done-message)
(switch-to-buffer YaTeX-generate-buffer)
(condition-case error
(eval-current-buffer)
(error (insert YaTeX-generate-bug-message)))
(pop-to-buffer YaTeX-generate-message-buffer))
(defun YaTeX-generate-parse-add-in (args add-in)
"Parse add-in string and extract argument for it.
Variable add-in is referred in parent function."
(let ((i 1) j (case-fold-search nil) ;i holds argument number
(prompt (make-vector (length args) ""))
(used (make-vector (length add-in) nil))
func-name (string ""))
;;Phase 1. extract argument from add-in string.
(mapcar
'(lambda (arg)
(let ((index 0) (match 0) beg end (carg (car arg)))
(YaTeX-generate-display-message
YaTeX-generate-read-prompt-message)
(aset prompt (1- i)
(read-string
(format
(if YaTeX-japan "%d番目(%s)を読む時?: "
"When reading argument #%d(%s)?: ") i (car arg))))
(while (string-match (regexp-quote carg) (substring add-in index))
(setq beg (+ index (match-beginning 0))
end (+ index (match-end 0)))
(if (aref used beg) nil
(setq match (1+ match))
(cond
((= match 1)
;;(setq arg (append arg (list (list beg end))))
(YaTeX-generate-register-match))
((YaTeX-generate-ask-match-position)
(YaTeX-generate-register-match))))
(setq index end))
(setq i (1+ i))))
args)
;;Phase 2. Generate function!!
(setq i 0)
(setq func-name (YaTeX-generate-function-name))
(while (< i (length add-in))
(setq beg i j (aref used i))
(while (and (< i (length add-in)) (equal j (aref used i)))
(setq i (1+ i)))
(if j ;If it is argument.
(setq string (concat string (format " arg%d" j)))
(setq string
(concat string " \""
(YaTeX-generate-quote-quote (substring add-in beg i))
"\""))
))
(erase-buffer)
(setq i 1)
(insert
"(defun " func-name " ()\n"
" (let (")
(mapcar
'(lambda (arg)
(insert (format "(arg%d (read-string \"%s: \"))\n"
i (aref prompt (1- i))))
(setq i (1+ i)))
args)
(delete-region (point) (progn (forward-line -1) (end-of-line) (point)))
(insert ")\n(concat " (YaTeX-generate-lisp-quote string)
")))\n")
(indent-region (point-min) (point) nil)
used))
(defun YaTeX-generate-ask-match-position ()
"Ask user whether match-position is in his expectation,
Referencing variables in parent function YaTeX-generate-parse-add-in."
(pop-to-buffer YaTeX-generate-message-buffer)
(goto-char (point-max))
(insert "\n\n"
(format (if YaTeX-japan "%d 番目の引数 %s って"
"Is argument #%d's value `%s' also corresponding to")
i carg) "\n" add-in "\n")
(indent-to-column beg)
(let ((c beg))
(while (< c end) (insert "^") (setq c (1+ c))))
(insert "\n" (if YaTeX-japan "ここにも対応してるの?"
"this underlined part too?"))
(other-window -1)
(y-or-n-p (if YaTeX-japan "下線部はあってますか" "Is underline right")))
(defun YaTeX-generate-register-match ()
(nconc arg (list (list beg end)))
(let ((x beg))
(while (< x end) (aset used x i)(setq x (1+ x)))))
(defun YaTeX-generate-display-message (mes &optional bottom)
"Display message to generation buffer."
(pop-to-buffer YaTeX-generate-message-buffer)
(goto-char (point-max))
(insert "\n\n")
(if bottom (recenter (1- bottom)) (recenter 0))
(insert mes)
(other-window -1))
(defun YaTeX-generate-move-to-add-in-position ()
"Move cursor where add-in function should insert string."
(cond
((eq YaTeX-current-completion-type 'begin)
(goto-char (point-min))
(skip-chars-forward "^{")
(setq YaTeX-env-name
(buffer-substring (1+ (point))
(progn (skip-chars-forward "^}") (point))))
(forward-char 1))
((eq YaTeX-current-completion-type 'section)
(goto-char (point-min))
(skip-chars-forward "^{"))
((eq YaTeX-current-completion-type 'maketitle)
(goto-char (point-max))
(if (= (preceding-char) ? )
(forward-char -1)))))
(defun YaTeX-generate-function-name ()
(concat
"YaTeX:"
(cond
((eq YaTeX-current-completion-type 'begin) YaTeX-env-name)
((eq YaTeX-current-completion-type 'section) YaTeX-section-name)
((eq YaTeX-current-completion-type 'maketitle) YaTeX-single-command))))
(defun YaTeX-generate-lisp-quote (str)
(let ((len (length str))(i 0) (quote ""))
(while (< i len)
(if (= (aref str i) ?\\)
(setq quote (concat quote "\\")))
(if (= (aref str i) 127)
(setq quote (concat quote "\""))
(setq quote (concat quote (substring str i (1+ i)))))
(setq i (1+ i)))
quote))
(defun YaTeX-generate-quote-quote (str)
(let ((len (length str))(i 0) (quote ""))
(while (< i len)
(if (= (aref str i) ?\")
(setq quote (concat quote (char-to-string 127))))
(setq quote (concat quote (substring str i (1+ i))))
(setq i (1+ i)))
quote))
(defun YaTeX-suppress-sparse-keymap (map)
(let ((i ? ))
(while (< i 127)
(define-key map (char-to-string i) 'undefined)
(setq i (1+ i)))))
;;;
;; Auto-generate Function for Lispers.
;;;
(defun YaTeX-generate-read-completion-type (nth)
(message
"Read type(%d): (S)tring (C)omplete (F)ile ([)option (P)osition co(O)rd. (q)uit" nth)
(let ((c (read-char)))
(cond
((= c ?s) 'string)
((= c ?c) 'completion)
((= c ?f) 'file)
((= c ?\[) 'option)
((= c ?p) 'oneof)
((= c ?o) 'coord)
;;((= c ?m) 'macro)
(t 'quit))))
(defun YaTeX-generate-read-completion-table ()
(let ((i 1) cand (cands "(") (cb (current-buffer))
(buf (get-buffer-create " *Candidates*")))
(save-window-excursion
(save-excursion
(YaTeX-showup-buffer buf nil)
(set-buffer buf)
(erase-buffer)
(while (string<
""
(setq cand (read-string (format "Item[%d](RET to exit): " i))))
(setq cands (concat cands (format "(\"%s\")\n" cand))
i (1+ i))
(insert cand "\n"))
(kill-buffer buf)))
;;(set-buffer cb)
(setq YaTeX-generate-current-completion-table (concat cands ")"))))
(defun YaTeX-generate-corresponding-paren (left)
(cond
((equal left "{") "}")
((equal left "[") "]")
((equal left "(") ")")
((equal left "<") ">")
((equal left "\\begin{") "}")
(t left)))
(defun YaTeX-generate-create-read-string (&optional nth)
(concat
"(read-string \""
(read-string (if nth (format "Prompt for argument#%d: " nth) "Prompt: "))
": \"\n"
"\"" (read-string "Default: ") "\""
")\n"))
(defun YaTeX-generate-create-completing-read (&optional nth)
(prog1
(concat
"(completing-read \""
(read-string
(if nth (format "Prompt for argument#%d: " nth) "Prompt: "))
": \"\n"
(format "'%s\n" (YaTeX-generate-read-completion-table))
"nil "
(format "%s)" (y-or-n-p "Require match? ")))
(if nil ;;;(y-or-n-p "Do you need learning for this completion?")
(setq YaTeX-generate-variables-for-learning
(cons
(cons (format "YaTeX-%s-%d" command (or nth 0))
YaTeX-generate-current-completion-table)
YaTeX-generate-variables-for-learning)))))
(defun YaTeX-generate-create-read-file-name (&optional nth)
(concat
"(read-file-name \""
(read-string (if nth (format "Prompt for argument#%d: " nth) "Prompt: "))
": \" "" \"\" t \"\")\n"))
(defun YaTeX-generate-create-read-oneof (&optional nth readpos)
(concat
(if readpos
"(YaTeX:read-position \""
"(YaTeX:read-oneof \"")
(read-string "Acceptable characters: " "lcr") "\")\n"))
(defun YaTeX-generate-option-type (command)
(let ((func (format "YaTeX:%s" command)) leftp
(buf (get-buffer-create YaTeX-generate-buffer)) type (n 1))
(set-buffer buf)
(erase-buffer)
(insert "(defun " func " ()\n (concat\n")
(catch 'done
(while t
(setq type (YaTeX-generate-read-completion-type n))
(insert
(cond
;;Read string
((eq type 'string)
(concat "\"" (setq leftp (read-string "Left parenthesis: " "("))
"\"\n"
(YaTeX-generate-create-read-string)
"\"" (YaTeX-generate-corresponding-paren leftp) "\"")
)
;;Completing-read
((eq type 'completion)
(concat "\"" (setq leftp (read-string "Left parenthesis: " "{"))
"\"\n"
(YaTeX-generate-create-completing-read)
"\"" (YaTeX-generate-corresponding-paren leftp) "\"")
)
((eq type 'file)
(concat "\"" (setq leftp (read-string "Left parenthesis: " "("))
"\"\n"
(YaTeX-generate-create-read-file-name)
"\"" (YaTeX-generate-corresponding-paren leftp) "\"")
)
((eq type 'oneof)
(YaTeX-generate-create-read-oneof nil t)
)
((eq type 'option)
(concat "(let ((op (read-string \""
(read-string "Prompt: ")
": \")))\n"
"(if (string< \"\" op)\n"
" (concat \"[\" op \"]\")\n"
" \"\"))\n")
)
((eq type 'coord)
(concat "(YaTeX:read-coordinates \""
(read-string "Prompt for coordinates: ")
": \")\n")
)
((eq type 'macro)
(error "not yet supported")
)
(t (throw 'done t))))
(setq n (1+ n))))
(insert "))\n") ;close defun
(goto-char (point-min))
(while (not (eobp)) (lisp-indent-line) (forward-line 1))
(eval-current-buffer)
buf))
(defun YaTeX-generate-argument-type (command argc)
"Create an argument-type add-in function."
(interactive)
(let ((func (format "YaTeX::%s" command)) (argp 1)
(cb (current-buffer))
(buf (get-buffer-create YaTeX-generate-buffer)))
(set-buffer buf)
(erase-buffer)
(insert "(defun " func " (&optional argp)\n(cond\n")
(while (<= argp argc)
(insert (format "((equal argp %d)\n" argp))
(setq type (YaTeX-generate-read-completion-type argp))
(insert
(cond
((eq type 'string)
(concat (YaTeX-generate-create-read-string argp)))
((eq type 'completion)
(concat (YaTeX-generate-create-completing-read argp)))
((eq type 'oneof)
(YaTeX-generate-create-read-oneof))
((eq type 'file)
(concat (YaTeX-generate-create-read-file-name argp)))
(t ""))
")\n")
(setq argp (1+ argp)))
(insert "))\n")
(goto-char (point-min))
(while (not (eobp)) (lisp-indent-line) (forward-line 1))
(eval-current-buffer)
(set-buffer cb)
(YaTeX-update-table
(if (> argc 1) (list command argc) (list command))
'section-table 'user-section-table 'tmp-section-table)
buf))
(defun YaTeX-generate-simple (&optional command)
"Simple but requiring some elisp knowledge add-in generator."
(interactive)
(setq YaTeX-generate-variables-for-learning nil)
(or command
(setq command
(completing-read
(format
"Making add-in function for (default %s): " YaTeX-section-name)
(append
section-table user-section-table tmp-section-table
env-table user-env-table tmp-env-table
singlecmd-table user-singlecmd-table tmp-singlecmd-table)
nil nil)
command (if (string= "" command) YaTeX-section-name command)))
(message
(cond
(YaTeX-japan "(o)追加型? (a)引数型? (yatexadd.docを参照のこと) :")
(t "(O)ption? (A)rgument?")))
(YaTeX-showup-buffer
(if (= (read-char) ?o)
(YaTeX-generate-option-type command)
(YaTeX-generate-argument-type
command
(string-to-int (read-string "How many arguments?: ")))) nil))
(provide 'yatexgen)