ansi-color.el 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. ;;; ansi-color.el --- translate ANSI escape sequences into faces -*- lexical-binding: t -*-
  2. ;; Copyright (C) 1999-2017 Free Software Foundation, Inc.
  3. ;; Author: Alex Schroeder <alex@gnu.org>
  4. ;; Maintainer: Alex Schroeder <alex@gnu.org>
  5. ;; Version: 3.4.2
  6. ;; Keywords: comm processes terminals services
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs is free software: you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation, either version 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; This file provides a function that takes a string or a region
  20. ;; containing Select Graphic Rendition (SGR) control sequences (formerly
  21. ;; known as ANSI escape sequences) and tries to translate these into
  22. ;; faces.
  23. ;;
  24. ;; This allows you to run ls --color=yes in shell-mode. It is now
  25. ;; enabled by default; to disable it, set ansi-color-for-comint-mode
  26. ;; to nil.
  27. ;;
  28. ;; Note that starting your shell from within Emacs might set the TERM
  29. ;; environment variable. The new setting might disable the output of
  30. ;; SGR control sequences. Using ls --color=yes forces ls to produce
  31. ;; these.
  32. ;;
  33. ;; SGR control sequences are defined in section 3.8.117 of the ECMA-48
  34. ;; standard (identical to ISO/IEC 6429), which is freely available as a
  35. ;; PDF file <URL:http://www.ecma-international.org/publications/standards/Ecma-048.htm>.
  36. ;; The "Graphic Rendition Combination Mode (GRCM)" implemented is
  37. ;; "cumulative mode" as defined in section 7.2.8. Cumulative mode
  38. ;; means that whenever possible, SGR control sequences are combined
  39. ;; (ie. blue and bold).
  40. ;; The basic functions are:
  41. ;;
  42. ;; `ansi-color-apply' to colorize a string containing SGR control
  43. ;; sequences.
  44. ;;
  45. ;; `ansi-color-filter-apply' to filter SGR control sequences from a
  46. ;; string.
  47. ;;
  48. ;; `ansi-color-apply-on-region' to colorize a region containing SGR
  49. ;; control sequences.
  50. ;;
  51. ;; `ansi-color-filter-region' to filter SGR control sequences from a
  52. ;; region.
  53. ;;; Thanks
  54. ;; Georges Brun-Cottan <gbruncot@emc.com> for improving ansi-color.el
  55. ;; substantially by adding the code needed to cope with arbitrary chunks
  56. ;; of output and the filter functions.
  57. ;;
  58. ;; Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> for pointing me to ECMA-48.
  59. ;;
  60. ;; Stefan Monnier <foo@acm.com> for explaining obscure font-lock stuff and for
  61. ;; code suggestions.
  62. ;;; Code:
  63. (defvar comint-last-output-start)
  64. ;; Customization
  65. (defgroup ansi-colors nil
  66. "Translating SGR control sequences to faces.
  67. This translation effectively colorizes strings and regions based upon
  68. SGR control sequences embedded in the text. SGR (Select Graphic
  69. Rendition) control sequences are defined in section 8.3.117 of the
  70. ECMA-48 standard (identical to ISO/IEC 6429), which is freely available
  71. at <URL:http://www.ecma-international.org/publications/standards/Ecma-048.htm>
  72. as a PDF file."
  73. :version "21.1"
  74. :group 'processes)
  75. (defcustom ansi-color-faces-vector
  76. [default bold default italic underline success warning error]
  77. "Faces used for SGR control sequences determining a face.
  78. This vector holds the faces used for SGR control sequence parameters 0
  79. to 7.
  80. Parameter Description Face used by default
  81. 0 default default
  82. 1 bold bold
  83. 2 faint default
  84. 3 italic italic
  85. 4 underlined underline
  86. 5 slowly blinking success
  87. 6 rapidly blinking warning
  88. 7 negative image error
  89. Note that the symbol `default' is special: It will not be combined
  90. with the current face.
  91. This vector is used by `ansi-color-make-color-map' to create a color
  92. map. This color map is stored in the variable `ansi-color-map'."
  93. :type '(vector face face face face face face face face)
  94. :set 'ansi-color-map-update
  95. :initialize 'custom-initialize-default
  96. :group 'ansi-colors)
  97. (defcustom ansi-color-names-vector
  98. ["black" "red3" "green3" "yellow3" "blue2" "magenta3" "cyan3" "gray90"]
  99. "Colors used for SGR control sequences determining a color.
  100. This vector holds the colors used for SGR control sequences parameters
  101. 30 to 37 (foreground colors) and 40 to 47 (background colors).
  102. Parameter Color
  103. 30 40 black
  104. 31 41 red
  105. 32 42 green
  106. 33 43 yellow
  107. 34 44 blue
  108. 35 45 magenta
  109. 36 46 cyan
  110. 37 47 white
  111. This vector is used by `ansi-color-make-color-map' to create a color
  112. map. This color map is stored in the variable `ansi-color-map'.
  113. Each element may also be a cons cell where the car and cdr specify the
  114. foreground and background colors, respectively."
  115. :type '(vector (choice color (cons color color))
  116. (choice color (cons color color))
  117. (choice color (cons color color))
  118. (choice color (cons color color))
  119. (choice color (cons color color))
  120. (choice color (cons color color))
  121. (choice color (cons color color))
  122. (choice color (cons color color)))
  123. :set 'ansi-color-map-update
  124. :initialize 'custom-initialize-default
  125. :version "24.4" ; default colors copied from `xterm-standard-colors'
  126. :group 'ansi-colors)
  127. (defconst ansi-color-control-seq-regexp
  128. ;; See ECMA 48, section 5.4 "Control Sequences".
  129. "\e\\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]"
  130. "Regexp matching an ANSI control sequence.")
  131. (defconst ansi-color-parameter-regexp "\\([0-9]*\\)[m;]"
  132. "Regexp that matches SGR control sequence parameters.")
  133. ;; Convenience functions for comint modes (eg. shell-mode)
  134. (defcustom ansi-color-for-comint-mode t
  135. "Determines what to do with comint output.
  136. If nil, do nothing.
  137. If the symbol `filter', then filter all SGR control sequences.
  138. If anything else (such as t), then translate SGR control sequences
  139. into text properties.
  140. In order for this to have any effect, `ansi-color-process-output' must
  141. be in `comint-output-filter-functions'.
  142. This can be used to enable colorized ls --color=yes output
  143. in shell buffers. You set this variable by calling one of:
  144. \\[ansi-color-for-comint-mode-on]
  145. \\[ansi-color-for-comint-mode-off]
  146. \\[ansi-color-for-comint-mode-filter]"
  147. :type '(choice (const :tag "Do nothing" nil)
  148. (const :tag "Filter" filter)
  149. (const :tag "Translate" t))
  150. :group 'ansi-colors
  151. :version "23.2")
  152. (defvar ansi-color-apply-face-function 'ansi-color-apply-overlay-face
  153. "Function for applying an Ansi Color face to text in a buffer.
  154. This function should accept three arguments: BEG, END, and FACE,
  155. and it should apply face FACE to the text between BEG and END.")
  156. ;;;###autoload
  157. (defun ansi-color-for-comint-mode-on ()
  158. "Set `ansi-color-for-comint-mode' to t."
  159. (interactive)
  160. (setq ansi-color-for-comint-mode t))
  161. (defun ansi-color-for-comint-mode-off ()
  162. "Set `ansi-color-for-comint-mode' to nil."
  163. (interactive)
  164. (setq ansi-color-for-comint-mode nil))
  165. (defun ansi-color-for-comint-mode-filter ()
  166. "Set `ansi-color-for-comint-mode' to symbol `filter'."
  167. (interactive)
  168. (setq ansi-color-for-comint-mode 'filter))
  169. ;;;###autoload
  170. (defun ansi-color-process-output (ignored)
  171. "Maybe translate SGR control sequences of comint output into text properties.
  172. Depending on variable `ansi-color-for-comint-mode' the comint output is
  173. either not processed, SGR control sequences are filtered using
  174. `ansi-color-filter-region', or SGR control sequences are translated into
  175. text properties using `ansi-color-apply-on-region'.
  176. The comint output is assumed to lie between the marker
  177. `comint-last-output-start' and the process-mark.
  178. This is a good function to put in `comint-output-filter-functions'."
  179. (let ((start-marker (if (and (markerp comint-last-output-start)
  180. (eq (marker-buffer comint-last-output-start)
  181. (current-buffer))
  182. (marker-position comint-last-output-start))
  183. comint-last-output-start
  184. (point-min-marker)))
  185. (end-marker (process-mark (get-buffer-process (current-buffer)))))
  186. (cond ((eq ansi-color-for-comint-mode nil))
  187. ((eq ansi-color-for-comint-mode 'filter)
  188. (ansi-color-filter-region start-marker end-marker))
  189. (t
  190. (ansi-color-apply-on-region start-marker end-marker)))))
  191. (define-obsolete-function-alias 'ansi-color-unfontify-region
  192. 'font-lock-default-unfontify-region "24.1")
  193. ;; Working with strings
  194. (defvar-local ansi-color-context nil
  195. "Context saved between two calls to `ansi-color-apply'.
  196. This is a list of the form (CODES FRAGMENT) or nil. CODES
  197. represents the state the last call to `ansi-color-apply' ended
  198. with, currently a list of ansi codes, and FRAGMENT is a string
  199. starting with an escape sequence, possibly the start of a new
  200. escape sequence.")
  201. (defun ansi-color-filter-apply (string)
  202. "Filter out all ANSI control sequences from STRING.
  203. Every call to this function will set and use the buffer-local variable
  204. `ansi-color-context' to save partial escape sequences. This information
  205. will be used for the next call to `ansi-color-apply'. Set
  206. `ansi-color-context' to nil if you don't want this.
  207. This function can be added to `comint-preoutput-filter-functions'."
  208. (let ((start 0) end result)
  209. ;; if context was saved and is a string, prepend it
  210. (if (cadr ansi-color-context)
  211. (setq string (concat (cadr ansi-color-context) string)
  212. ansi-color-context nil))
  213. ;; find the next escape sequence
  214. (while (setq end (string-match ansi-color-control-seq-regexp string start))
  215. (push (substring string start end) result)
  216. (setq start (match-end 0)))
  217. ;; save context, add the remainder of the string to the result
  218. (let (fragment)
  219. (push (substring string start
  220. (if (string-match "\033" string start)
  221. (let ((pos (match-beginning 0)))
  222. (setq fragment (substring string pos))
  223. pos)
  224. nil))
  225. result)
  226. (setq ansi-color-context (if fragment (list nil fragment))))
  227. (apply #'concat (nreverse result))))
  228. (defun ansi-color--find-face (codes)
  229. "Return the face corresponding to CODES."
  230. (let (faces)
  231. (while codes
  232. (let ((face (ansi-color-get-face-1 (pop codes))))
  233. ;; In the (default underline) face, say, the value of the
  234. ;; "underline" attribute of the `default' face wins.
  235. (unless (eq face 'default)
  236. (push face faces))))
  237. ;; Avoid some long-lived conses in the common case.
  238. (if (cdr faces)
  239. (nreverse faces)
  240. (car faces))))
  241. (defun ansi-color-apply (string)
  242. "Translates SGR control sequences into text properties.
  243. Delete all other control sequences without processing them.
  244. Applies SGR control sequences setting foreground and background colors
  245. to STRING using text properties and returns the result. The colors used
  246. are given in `ansi-color-faces-vector' and `ansi-color-names-vector'.
  247. See function `ansi-color-apply-sequence' for details.
  248. Every call to this function will set and use the buffer-local variable
  249. `ansi-color-context' to save partial escape sequences and current ansi codes.
  250. This information will be used for the next call to `ansi-color-apply'.
  251. Set `ansi-color-context' to nil if you don't want this.
  252. This function can be added to `comint-preoutput-filter-functions'."
  253. (let ((codes (car ansi-color-context))
  254. (start 0) end result)
  255. ;; If context was saved and is a string, prepend it.
  256. (if (cadr ansi-color-context)
  257. (setq string (concat (cadr ansi-color-context) string)
  258. ansi-color-context nil))
  259. ;; Find the next escape sequence.
  260. (while (setq end (string-match ansi-color-control-seq-regexp string start))
  261. (let ((esc-end (match-end 0)))
  262. ;; Colorize the old block from start to end using old face.
  263. (when codes
  264. (put-text-property start end 'font-lock-face
  265. (ansi-color--find-face codes) string))
  266. (push (substring string start end) result)
  267. (setq start (match-end 0))
  268. ;; If this is a color escape sequence,
  269. (when (eq (aref string (1- esc-end)) ?m)
  270. ;; create a new face from it.
  271. (setq codes (ansi-color-apply-sequence
  272. (substring string end esc-end) codes)))))
  273. ;; if the rest of the string should have a face, put it there
  274. (when codes
  275. (put-text-property start (length string)
  276. 'font-lock-face (ansi-color--find-face codes) string))
  277. ;; save context, add the remainder of the string to the result
  278. (let (fragment)
  279. (if (string-match "\033" string start)
  280. (let ((pos (match-beginning 0)))
  281. (setq fragment (substring string pos))
  282. (push (substring string start pos) result))
  283. (push (substring string start) result))
  284. (setq ansi-color-context (if (or codes fragment) (list codes fragment))))
  285. (apply 'concat (nreverse result))))
  286. ;; Working with regions
  287. (defvar-local ansi-color-context-region nil
  288. "Context saved between two calls to `ansi-color-apply-on-region'.
  289. This is a list of the form (CODES MARKER) or nil. CODES
  290. represents the state the last call to `ansi-color-apply-on-region'
  291. ended with, currently a list of ansi codes, and MARKER is a
  292. buffer position within an escape sequence or the last position
  293. processed.")
  294. (defun ansi-color-filter-region (begin end)
  295. "Filter out all ANSI control sequences from region BEGIN to END.
  296. Every call to this function will set and use the buffer-local variable
  297. `ansi-color-context-region' to save position. This information will be
  298. used for the next call to `ansi-color-apply-on-region'. Specifically,
  299. it will override BEGIN, the start of the region. Set
  300. `ansi-color-context-region' to nil if you don't want this."
  301. (let ((end-marker (copy-marker end))
  302. (start (or (cadr ansi-color-context-region) begin)))
  303. (save-excursion
  304. (goto-char start)
  305. ;; Delete escape sequences.
  306. (while (re-search-forward ansi-color-control-seq-regexp end-marker t)
  307. (delete-region (match-beginning 0) (match-end 0)))
  308. ;; save context, add the remainder of the string to the result
  309. (if (re-search-forward "\033" end-marker t)
  310. (setq ansi-color-context-region (list nil (match-beginning 0)))
  311. (setq ansi-color-context-region nil)))))
  312. (defun ansi-color-apply-on-region (begin end)
  313. "Translates SGR control sequences into overlays or extents.
  314. Delete all other control sequences without processing them.
  315. SGR control sequences are applied by calling the function
  316. specified by `ansi-color-apply-face-function'. The default
  317. function sets foreground and background colors to the text
  318. between BEGIN and END, using overlays. The colors used are given
  319. in `ansi-color-faces-vector' and `ansi-color-names-vector'. See
  320. `ansi-color-apply-sequence' for details.
  321. Every call to this function will set and use the buffer-local
  322. variable `ansi-color-context-region' to save position and current
  323. ansi codes. This information will be used for the next call to
  324. `ansi-color-apply-on-region'. Specifically, it will override
  325. BEGIN, the start of the region and set the face with which to
  326. start. Set `ansi-color-context-region' to nil if you don't want
  327. this."
  328. (let ((codes (car ansi-color-context-region))
  329. (start-marker (or (cadr ansi-color-context-region)
  330. (copy-marker begin)))
  331. (end-marker (copy-marker end)))
  332. (save-excursion
  333. (goto-char start-marker)
  334. ;; Find the next escape sequence.
  335. (while (re-search-forward ansi-color-control-seq-regexp end-marker t)
  336. ;; Remove escape sequence.
  337. (let ((esc-seq (delete-and-extract-region
  338. (match-beginning 0) (point))))
  339. ;; Colorize the old block from start to end using old face.
  340. (funcall ansi-color-apply-face-function
  341. (prog1 (marker-position start-marker)
  342. ;; Store new start position.
  343. (set-marker start-marker (point)))
  344. (match-beginning 0) (ansi-color--find-face codes))
  345. ;; If this is a color sequence,
  346. (when (eq (aref esc-seq (1- (length esc-seq))) ?m)
  347. ;; update the list of ansi codes.
  348. (setq codes (ansi-color-apply-sequence esc-seq codes)))))
  349. ;; search for the possible start of a new escape sequence
  350. (if (re-search-forward "\033" end-marker t)
  351. (progn
  352. ;; if the rest of the region should have a face, put it there
  353. (funcall ansi-color-apply-face-function
  354. start-marker (point) (ansi-color--find-face codes))
  355. ;; save codes and point
  356. (setq ansi-color-context-region
  357. (list codes (copy-marker (match-beginning 0)))))
  358. ;; if the rest of the region should have a face, put it there
  359. (funcall ansi-color-apply-face-function
  360. start-marker end-marker (ansi-color--find-face codes))
  361. (setq ansi-color-context-region (if codes (list codes)))))))
  362. (defun ansi-color-apply-overlay-face (beg end face)
  363. "Make an overlay from BEG to END, and apply face FACE.
  364. If FACE is nil, do nothing."
  365. (when face
  366. (ansi-color-set-extent-face
  367. (ansi-color-make-extent beg end)
  368. face)))
  369. ;; This function helps you look for overlapping overlays. This is
  370. ;; useful in comint-buffers. Overlapping overlays should not happen!
  371. ;; A possible cause for bugs are the markers. If you create an overlay
  372. ;; up to the end of the region, then that end might coincide with the
  373. ;; process-mark. As text is added BEFORE the process-mark, the overlay
  374. ;; will keep growing. Therefore, as more overlays are created later on,
  375. ;; there will be TWO OR MORE overlays covering the buffer at that point.
  376. ;; This function helps you check your buffer for these situations.
  377. ; (defun ansi-color-debug-overlays ()
  378. ; (interactive)
  379. ; (let ((pos (point-min)))
  380. ; (while (< pos (point-max))
  381. ; (if (<= 2 (length (overlays-at pos)))
  382. ; (progn
  383. ; (goto-char pos)
  384. ; (error "%d overlays at %d" (length (overlays-at pos)) pos))
  385. ; (let (message-log-max)
  386. ; (message "Reached %d." pos)))
  387. ; (setq pos (next-overlay-change pos)))))
  388. ;; Emacs/XEmacs compatibility layer
  389. (defun ansi-color-make-face (property color)
  390. "Return a face with PROPERTY set to COLOR.
  391. PROPERTY can be either symbol `foreground' or symbol `background'.
  392. For Emacs, we just return the cons cell (PROPERTY . COLOR).
  393. For XEmacs, we create a temporary face and return it."
  394. (if (featurep 'xemacs)
  395. (let ((face (make-face (intern (concat color "-" (symbol-name property)))
  396. "Temporary face created by ansi-color."
  397. t)))
  398. (set-face-property face property color)
  399. face)
  400. (cond ((eq property 'foreground)
  401. (cons 'foreground-color color))
  402. ((eq property 'background)
  403. (cons 'background-color color))
  404. (t
  405. (cons property color)))))
  406. (defun ansi-color-make-extent (from to &optional object)
  407. "Make an extent for the range [FROM, TO) in OBJECT.
  408. OBJECT defaults to the current buffer. XEmacs uses `make-extent', Emacs
  409. uses `make-overlay'. XEmacs can use a buffer or a string for OBJECT,
  410. Emacs requires OBJECT to be a buffer."
  411. (if (fboundp 'make-extent)
  412. (make-extent from to object)
  413. ;; In Emacs, the overlay might end at the process-mark in comint
  414. ;; buffers. In that case, new text will be inserted before the
  415. ;; process-mark, ie. inside the overlay (using insert-before-marks).
  416. ;; In order to avoid this, we use the `insert-behind-hooks' overlay
  417. ;; property to make sure it works.
  418. (let ((overlay (make-overlay from to object)))
  419. (overlay-put overlay 'modification-hooks '(ansi-color-freeze-overlay))
  420. (overlay-put overlay 'insert-behind-hooks '(ansi-color-freeze-overlay))
  421. overlay)))
  422. (defun ansi-color-freeze-overlay (overlay is-after begin end &optional len)
  423. "Prevent OVERLAY from being extended.
  424. This function can be used for the `modification-hooks' overlay
  425. property."
  426. ;; if stuff was inserted at the end of the overlay
  427. (when (and is-after
  428. (= 0 len)
  429. (= end (overlay-end overlay)))
  430. ;; reset the end of the overlay
  431. (move-overlay overlay (overlay-start overlay) begin)))
  432. (defun ansi-color-set-extent-face (extent face)
  433. "Set the `face' property of EXTENT to FACE.
  434. XEmacs uses `set-extent-face', Emacs uses `overlay-put'."
  435. (if (featurep 'xemacs)
  436. (set-extent-face extent face)
  437. (overlay-put extent 'face face)))
  438. ;; Helper functions
  439. (defsubst ansi-color-parse-sequence (escape-seq)
  440. "Return the list of all the parameters in ESCAPE-SEQ.
  441. ESCAPE-SEQ is a SGR control sequences such as \\033[34m. The parameter
  442. 34 is used by `ansi-color-get-face-1' to return a face definition.
  443. Returns nil only if there's no match for `ansi-color-parameter-regexp'."
  444. (let ((i 0)
  445. codes val)
  446. (while (string-match ansi-color-parameter-regexp escape-seq i)
  447. (setq i (match-end 0)
  448. val (string-to-number (match-string 1 escape-seq) 10))
  449. ;; It so happens that (string-to-number "") => 0.
  450. (push val codes))
  451. (nreverse codes)))
  452. (defun ansi-color-apply-sequence (escape-sequence codes)
  453. "Apply ESCAPE-SEQUENCE to CODES and return the new list of codes.
  454. ESCAPE-SEQUENCE is an escape sequence parsed by
  455. `ansi-color-parse-sequence'.
  456. For each new code, the following happens: if it is 1-7, add it to
  457. the list of codes; if it is 21-25 or 27, delete appropriate
  458. parameters from the list of codes; if it is 30-37 resp. 39, the
  459. foreground color code is replaced or added resp. deleted; if it
  460. is 40-47 resp. 49, the background color code is replaced or added
  461. resp. deleted; any other code is discarded together with the old
  462. codes. Finally, the so changed list of codes is returned."
  463. (let ((new-codes (ansi-color-parse-sequence escape-sequence)))
  464. (while new-codes
  465. (let* ((new (pop new-codes))
  466. (q (/ new 10)))
  467. (setq codes
  468. (pcase q
  469. (0 (unless (memq new '(0 8 9))
  470. (cons new (remq new codes))))
  471. (2 (unless (memq new '(20 26 28 29))
  472. ;; The standard says `21 doubly underlined' while
  473. ;; http://en.wikipedia.org/wiki/ANSI_escape_code claims
  474. ;; `21 Bright/Bold: off or Underline: Double'.
  475. (remq (- new 20) (pcase new
  476. (22 (remq 1 codes))
  477. (25 (remq 6 codes))
  478. (_ codes)))))
  479. ((or 3 4) (let ((r (mod new 10)))
  480. (unless (= r 8)
  481. (let (beg)
  482. (while (and codes (/= q (/ (car codes) 10)))
  483. (push (pop codes) beg))
  484. (setq codes (nconc (nreverse beg) (cdr codes)))
  485. (if (= r 9)
  486. codes
  487. (cons new codes))))))
  488. (_ nil)))))
  489. codes))
  490. (defun ansi-color-make-color-map ()
  491. "Creates a vector of face definitions and returns it.
  492. The index into the vector is an ANSI code. See the documentation of
  493. `ansi-color-map' for an example.
  494. The face definitions are based upon the variables
  495. `ansi-color-faces-vector' and `ansi-color-names-vector'."
  496. (let ((map (make-vector 50 nil))
  497. (index 0))
  498. ;; miscellaneous attributes
  499. (mapc
  500. (function (lambda (e)
  501. (aset map index e)
  502. (setq index (1+ index)) ))
  503. ansi-color-faces-vector)
  504. ;; foreground attributes
  505. (setq index 30)
  506. (mapc
  507. (function (lambda (e)
  508. (aset map index
  509. (ansi-color-make-face 'foreground
  510. (if (consp e) (car e) e)))
  511. (setq index (1+ index)) ))
  512. ansi-color-names-vector)
  513. ;; background attributes
  514. (setq index 40)
  515. (mapc
  516. (function (lambda (e)
  517. (aset map index
  518. (ansi-color-make-face 'background
  519. (if (consp e) (cdr e) e)))
  520. (setq index (1+ index)) ))
  521. ansi-color-names-vector)
  522. map))
  523. (defvar ansi-color-map (ansi-color-make-color-map)
  524. "A brand new color map suitable for `ansi-color-get-face'.
  525. The value of this variable is usually constructed by
  526. `ansi-color-make-color-map'. The values in the array are such that the
  527. numbers included in an SGR control sequences point to the correct
  528. foreground or background colors.
  529. Example: The sequence \\033[34m specifies a blue foreground. Therefore:
  530. (aref ansi-color-map 34)
  531. => (foreground-color . \"blue\")")
  532. (defun ansi-color-map-update (symbol value)
  533. "Update `ansi-color-map'.
  534. Whenever the vectors used to construct `ansi-color-map' are changed,
  535. this function is called. Therefore this function is listed as the :set
  536. property of `ansi-color-faces-vector' and `ansi-color-names-vector'."
  537. (set-default symbol value)
  538. (setq ansi-color-map (ansi-color-make-color-map)))
  539. (defun ansi-color-get-face-1 (ansi-code)
  540. "Get face definition from `ansi-color-map'.
  541. ANSI-CODE is used as an index into the vector."
  542. (condition-case nil
  543. (aref ansi-color-map ansi-code)
  544. (args-out-of-range nil)))
  545. (provide 'ansi-color)
  546. ;;; ansi-color.el ends here