aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Moellmann1999-10-19 11:17:23 +0000
committerGerd Moellmann1999-10-19 11:17:23 +0000
commit8737bb5a2a2dbd80a265a2390a90875d2913eda9 (patch)
treebfa4dc62ca69f7e7e8647ba308fb4b0458d1b5dc
parentf20386e596e4f120a2c1d90bbbfa91d6d3234999 (diff)
downloademacs-8737bb5a2a2dbd80a265a2390a90875d2913eda9.tar.gz
emacs-8737bb5a2a2dbd80a265a2390a90875d2913eda9.zip
Complete rewrite.
-rw-r--r--lisp/ansi-color.el216
1 files changed, 94 insertions, 122 deletions
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 53b29a76552..7bc747dd04a 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -2,9 +2,9 @@
2 2
3;; Copyright (C) 1999 Free Software Foundation, Inc. 3;; Copyright (C) 1999 Free Software Foundation, Inc.
4 4
5;; Author: Alex Schroeder <alex@gnu.ch> 5;; Author: Alex Schroeder <alex@gnu.org>
6;; Maintainer: Alex Schroeder <alex@gnu.ch> 6;; Maintainer: Alex Schroeder <alex@gnu.org>
7;; Version: 1.2.0 7;; Version: 2.1.1
8;; Keywords: comm processes 8;; Keywords: comm processes
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -36,70 +36,55 @@
36;; program I wanted to extend (the MUSH client TinyTalk.el), so I had to 36;; program I wanted to extend (the MUSH client TinyTalk.el), so I had to
37;; rewrite this. 37;; rewrite this.
38 38
39;; In order to install this with TinyMush.el, add the following to your
40;; .emacs file:
41;;
42;; (setq tinymud-filter-line-hook 'my-tinymud-add-ansi-text-properties)
43;; (autoload 'ansi-color-to-text-properties "ansi-color"
44;; "Translates ANSI color control sequences into text-properties." t)
45;; (defun my-tinymud-add-ansi-text-properties (conn line)
46;; "Call `ansi-color-to-text-properties' for LINE.
47;; Ignores CONN and returns nil, so that `tinymud-filter-line' continues to
48;; process triggers and everything else."
49;; (ansi-color-to-text-properties line)
50;; nil)
51
52;; If the ANSI sequences assume that you have a black background, you'll
53;; have to display the stuff in a frame with a black background. You
54;; can create such a frame like this (it still looks ugly!):
55;;
56;; (defun my-black-frame ()
57;; "Create a frame with black background."
58;; (interactive)
59;; (make-frame '((foreground-color . "white")
60;; (background-color . "black"))))
61
62;;; Testing: 39;;; Testing:
63 40
64;; If you want to test the setup, evaluate the following fragment in a 41;; If you want to test the setup, evaluate the following fragment in a
65;; buffer without font-lock-mode. This doesn't work in buffers that 42;; buffer without font-lock-mode. This doesn't work in buffers that
66;; have font-lock-mode! 43;; have font-lock-mode!
67;; 44;;
68;; (progn 45;; (insert (ansi-color-apply "\033[1mbold\033[0m and \033[34mblue\033[0m, \033[1m\033[34mbold and blue\033[0m!!"))
69;; (setq line "bold and blue, bold and blue!!")
70;; (ansi-color-to-text-properties line)
71;; (insert line))
72;;
73;; Other test strings: (m-eating-bug) "mold should be mold"
74 46
75;;; Bugs: 47;; Usage with TinyMush.el:
76 48
77;; 1. Only supports the ANSI sequences that the MUSH I'm on uses (the 49;; In order to install this with TinyMush.el, add the following to your
78;; MUSH is Elendor, see http://www.elendor.net). To see the list of 50;; .emacs file:
79;; codes supported I did a `help ansi()'. Based on this information,
80;; I used TinyTalk.el (without ANSI color support), gave myself the
81;; ANSI color flags using `@set me=ANSI' and `@set me=COLOR', and
82;; noted the ANSI escape sequences produced by the MUSH using `think
83;; ansi(r,red)' for example.
84;;
85;; 2. The code is spaghetti-code, I hate it.
86;; 51;;
87;; 3. If a squence of chars looks like the start of an ANSI sequence, 52;; (setq tinymud-filter-line-hook 'my-ansi-color-filter)
88;; the chars will be set invisible. If the squence of chars turns 53;; (autoload 'ansi-color-apply "ansi-color"
89;; out not to be an ANSI sequence, this is not undone. Here is a 54;; "Translates ANSI color control sequences into text-properties." t)
90;; teststring: "Is '[3' visible as ^[[3?" This could be solved by 55;; (defun my-ansi-color-filter (conn line)
91;; using `state': it shows most of the time how many characters have 56;; "Call `ansi-color-apply' and then processes things like `filter-line'."
92;; been set invisible. 57;; (setq line (ansi-color-apply line))
58;; (if (not (get-value conn 'trigger-disable))
59;; (progn
60;; (check-triggers conn line
61;; (get-value conn 'triggers))
62;; (check-triggers conn line
63;; (get-value (get-value conn 'world) 'triggers))
64;; (check-triggers conn line
65;; tinymud-global-triggers)))
66;; (display-line conn line)
67;; t)
68
69;; Usage with shell-mode:
70
71;; In order to enjoy the marvels of "ls --color=tty" you will have to
72;; enter shell-mode using M-x shell, possibly disable font-lock-mode
73;; using M-: (font-lock-mode 0), and add ansi-color-apply to
74;; comint-preoutput-filter-functions using M-: (add-hook
75;; 'comint-preoutput-filter-functions 'ansi-color-apply).
93 76
94 77
95 78
96;;; Code: 79;;; Code:
97 80
81;; Customization
82
98(defvar ansi-color-faces-vector 83(defvar ansi-color-faces-vector
99 [default bold default default underline bold default modeline] 84 [default bold default default underline bold default modeline]
100 "Faces used for ANSI control sequences determining a face. 85 "Faces used for ANSI control sequences determining a face.
101 86
102Those are sequences like this one: , where 1 could be one of the 87Those are sequences like this one: \033[1m, where 1 could be one of the
103following numbers: 0 (default), 1 (hilight, rendered as bold), 4 88following numbers: 0 (default), 1 (hilight, rendered as bold), 4
104(underline), 5 (flashing, rendered as bold), 7 (inverse, rendered the 89(underline), 5 (flashing, rendered as bold), 7 (inverse, rendered the
105same as the modeline)") 90same as the modeline)")
@@ -108,8 +93,8 @@ same as the modeline)")
108 ["black" "red" "green" "yellow" "blue" "magenta" "cyan" "white"] 93 ["black" "red" "green" "yellow" "blue" "magenta" "cyan" "white"]
109 "Array of colors. 94 "Array of colors.
110 95
111Used for sequences like this one: , where 1 could be an index to a 96Used for sequences like this one: \033[31m, where 1 could be an index to a
112foreground color (red, in this case), or , where 1 could be an 97foreground color (red, in this case), or \033[41m, where 1 could be an
113index to a background color. 98index to a background color.
114 99
115The default colors are: black, red, green, yellow, blue, magenta, 100The default colors are: black, red, green, yellow, blue, magenta,
@@ -118,77 +103,64 @@ cyan, and white.
118On a light background, I prefer: black, red, dark green, orange, blue, 103On a light background, I prefer: black, red, dark green, orange, blue,
119magenta, turquoise, snow4") 104magenta, turquoise, snow4")
120 105
121;; The main function 106;; Main function
122 107
123(defun ansi-color-to-text-properties (str) 108(defun ansi-color-apply (string)
124 "Translates ANSI color control sequences into text-properties. 109 "Translates ANSI color control sequences into text-properties.
125 110
126The ANSI control sequences are made invisible. The text-properties are 111Applies ANSI control sequences setting foreground and background colors
127added to the string given in the parameter STR." 112to STRING and returns the result. The colors used are given in
128 ;; ANSI code for highlighting, example: boringINTERESTINGboring 113`ansi-color-faces-vector' and `ansi-color-names-vector'.
129 ;; state: start with 0, "" -> 1, "[" -> 2, "[013457]" -> 3, 114
130 ;; "[013457]" -> 4, "m" -> back to 0! 115This function can be added to `comint-preoutput-filter-functions'."
131 ;; param: stored when state is 3 (in the above example: 1) 116 (let ((face)
132 (let ((str-length (length str)) 117 (start 0) (end) (escape)
133 (face '(default)) 118 (result)
134 (i 0) (char) (state 0) (param1) (param2)) 119 (params))
135 (while (< i str-length) 120 ;; find the next escape sequence
136 (setq char (aref str i)) 121 (while (setq end (string-match "\033\\[\\([01347][01234567]?;\\)*[01347][01234567]?m" string start))
137 (cond 122 ;; store escape sequence
138 ;; When writing normal chars (state 0) and happening upon an ANSI sequence. 123 (setq escape (match-string 0 string))
139 ((and (= state 0) (= char ?)) 124 ;; colorize the old block from start to end using old face
140 (setq state 1)); saw escape 125 (if face
141 ((and (= state 1) (= char ?\[)); seen escape 126 (put-text-property start end 'face face string))
142 (setq state 2 127 (setq result (concat result (substring string start end)))
143 param1 nil 128 ;; create new face by applying all the parameters in the escape sequence
144 param2 nil)); saw [, prepare for param1 and param2! 129 (let ((i 0))
145 ((and (or (= state 2) (= state 3)); reading first or second digit 130 (while (setq i (string-match "[01347][01234567]?[;m]" escape i))
146 (string-match "[01234567]" (substring str i (1+ i)))) 131 (setq face (ansi-color-make-face face
147 (if (= state 2); reading first digit 132 (aref escape i)
148 ;;  (hilight) 133 (aref escape (1+ i))))
149 (setq param1 (string-to-number (substring str i (1+ i))) 134 (setq i (match-end 0))))
150 state 3); prepare to read a second digit or quit. 135 (setq start (+ end (length escape))))
151 ;; if reading second digit 136 (concat result (substring string start))))
152 ;; such as  (green foreground) 137
153 (setq param2 (string-to-number (substring str i (1+ i))) 138;; Helper functions
154 state 4))); read second digit, prepare to quit 139
155 ((and (or (= state 3) (= state 4)) (= char ?m)); reading last char: m 140(defun ansi-color-make-face (face param1 param2)
156 (setq state 5); state 5: m will be last invisible char. Now 141 "Return a face based on FACE and characters PARAM1 and PARAM2.
157 ;; reset face according to param1 and param2. 142
158 (if (null param2); only param1 set: no color changes! 143The face can be used in a call to `add-text-properties'. The PARAM1 and
159 ;; : default face 144PARAM2 characters are the two numeric characters in ANSI control
160 (if (= param1 0) 145sequences between ?[ and ?m. Unless the ANSI control sequence specifies
161 (setq face '(default)) 146a return to default face using PARAM1 ?0 and PARAM2 ?m (ie. \"\033[0m\"), the
162 ;; : hilight, : inverse, : underline, etc. 147properties specified by PARAM1 and PARAM2 are added to face."
163 (add-to-list 'face (aref ansi-color-faces-vector param1))) 148 (cond ((= param1 ?0)
164 ;; If param2 is set, we are changing back- or foreground color. 149 nil)
165 (if (= param1 3); first digit told us to change foreground 150 ((= param2 ?m)
166 ;; : red foreground 151 (add-to-list 'face (aref ansi-color-faces-vector
167 (add-to-list 'face (cons 'foreground-color 152 (string-to-number (char-to-string param1)))))
168 (aref ansi-color-names-vector param2))) 153 ((= param1 ?3)
169 ;; : green background 154 (add-to-list 'face (cons 'foreground-color
170 (add-to-list 'face (cons 'background-color 155 (aref ansi-color-names-vector
171 (aref ansi-color-names-vector param2)))))) 156 (string-to-number (char-to-string param2))))))
172 (t (setq state 0))); all other cases, state is 0. 157 ((= param1 ?4)
173 158 (add-to-list 'face (cons 'background-color
174 ;; Set text-property for every char. 159 (aref ansi-color-names-vector
175 (if (> state 0); if reading ANSI codes, state > 0: make them 160 (string-to-number (char-to-string param2))))))
176 ; invisible. 161 (t (add-to-list 'face (aref ansi-color-faces-vector
177 (put-text-property i (1+ i) 'invisible t str) 162 (string-to-number (char-to-string param1)))))))
178 ;; if reading normal chars, state is 0, put them in the
179 ;; current face.
180 (put-text-property i (1+ i) 'face face str))
181
182 ;; Debug: (message "%c: %d" char state)
183
184 ;; If we just finished reading an ANSI sequence (state 5), reset
185 ;; state (state 0).
186 (if (> state 4) (setq state 0))
187 ;; Next char
188 (setq i (1+ i)))))
189 163
190(provide 'ansi-color) 164(provide 'ansi-color)
191 165
192;;; ansi-colors.el ends here 166;;; ansi-color.el ends here
193
194