sekka 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING CHANGED
@@ -43,7 +43,7 @@ Copyright and condition of use of main portion of the source:
43
43
 
44
44
  Copyright of emacs/*.el ---------------------------------------------------
45
45
 
46
- This file is covered by GPL version 2
46
+ This file is covered by GPL version 2 or 3
47
47
 
48
48
  Copyright of data/SKK-JISYO.* -----------------------------------------------
49
49
 
@@ -4,6 +4,7 @@
4
4
  require 'digest/md5'
5
5
  require 'fileutils'
6
6
  require 'rack'
7
+ require 'uri'
7
8
  require File.expand_path(File.dirname(__FILE__) + "/../lib/sekkaconfig")
8
9
  require File.expand_path(File.dirname(__FILE__) + "/../lib/sekka/sekkaversion")
9
10
 
@@ -12,6 +13,8 @@ require File.expand_path(File.dirname(__FILE__) + "/../lib/sekka/sekkaversion")
12
13
  DICTDIR = File.expand_path( "~/.sekka-server" )
13
14
  DICTURL = "http://sumibi.org/sekka/dict/" + SekkaVersion.version
14
15
 
16
+ PIDFILE = DICTDIR + "/pid"
17
+
15
18
  TC_FILE = DICTDIR + "/SEKKA-JISYO.SMALL.tch"
16
19
  SUMFILE = DICTDIR + "/SEKKA-JISYO.SMALL.md5"
17
20
  TC_URL = DICTURL + "/SEKKA-JISYO.SMALL.tch"
@@ -30,6 +33,20 @@ def main
30
33
  STDERR.printf( "Info: created directory [%s]\n", DICTDIR )
31
34
  end
32
35
 
36
+ # sekka-server自身のpidを書きこむ(デーモン化したときの停止用)
37
+ open( PIDFILE, "w" ) {|f|
38
+ f.printf( "%d\n", Process.pid )
39
+ }
40
+
41
+ # 環境変数からHTTPプロキシサーバーの情報を取得する
42
+ proxyHost = nil
43
+ proxyPort = nil
44
+ if ENV.key?( 'http_proxy' )
45
+ uri = URI.parse ENV[ 'http_proxy' ]
46
+ proxyPort = uri.port
47
+ proxyHost = uri.host
48
+ end
49
+
33
50
  if not File.exist?( TC_FILE )
34
51
  STDERR.printf( "Info: Downloading SEKKA-JISYO\n" )
35
52
  # 辞書をダウンロードする
@@ -64,7 +81,7 @@ def main
64
81
  list = TC_FILE_LIST.select { |name| File.exist?( name ) }
65
82
 
66
83
  # 設定項目をConfigオブジェクトに代入
67
- SekkaServer::Config.setup( list[0], MEMCACHED, 12929 )
84
+ SekkaServer::Config.setup( list[0], MEMCACHED, 12929, proxyHost, proxyPort )
68
85
 
69
86
  # サーバースクリプトのrootディレクトリへ移動
70
87
  FileUtils.cd(File.dirname(__FILE__) + "/../")
@@ -0,0 +1,1061 @@
1
+ ;;; popup.el --- Visual popup interface
2
+
3
+ ;; Copyright (C) 2009, 2010 Tomohiro Matsuyama
4
+
5
+ ;; Author: Tomohiro Matsuyama <tomo@cx4a.org>
6
+ ;; Keywords: lisp
7
+ ;; Version: 0.4
8
+
9
+ ;; This program is free software; you can redistribute it and/or modify
10
+ ;; it under the terms of the GNU General Public License as published by
11
+ ;; the Free Software Foundation, either version 3 of the License, or
12
+ ;; (at your option) any later version.
13
+
14
+ ;; This program is distributed in the hope that it will be useful,
15
+ ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ ;; GNU General Public License for more details.
18
+
19
+ ;; You should have received a copy of the GNU General Public License
20
+ ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ ;;; Commentary:
23
+
24
+ ;;
25
+
26
+ ;;; Code:
27
+
28
+ (eval-when-compile
29
+ (require 'cl))
30
+
31
+
32
+
33
+ ;; Utilities
34
+
35
+ (defvar popup-use-optimized-column-computation t
36
+ "Use optimized column computation routine.
37
+ If there is a problem, please set it to nil.")
38
+
39
+ ;; Borrowed from anything.el
40
+ (defmacro popup-aif (test-form then-form &rest else-forms)
41
+ "Anaphoric if. Temporary variable `it' is the result of test-form."
42
+ (declare (indent 2))
43
+ `(let ((it ,test-form))
44
+ (if it ,then-form ,@else-forms)))
45
+
46
+ (defun popup-x-to-string (x)
47
+ "Convert any object to string effeciently.
48
+ This is faster than prin1-to-string in many cases."
49
+ (typecase x
50
+ (string x)
51
+ (symbol (symbol-name x))
52
+ (integer (number-to-string x))
53
+ (float (number-to-string x))
54
+ (t (format "%s" x))))
55
+
56
+ (defun popup-substring-by-width (string width)
57
+ "Return cons of substring and remaining string by `WIDTH'."
58
+ ;; Expand tabs with 4 spaces
59
+ (setq string (replace-regexp-in-string "\t" " " string))
60
+ (loop with len = (length string)
61
+ with w = 0
62
+ for l from 0
63
+ for c in (append string nil)
64
+ while (<= (incf w (char-width c)) width)
65
+ finally return
66
+ (if (< l len)
67
+ (cons (substring string 0 l) (substring string l))
68
+ (list string))))
69
+
70
+ (defun popup-fill-string (string &optional width max-width justify squeeze)
71
+ "Split STRING into fixed width strings and return a cons cell like
72
+ \(WIDTH . ROWS). Here, the car WIDTH indicates the actual maxim width of ROWS.
73
+
74
+ The argument WIDTH specifies the width of filling each paragraph. WIDTH nil
75
+ means don't perform any justification and word wrap. Note that this function
76
+ doesn't add any padding characters at the end of each row.
77
+
78
+ MAX-WIDTH, if WIDTH is nil, specifies the maximum number of columns.
79
+
80
+ The optional fourth argument JUSTIFY specifies which kind of justification
81
+ to do: `full', `left', `right', `center', or `none' (equivalent to nil).
82
+ A value of t means handle each paragraph as specified by its text properties.
83
+
84
+ SQUEEZE nil means leave whitespaces other than line breaks untouched."
85
+ (if (eq width 0)
86
+ (error "Can't fill string with 0 width"))
87
+ (if width
88
+ (setq max-width width))
89
+ (with-temp-buffer
90
+ (let ((tab-width 4)
91
+ (fill-column width)
92
+ (left-margin 0)
93
+ (kinsoku-limit 1)
94
+ indent-tabs-mode
95
+ row rows)
96
+ (insert string)
97
+ (untabify (point-min) (point-max))
98
+ (if width
99
+ (fill-region (point-min) (point-max) justify (not squeeze)))
100
+ (goto-char (point-min))
101
+ (setq width 0)
102
+ (while (prog2
103
+ (let ((line (buffer-substring
104
+ (point) (progn (end-of-line) (point)))))
105
+ (if max-width
106
+ (while (progn
107
+ (setq row (truncate-string-to-width line max-width)
108
+ width (max width (string-width row)))
109
+ (push row rows)
110
+ (if (not (= (length row) (length line)))
111
+ (setq line (substring line (length row))))))
112
+ (setq width (max width (string-width line)))
113
+ (push line rows)))
114
+ (< (point) (point-max))
115
+ (beginning-of-line 2)))
116
+ (cons width (nreverse rows)))))
117
+
118
+ (defmacro popup-save-buffer-state (&rest body)
119
+ (declare (indent 0))
120
+ `(save-excursion
121
+ (let ((buffer-undo-list t)
122
+ (buffer-read-only nil)
123
+ (modified (buffer-modified-p)))
124
+ (unwind-protect
125
+ (progn ,@body)
126
+ (set-buffer-modified-p modified)))))
127
+
128
+ (defun popup-preferred-width (list)
129
+ "Return preferred width of popup to show `LIST' beautifully."
130
+ (loop with tab-width = 4
131
+ for item in list
132
+ for summary = (popup-item-summary item)
133
+ maximize (string-width (popup-x-to-string item)) into width
134
+ if (stringp summary)
135
+ maximize (+ (string-width summary) 2) into summary-width
136
+ finally return (* (ceiling (/ (+ (or width 0) (or summary-width 0)) 10.0)) 10)))
137
+
138
+ ;; window-full-width-p is not defined in Emacs 22.1
139
+ (defun popup-window-full-width-p (&optional window)
140
+ (if (fboundp 'window-full-width-p)
141
+ (window-full-width-p window)
142
+ (= (window-width window) (frame-width (window-frame (or window (selected-window)))))))
143
+
144
+ ;; truncated-partial-width-window-p is not defined in Emacs 22
145
+ (defun popup-truncated-partial-width-window-p (&optional window)
146
+ (unless window
147
+ (setq window (selected-window)))
148
+ (unless (popup-window-full-width-p window)
149
+ (let ((t-p-w-w (buffer-local-value 'truncate-partial-width-windows
150
+ (window-buffer window))))
151
+ (if (integerp t-p-w-w)
152
+ (< (window-width window) t-p-w-w)
153
+ t-p-w-w))))
154
+
155
+ (defun popup-current-physical-column ()
156
+ (or (when (and popup-use-optimized-column-computation
157
+ (eq (window-hscroll) 0))
158
+ (let ((current-column (current-column)))
159
+ (if (or (popup-truncated-partial-width-window-p)
160
+ truncate-lines
161
+ (< current-column (window-width)))
162
+ current-column)))
163
+ (car (posn-col-row (posn-at-point)))))
164
+
165
+ (defun popup-last-line-of-buffer-p ()
166
+ (save-excursion (end-of-line) (/= (forward-line) 0)))
167
+
168
+ (defun popup-lookup-key-by-event (function event)
169
+ (or (funcall function (vector event))
170
+ (if (symbolp event)
171
+ (popup-aif (get event 'event-symbol-element-mask)
172
+ (funcall function (vector (logior (or (get (car it) 'ascii-character) 0)
173
+ (cadr it))))))))
174
+
175
+
176
+
177
+ ;; Popup common
178
+
179
+ (defgroup popup nil
180
+ "Visual popup interface"
181
+ :group 'lisp
182
+ :prefix "popup-")
183
+
184
+ (defface popup-face
185
+ '((t (:background "lightgray" :foreground "black")))
186
+ "Face for popup."
187
+ :group 'popup)
188
+
189
+ (defface popup-scroll-bar-foreground-face
190
+ '((t (:background "black")))
191
+ "Foreground face for scroll-bar."
192
+ :group 'popup)
193
+
194
+ (defface popup-scroll-bar-background-face
195
+ '((t (:background "gray")))
196
+ "Background face for scroll-bar."
197
+ :group 'popup)
198
+
199
+ (defvar popup-instances nil
200
+ "Popup instances.")
201
+
202
+ (defvar popup-scroll-bar-foreground-char
203
+ (propertize " " 'face 'popup-scroll-bar-foreground-face)
204
+ "Foreground character for scroll-bar.")
205
+
206
+ (defvar popup-scroll-bar-background-char
207
+ (propertize " " 'face 'popup-scroll-bar-background-face)
208
+ "Background character for scroll-bar.")
209
+
210
+ (defstruct popup
211
+ point row column width height min-height direction overlays
212
+ parent depth
213
+ face selection-face
214
+ margin-left margin-right margin-left-cancel scroll-bar symbol
215
+ cursor offset scroll-top current-height list newlines
216
+ pattern original-list)
217
+
218
+ (defun popup-item-propertize (item &rest properties)
219
+ "Same to `propertize` but this avoids overriding existed value with `nil` property."
220
+ (let (props)
221
+ (while properties
222
+ (when (cadr properties)
223
+ (push (car properties) props)
224
+ (push (cadr properties) props))
225
+ (setq properties (cddr properties)))
226
+ (apply 'propertize
227
+ (popup-x-to-string item)
228
+ (nreverse props))))
229
+
230
+ (defun popup-item-property (item property)
231
+ (if (stringp item)
232
+ (get-text-property 0 property item)))
233
+
234
+ (defun* popup-make-item (name
235
+ &key
236
+ value
237
+ popup-face
238
+ selection-face
239
+ sublist
240
+ document
241
+ symbol
242
+ summary)
243
+ "Utility function to make popup item.
244
+ See also `popup-item-propertize'."
245
+ (popup-item-propertize name
246
+ 'value value
247
+ 'popup-face popup-face
248
+ 'selection-face selection-face
249
+ 'document document
250
+ 'symbol symbol
251
+ 'summary summary
252
+ 'sublist sublist))
253
+
254
+ (defsubst popup-item-value (item) (popup-item-property item 'value))
255
+ (defsubst popup-item-value-or-self (item) (or (popup-item-value item) item))
256
+ (defsubst popup-item-popup-face (item) (popup-item-property item 'popup-face))
257
+ (defsubst popup-item-selection-face (item) (popup-item-property item 'selection-face))
258
+ (defsubst popup-item-document (item) (popup-item-property item 'document))
259
+ (defsubst popup-item-summary (item) (popup-item-property item 'summary))
260
+ (defsubst popup-item-symbol (item) (popup-item-property item 'symbol))
261
+ (defsubst popup-item-sublist (item) (popup-item-property item 'sublist))
262
+
263
+ (defun popup-item-documentation (item)
264
+ (let ((doc (popup-item-document item)))
265
+ (if (functionp doc)
266
+ (setq doc (funcall doc (popup-item-value-or-self item))))
267
+ doc))
268
+
269
+ (defun popup-item-show-help-1 (item)
270
+ (let ((doc (popup-item-documentation item)))
271
+ (when doc
272
+ (with-current-buffer (get-buffer-create " *Popup Help*")
273
+ (erase-buffer)
274
+ (insert doc)
275
+ (goto-char (point-min))
276
+ (display-buffer (current-buffer)))
277
+ t)))
278
+
279
+ (defun popup-item-show-help (item &optional persist)
280
+ (when item
281
+ (if (not persist)
282
+ (save-window-excursion
283
+ (when (popup-item-show-help-1 item)
284
+ (block nil
285
+ (while t
286
+ (clear-this-command-keys)
287
+ (let ((key (read-key-sequence-vector nil)))
288
+ (case (key-binding key)
289
+ ('scroll-other-window
290
+ (scroll-other-window))
291
+ ('scroll-other-window-down
292
+ (scroll-other-window-down nil))
293
+ (t
294
+ (setq unread-command-events (append key unread-command-events))
295
+ (return))))))))
296
+ (popup-item-show-help-1 item))))
297
+
298
+ (defun popup-set-list (popup list)
299
+ (popup-set-filtered-list popup list)
300
+ (setf (popup-pattern popup) nil)
301
+ (setf (popup-original-list popup) list))
302
+
303
+ (defun popup-set-filtered-list (popup list)
304
+ (setf (popup-list popup) list
305
+ (popup-offset popup) (if (> (popup-direction popup) 0)
306
+ 0
307
+ (max (- (popup-height popup) (length list)) 0))))
308
+
309
+ (defun popup-selected-item (popup)
310
+ (nth (popup-cursor popup) (popup-list popup)))
311
+
312
+ (defun popup-selected-line (popup)
313
+ (- (popup-cursor popup) (popup-scroll-top popup)))
314
+
315
+ (defun popup-line-overlay (popup line)
316
+ (aref (popup-overlays popup) line))
317
+
318
+ (defun popup-selected-line-overlay (popup)
319
+ (popup-line-overlay popup (popup-selected-line popup)))
320
+
321
+ (defun popup-hide-line (popup line)
322
+ (let ((overlay (popup-line-overlay popup line)))
323
+ (overlay-put overlay 'display nil)
324
+ (overlay-put overlay 'after-string nil)))
325
+
326
+ (defun popup-line-hidden-p (popup line)
327
+ (let ((overlay (popup-line-overlay popup line)))
328
+ (and (eq (overlay-get overlay 'display) nil)
329
+ (eq (overlay-get overlay 'after-string) nil))))
330
+
331
+ (defun popup-set-line-item (popup line item face margin-left margin-right scroll-bar-char symbol summary)
332
+ (let* ((overlay (popup-line-overlay popup line))
333
+ (content (popup-create-line-string popup (popup-x-to-string item) margin-left margin-right symbol summary))
334
+ (start 0)
335
+ (prefix (overlay-get overlay 'prefix))
336
+ (postfix (overlay-get overlay 'postfix))
337
+ end)
338
+ ;; Overlap face properties
339
+ (if (get-text-property start 'face content)
340
+ (setq start (next-single-property-change start 'face content)))
341
+ (while (and start (setq end (next-single-property-change start 'face content)))
342
+ (put-text-property start end 'face face content)
343
+ (setq start (next-single-property-change end 'face content)))
344
+ (if start
345
+ (put-text-property start (length content) 'face face content))
346
+ (unless (overlay-get overlay 'dangle)
347
+ (overlay-put overlay 'display (concat prefix (substring content 0 1)))
348
+ (setq prefix nil
349
+ content (concat (substring content 1))))
350
+ (overlay-put overlay
351
+ 'after-string
352
+ (concat prefix
353
+ content
354
+ scroll-bar-char
355
+ postfix))))
356
+
357
+ (defun popup-create-line-string (popup string margin-left margin-right symbol summary)
358
+ (let* ((popup-width (popup-width popup))
359
+ (summary-width (string-width summary))
360
+ (string (car (popup-substring-by-width string
361
+ (- popup-width
362
+ (if (> summary-width 0)
363
+ (+ summary-width 2)
364
+ 0)))))
365
+ (string-width (string-width string)))
366
+ (concat margin-left
367
+ string
368
+ (make-string (max (- popup-width string-width summary-width) 0) ? )
369
+ summary
370
+ symbol
371
+ margin-right)))
372
+
373
+ (defun popup-live-p (popup)
374
+ (and popup (popup-overlays popup) t))
375
+
376
+ (defun popup-child-point (popup &optional offset)
377
+ (overlay-end (popup-line-overlay popup
378
+ (or offset
379
+ (popup-selected-line popup)))))
380
+
381
+ (defun* popup-create (point
382
+ width
383
+ height
384
+ &key
385
+ min-height
386
+ around
387
+ (face 'popup-face)
388
+ (selection-face face)
389
+ scroll-bar
390
+ margin-left
391
+ margin-right
392
+ symbol
393
+ parent
394
+ parent-offset)
395
+ (or margin-left (setq margin-left 0))
396
+ (or margin-right (setq margin-right 0))
397
+ (unless point
398
+ (setq point
399
+ (if parent (popup-child-point parent parent-offset) (point))))
400
+
401
+ (save-excursion
402
+ (goto-char point)
403
+ (let* ((row (line-number-at-pos))
404
+ (column (popup-current-physical-column))
405
+ (overlays (make-vector height nil))
406
+ (popup-width (+ width
407
+ (if scroll-bar 1 0)
408
+ margin-left
409
+ margin-right
410
+ (if symbol 2 0)))
411
+ margin-left-cancel
412
+ (window (selected-window))
413
+ (window-start (window-start))
414
+ (window-hscroll (window-hscroll))
415
+ (window-width (window-width))
416
+ (right (+ column popup-width))
417
+ (overflow (and (> right window-width)
418
+ (>= right popup-width)))
419
+ (foldable (and (null parent)
420
+ (>= column popup-width)))
421
+ (direction (or
422
+ ;; Currently the direction of cascade popup won't be changed
423
+ (and parent (popup-direction parent))
424
+
425
+ ;; Calculate direction
426
+ (if (and (> row height)
427
+ (> height (- (max 1 (- (window-height)
428
+ (if mode-line-format 1 0)
429
+ (if header-line-format 1 0)))
430
+ (count-lines window-start (point)))))
431
+ -1
432
+ 1)))
433
+ (depth (if parent (1+ (popup-depth parent)) 0))
434
+ (newlines (max 0 (+ (- height (count-lines point (point-max))) (if around 1 0))))
435
+ current-column)
436
+ (when (> newlines 0)
437
+ (popup-save-buffer-state
438
+ (goto-char (point-max))
439
+ (insert (make-string newlines ?\n))))
440
+
441
+ (if overflow
442
+ (if foldable
443
+ (progn
444
+ (decf column (- popup-width margin-left margin-right))
445
+ (unless around (move-to-column column)))
446
+ (when (not truncate-lines)
447
+ ;; Cut out overflow
448
+ (let ((d (1+ (- popup-width (- window-width column)))))
449
+ (decf popup-width d)
450
+ (decf width d)))
451
+ (decf column margin-left))
452
+ (decf column margin-left))
453
+ (when (and (null parent)
454
+ (< column 0))
455
+ ;; Cancel margin left
456
+ (setq column 0)
457
+ (decf popup-width margin-left)
458
+ (setq margin-left-cancel t))
459
+
460
+ (dotimes (i height)
461
+ (let (overlay begin w (dangle t) (prefix "") (postfix ""))
462
+ (when around
463
+ (if (>= emacs-major-version 23)
464
+ (vertical-motion (cons column direction))
465
+ (vertical-motion direction)
466
+ (move-to-column (+ (current-column) column))))
467
+ (setq around t
468
+ current-column (popup-current-physical-column))
469
+
470
+ (when (> current-column column)
471
+ (backward-char)
472
+ (setq current-column (popup-current-physical-column)))
473
+ (when (< current-column column)
474
+ ;; Extend short buffer lines by popup prefix (line of spaces)
475
+ (setq prefix (make-string (+ (if (= current-column 0)
476
+ (- window-hscroll (current-column))
477
+ 0)
478
+ (- column current-column))
479
+ ? )))
480
+
481
+ (setq begin (point))
482
+ (setq w (+ popup-width (length prefix)))
483
+ (while (and (not (eolp)) (> w 0))
484
+ (setq dangle nil)
485
+ (decf w (char-width (char-after)))
486
+ (forward-char))
487
+ (if (< w 0)
488
+ (setq postfix (make-string (- w) ? )))
489
+
490
+ (setq overlay (make-overlay begin (point)))
491
+ (overlay-put overlay 'window window)
492
+ (overlay-put overlay 'dangle dangle)
493
+ (overlay-put overlay 'prefix prefix)
494
+ (overlay-put overlay 'postfix postfix)
495
+ (overlay-put overlay 'width width)
496
+ (aset overlays
497
+ (if (> direction 0) i (- height i 1))
498
+ overlay)))
499
+ (loop for p from (- 10000 (* depth 1000))
500
+ for overlay in (nreverse (append overlays nil))
501
+ do (overlay-put overlay 'priority p))
502
+ (let ((it (make-popup :point point
503
+ :row row
504
+ :column column
505
+ :width width
506
+ :height height
507
+ :min-height min-height
508
+ :direction direction
509
+ :parent parent
510
+ :depth depth
511
+ :face face
512
+ :selection-face selection-face
513
+ :margin-left margin-left
514
+ :margin-right margin-right
515
+ :margin-left-cancel margin-left-cancel
516
+ :scroll-bar scroll-bar
517
+ :symbol symbol
518
+ :cursor 0
519
+ :scroll-top 0
520
+ :current-height 0
521
+ :list nil
522
+ :newlines newlines
523
+ :overlays overlays)))
524
+ (push it popup-instances)
525
+ it))))
526
+
527
+ (defun popup-delete (popup)
528
+ (when (popup-live-p popup)
529
+ (popup-hide popup)
530
+ (mapc 'delete-overlay (popup-overlays popup))
531
+ (setf (popup-overlays popup) nil)
532
+ (setq popup-instances (delq popup popup-instances))
533
+ (let ((newlines (popup-newlines popup)))
534
+ (when (> newlines 0)
535
+ (popup-save-buffer-state
536
+ (goto-char (point-max))
537
+ (dotimes (i newlines)
538
+ (if (= (char-before) ?\n)
539
+ (delete-char -1)))))))
540
+ nil)
541
+
542
+ (defun popup-draw (popup)
543
+ (loop with height = (popup-height popup)
544
+ with min-height = (popup-min-height popup)
545
+ with popup-face = (popup-face popup)
546
+ with selection-face = (popup-selection-face popup)
547
+ with list = (popup-list popup)
548
+ with length = (length list)
549
+ with thum-size = (max (/ (* height height) (max length 1)) 1)
550
+ with page-size = (/ (+ 0.0 (max length 1)) height)
551
+ with scroll-bar = (popup-scroll-bar popup)
552
+ with margin-left = (make-string (if (popup-margin-left-cancel popup) 0 (popup-margin-left popup)) ? )
553
+ with margin-right = (make-string (popup-margin-right popup) ? )
554
+ with symbol = (popup-symbol popup)
555
+ with cursor = (popup-cursor popup)
556
+ with scroll-top = (popup-scroll-top popup)
557
+ with offset = (popup-offset popup)
558
+ for o from offset
559
+ for i from scroll-top
560
+ while (< o height)
561
+ for item in (nthcdr scroll-top list)
562
+ for page-index = (* thum-size (/ o thum-size))
563
+ for face = (if (= i cursor)
564
+ (or (popup-item-selection-face item) selection-face)
565
+ (or (popup-item-popup-face item) popup-face))
566
+ for empty-char = (propertize " " 'face face)
567
+ for scroll-bar-char = (if scroll-bar
568
+ (cond
569
+ ((<= page-size 1)
570
+ empty-char)
571
+ ((and (> page-size 1)
572
+ (>= cursor (* page-index page-size))
573
+ (< cursor (* (+ page-index thum-size) page-size)))
574
+ popup-scroll-bar-foreground-char)
575
+ (t
576
+ popup-scroll-bar-background-char))
577
+ "")
578
+ for sym = (if symbol
579
+ (concat " " (or (popup-item-symbol item) " "))
580
+ "")
581
+ for summary = (or (popup-item-summary item) "")
582
+
583
+ do
584
+ ;; Show line and set item to the line
585
+ (popup-set-line-item popup o item face margin-left margin-right scroll-bar-char sym summary)
586
+
587
+ finally
588
+ ;; Remember current height
589
+ (setf (popup-current-height popup) (- o offset))
590
+
591
+ ;; Hide remaining lines
592
+ (let ((scroll-bar-char (if scroll-bar (propertize " " 'face popup-face) ""))
593
+ (symbol (if symbol " " "")))
594
+ (if (> (popup-direction popup) 0)
595
+ (progn
596
+ (when min-height
597
+ (while (< o min-height)
598
+ (popup-set-line-item popup o "" popup-face margin-left margin-right scroll-bar-char symbol "")
599
+ (incf o)))
600
+ (while (< o height)
601
+ (popup-hide-line popup o)
602
+ (incf o)))
603
+ (loop with h = (if min-height (- height min-height) offset)
604
+ for o from 0 below offset
605
+ if (< o h)
606
+ do (popup-hide-line popup o)
607
+ if (>= o h)
608
+ do (popup-set-line-item popup o "" popup-face margin-left margin-right scroll-bar-char symbol ""))))))
609
+
610
+ (defun popup-hide (popup)
611
+ (dotimes (i (popup-height popup))
612
+ (popup-hide-line popup i)))
613
+
614
+ (defun popup-hidden-p (popup)
615
+ (let ((hidden t))
616
+ (when (popup-live-p popup)
617
+ (dotimes (i (popup-height popup))
618
+ (unless (popup-line-hidden-p popup i)
619
+ (setq hidden nil))))
620
+ hidden))
621
+
622
+ (defun popup-select (popup i)
623
+ (setq i (+ i (popup-offset popup)))
624
+ (when (and (<= 0 i) (< i (popup-height popup)))
625
+ (setf (popup-cursor popup) i)
626
+ (popup-draw popup)
627
+ t))
628
+
629
+ (defun popup-next (popup)
630
+ (let ((height (popup-height popup))
631
+ (cursor (1+ (popup-cursor popup)))
632
+ (scroll-top (popup-scroll-top popup))
633
+ (length (length (popup-list popup))))
634
+ (cond
635
+ ((>= cursor length)
636
+ ;; Back to first page
637
+ (setq cursor 0
638
+ scroll-top 0))
639
+ ((= cursor (+ scroll-top height))
640
+ ;; Go to next page
641
+ (setq scroll-top (min (1+ scroll-top) (max (- length height) 0)))))
642
+ (setf (popup-cursor popup) cursor
643
+ (popup-scroll-top popup) scroll-top)
644
+ (popup-draw popup)))
645
+
646
+ (defun popup-previous (popup)
647
+ (let ((height (popup-height popup))
648
+ (cursor (1- (popup-cursor popup)))
649
+ (scroll-top (popup-scroll-top popup))
650
+ (length (length (popup-list popup))))
651
+ (cond
652
+ ((< cursor 0)
653
+ ;; Go to last page
654
+ (setq cursor (1- length)
655
+ scroll-top (max (- length height) 0)))
656
+ ((= cursor (1- scroll-top))
657
+ ;; Go to previous page
658
+ (decf scroll-top)))
659
+ (setf (popup-cursor popup) cursor
660
+ (popup-scroll-top popup) scroll-top)
661
+ (popup-draw popup)))
662
+
663
+ (defun popup-scroll-down (popup &optional n)
664
+ (let ((scroll-top (min (+ (popup-scroll-top popup) (or n 1))
665
+ (- (length (popup-list popup)) (popup-height popup)))))
666
+ (setf (popup-cursor popup) scroll-top
667
+ (popup-scroll-top popup) scroll-top)
668
+ (popup-draw popup)))
669
+
670
+ (defun popup-scroll-up (popup &optional n)
671
+ (let ((scroll-top (max (- (popup-scroll-top popup) (or n 1))
672
+ 0)))
673
+ (setf (popup-cursor popup) scroll-top
674
+ (popup-scroll-top popup) scroll-top)
675
+ (popup-draw popup)))
676
+
677
+
678
+
679
+ ;; Popup isearch
680
+
681
+ (defface popup-isearch-match
682
+ '((t (:background "sky blue")))
683
+ "Popup isearch match face."
684
+ :group 'popup)
685
+
686
+ (defvar popup-isearch-cursor-color "blue")
687
+
688
+ (defvar popup-isearch-keymap
689
+ (let ((map (make-sparse-keymap)))
690
+ ;(define-key map "\r" 'popup-isearch-done)
691
+ (define-key map "\C-g" 'popup-isearch-cancel)
692
+ (define-key map "\C-h" 'popup-isearch-delete)
693
+ (define-key map (kbd "DEL") 'popup-isearch-delete)
694
+ map))
695
+
696
+ (defsubst popup-isearch-char-p (char)
697
+ (and (integerp char)
698
+ (<= 32 char)
699
+ (<= char 126)))
700
+
701
+ (defun popup-isearch-filter-list (pattern list)
702
+ (loop with regexp = (regexp-quote pattern)
703
+ for item in list
704
+ do
705
+ (unless (stringp item)
706
+ (setq item (popup-item-propertize (popup-x-to-string item)
707
+ 'value item)))
708
+ if (string-match regexp item)
709
+ collect (let ((beg (match-beginning 0))
710
+ (end (match-end 0)))
711
+ (alter-text-property 0 (length item) 'face
712
+ (lambda (prop)
713
+ (unless (eq prop 'popup-isearch-match)
714
+ prop))
715
+ item)
716
+ (put-text-property beg end
717
+ 'face 'popup-isearch-match
718
+ item)
719
+ item)))
720
+
721
+ (defun popup-isearch-prompt (popup pattern)
722
+ (format "Pattern: %s" (if (= (length (popup-list popup)) 0)
723
+ (propertize pattern 'face 'isearch-fail)
724
+ pattern)))
725
+
726
+ (defun popup-isearch-update (popup pattern &optional callback)
727
+ (setf (popup-cursor popup) 0
728
+ (popup-scroll-top popup) 0
729
+ (popup-pattern popup) pattern)
730
+ (let ((list (popup-isearch-filter-list pattern (popup-original-list popup))))
731
+ (popup-set-filtered-list popup list)
732
+ (if callback
733
+ (funcall callback list)))
734
+ (popup-draw popup))
735
+
736
+ (defun* popup-isearch (popup
737
+ &key
738
+ (cursor-color popup-isearch-cursor-color)
739
+ (keymap popup-isearch-keymap)
740
+ callback
741
+ help-delay)
742
+ (let ((list (popup-original-list popup))
743
+ (pattern (or (popup-pattern popup) ""))
744
+ (old-cursor-color (frame-parameter (selected-frame) 'cursor-color))
745
+ prompt key binding done)
746
+ (unwind-protect
747
+ (unless (block nil
748
+ (if cursor-color
749
+ (set-cursor-color cursor-color))
750
+ (while t
751
+ (setq prompt (popup-isearch-prompt popup pattern))
752
+ (setq key (popup-menu-read-key-sequence keymap prompt help-delay))
753
+ (if (null key)
754
+ (unless (funcall popup-menu-show-quick-help-function popup nil :prompt prompt)
755
+ (clear-this-command-keys)
756
+ (push (read-event prompt) unread-command-events))
757
+ (setq binding (lookup-key keymap key))
758
+ (cond
759
+ ((and (stringp key)
760
+ (popup-isearch-char-p (aref key 0)))
761
+ (setq pattern (concat pattern key)))
762
+ ((eq binding 'popup-isearch-done)
763
+ (return t))
764
+ ((eq binding 'popup-isearch-cancel)
765
+ (return nil))
766
+ ((eq binding 'popup-isearch-delete)
767
+ (if (> (length pattern) 0)
768
+ (setq pattern (substring pattern 0 (1- (length pattern))))))
769
+ (t
770
+ (setq unread-command-events
771
+ (append (listify-key-sequence key) unread-command-events))
772
+ (return t)))
773
+ (popup-isearch-update popup pattern callback))))
774
+ (popup-isearch-update popup "" callback)
775
+ t) ; Return non-nil if isearch is cancelled
776
+ (if old-cursor-color
777
+ (set-cursor-color old-cursor-color)))))
778
+
779
+
780
+
781
+ ;; Popup tip
782
+
783
+ (defface popup-tip-face
784
+ '((t (:background "khaki1" :foreground "black")))
785
+ "Face for popup tip."
786
+ :group 'popup)
787
+
788
+ (defvar popup-tip-max-width 80)
789
+
790
+ (defun* popup-tip (string
791
+ &key
792
+ point
793
+ (around t)
794
+ width
795
+ (height 15)
796
+ min-height
797
+ truncate
798
+ margin
799
+ margin-left
800
+ margin-right
801
+ scroll-bar
802
+ parent
803
+ parent-offset
804
+ nowait
805
+ prompt
806
+ &aux tip lines)
807
+ (if (bufferp string)
808
+ (setq string (with-current-buffer string (buffer-string))))
809
+ ;; TODO strip text (mainly face) properties
810
+ (setq string (substring-no-properties string))
811
+
812
+ (and (eq margin t) (setq margin 1))
813
+ (or margin-left (setq margin-left margin))
814
+ (or margin-right (setq margin-right margin))
815
+
816
+ (let ((it (popup-fill-string string width popup-tip-max-width)))
817
+ (setq width (car it)
818
+ lines (cdr it)))
819
+
820
+ (setq tip (popup-create point width height
821
+ :min-height min-height
822
+ :around around
823
+ :margin-left margin-left
824
+ :margin-right margin-right
825
+ :scroll-bar scroll-bar
826
+ :face 'popup-tip-face
827
+ :parent parent
828
+ :parent-offset parent-offset))
829
+
830
+ (unwind-protect
831
+ (when (> (popup-width tip) 0) ; not to be corrupted
832
+ (when (and (not (eq width (popup-width tip))) ; truncated
833
+ (not truncate))
834
+ ;; Refill once again to lines be fitted to popup width
835
+ (setq width (popup-width tip))
836
+ (setq lines (cdr (popup-fill-string string width width))))
837
+
838
+ (popup-set-list tip lines)
839
+ (popup-draw tip)
840
+ (if nowait
841
+ tip
842
+ (clear-this-command-keys)
843
+ (push (read-event prompt) unread-command-events)
844
+ t))
845
+ (unless nowait
846
+ (popup-delete tip))))
847
+
848
+
849
+
850
+ ;; Popup menu
851
+
852
+ (defface popup-menu-face
853
+ '((t (:background "lightgray" :foreground "black")))
854
+ "Face for popup menu."
855
+ :group 'popup)
856
+
857
+ (defface popup-menu-selection-face
858
+ '((t (:background "steelblue" :foreground "white")))
859
+ "Face for popup menu selection."
860
+ :group 'popup)
861
+
862
+ (defvar popup-menu-show-tip-function 'popup-tip
863
+ "Function used for showing tooltip by `popup-menu-show-quick-help'.")
864
+
865
+ (defvar popup-menu-show-quick-help-function 'popup-menu-show-quick-help
866
+ "Function used for showing quick help by `popup-menu*'.")
867
+
868
+ (defun popup-menu-show-help (menu &optional persist item)
869
+ (popup-item-show-help (or item (popup-selected-item menu)) persist))
870
+
871
+ (defun popup-menu-documentation (menu &optional item)
872
+ (popup-item-documentation (or item (popup-selected-item menu))))
873
+
874
+ (defun popup-menu-show-quick-help (menu &optional item &rest args)
875
+ (let* ((point (plist-get args :point))
876
+ (height (or (plist-get args :height) (popup-height menu)))
877
+ (min-height (min height (popup-current-height menu)))
878
+ (around nil)
879
+ (parent-offset (popup-offset menu))
880
+ (doc (popup-menu-documentation menu item)))
881
+ (when (stringp doc)
882
+ (if (popup-hidden-p menu)
883
+ (setq around t
884
+ menu nil
885
+ parent-offset nil)
886
+ (setq point nil))
887
+ (let ((popup-use-optimized-column-computation nil)) ; To avoid wrong positioning
888
+ (apply popup-menu-show-tip-function
889
+ doc
890
+ :point point
891
+ :height height
892
+ :min-height min-height
893
+ :around around
894
+ :parent menu
895
+ :parent-offset parent-offset
896
+ args)))))
897
+
898
+ (defun popup-menu-read-key-sequence (keymap &optional prompt timeout)
899
+ (catch 'timeout
900
+ (let ((timer (and timeout
901
+ (run-with-timer timeout nil
902
+ (lambda ()
903
+ (if (zerop (length (this-command-keys)))
904
+ (throw 'timeout nil))))))
905
+ (old-global-map (current-global-map))
906
+ (temp-global-map (make-sparse-keymap))
907
+ (overriding-terminal-local-map (make-sparse-keymap)))
908
+ (substitute-key-definition 'keyboard-quit 'keyboard-quit
909
+ temp-global-map old-global-map)
910
+ (define-key temp-global-map [menu-bar] (lookup-key old-global-map [menu-bar]))
911
+ (define-key temp-global-map [tool-bar] (lookup-key old-global-map [tool-bar]))
912
+ (set-keymap-parent overriding-terminal-local-map keymap)
913
+ (if (current-local-map)
914
+ (define-key overriding-terminal-local-map [menu-bar]
915
+ (lookup-key (current-local-map) [menu-bar])))
916
+ (unwind-protect
917
+ (progn
918
+ (use-global-map temp-global-map)
919
+ (clear-this-command-keys)
920
+ (with-temp-message prompt
921
+ (read-key-sequence nil)))
922
+ (use-global-map old-global-map)
923
+ (if timer (cancel-timer timer))))))
924
+
925
+ (defun popup-menu-fallback (event default))
926
+
927
+ (defun* popup-menu-event-loop (menu keymap fallback &optional prompt help-delay isearch isearch-cursor-color isearch-keymap isearch-callback &aux key binding)
928
+ (block nil
929
+ (while (popup-live-p menu)
930
+ (and isearch
931
+ (popup-isearch menu
932
+ :cursor-color isearch-cursor-color
933
+ :keymap isearch-keymap
934
+ :callback isearch-callback
935
+ :help-delay help-delay)
936
+ (keyboard-quit))
937
+ (setq key (popup-menu-read-key-sequence keymap prompt help-delay))
938
+ (if (null key)
939
+ (unless (funcall popup-menu-show-quick-help-function menu nil :prompt prompt)
940
+ (clear-this-command-keys)
941
+ (push (read-event prompt) unread-command-events))
942
+ (if (eq (lookup-key (current-global-map) key) 'keyboard-quit)
943
+ (keyboard-quit))
944
+ (setq binding (lookup-key keymap key))
945
+ (cond
946
+ ((eq binding 'popup-close)
947
+ (if (popup-parent menu)
948
+ (return)))
949
+ ((memq binding '(popup-select popup-open))
950
+ (let* ((item (popup-selected-item menu))
951
+ (sublist (popup-item-sublist item)))
952
+ (if sublist
953
+ (popup-aif (popup-cascade-menu sublist
954
+ :around nil
955
+ :parent menu
956
+ :margin-left (popup-margin-left menu)
957
+ :margin-right (popup-margin-right menu)
958
+ :scroll-bar (popup-scroll-bar menu))
959
+ (and it (return it)))
960
+ (if (eq binding 'popup-select)
961
+ (return (popup-item-value-or-self item))))))
962
+ ((eq binding 'popup-next)
963
+ (popup-next menu))
964
+ ((eq binding 'popup-previous)
965
+ (popup-previous menu))
966
+ ((eq binding 'popup-help)
967
+ (popup-menu-show-help menu))
968
+ ((eq binding 'popup-isearch)
969
+ (popup-isearch menu
970
+ :cursor-color isearch-cursor-color
971
+ :keymap isearch-keymap
972
+ :callback isearch-callback
973
+ :help-delay help-delay))
974
+ ((commandp binding)
975
+ (call-interactively binding))
976
+ (t
977
+ (funcall fallback key (key-binding key))))))))
978
+
979
+ ;; popup-menu is used by mouse.el unfairly...
980
+ (defun* popup-menu* (list
981
+ &key
982
+ point
983
+ (around t)
984
+ (width (popup-preferred-width list))
985
+ (height 15)
986
+ margin
987
+ margin-left
988
+ margin-right
989
+ scroll-bar
990
+ symbol
991
+ parent
992
+ parent-offset
993
+ (keymap popup-menu-keymap)
994
+ (fallback 'popup-menu-fallback)
995
+ help-delay
996
+ prompt
997
+ isearch
998
+ (isearch-cursor-color popup-isearch-cursor-color)
999
+ (isearch-keymap popup-isearch-keymap)
1000
+ isearch-callback
1001
+ &aux menu event)
1002
+ (and (eq margin t) (setq margin 1))
1003
+ (or margin-left (setq margin-left margin))
1004
+ (or margin-right (setq margin-right margin))
1005
+ (if (and scroll-bar
1006
+ (integerp margin-right)
1007
+ (> margin-right 0))
1008
+ ;; Make scroll-bar space as margin-right
1009
+ (decf margin-right))
1010
+ (setq menu (popup-create point width height
1011
+ :around around
1012
+ :face 'popup-menu-face
1013
+ :selection-face 'popup-menu-selection-face
1014
+ :margin-left margin-left
1015
+ :margin-right margin-right
1016
+ :scroll-bar scroll-bar
1017
+ :symbol symbol
1018
+ :parent parent))
1019
+ (unwind-protect
1020
+ (progn
1021
+ (popup-set-list menu list)
1022
+ (popup-draw menu)
1023
+ (popup-menu-event-loop menu keymap fallback prompt help-delay isearch
1024
+ isearch-cursor-color isearch-keymap isearch-callback))
1025
+ (popup-delete menu)))
1026
+
1027
+ (defun popup-cascade-menu (list &rest args)
1028
+ "Same to `popup-menu', but an element of `LIST' can be
1029
+ list of submenu."
1030
+ (apply 'popup-menu*
1031
+ (mapcar (lambda (item)
1032
+ (if (consp item)
1033
+ (popup-make-item (car item)
1034
+ :sublist (cdr item)
1035
+ :symbol ">")
1036
+ item))
1037
+ list)
1038
+ :symbol t
1039
+ args))
1040
+
1041
+ (defvar popup-menu-keymap
1042
+ (let ((map (make-sparse-keymap)))
1043
+ (define-key map "\r" 'popup-select)
1044
+ (define-key map "\C-f" 'popup-open)
1045
+ (define-key map [right] 'popup-open)
1046
+ (define-key map "\C-b" 'popup-close)
1047
+ (define-key map [left] 'popup-close)
1048
+
1049
+ (define-key map "\C-n" 'popup-next)
1050
+ (define-key map [down] 'popup-next)
1051
+ (define-key map "\C-p" 'popup-previous)
1052
+ (define-key map [up] 'popup-previous)
1053
+
1054
+ (define-key map [f1] 'popup-help)
1055
+ (define-key map (kbd "\C-?") 'popup-help)
1056
+
1057
+ (define-key map "\C-s" 'popup-isearch)
1058
+ map))
1059
+
1060
+ (provide 'popup)
1061
+ ;;; popup.el ends here