[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/engrave-faces 4e6026e 21/36: New backend: ANSI
From: |
ELPA Syncer |
Subject: |
[elpa] externals/engrave-faces 4e6026e 21/36: New backend: ANSI |
Date: |
Tue, 31 Aug 2021 01:57:27 -0400 (EDT) |
branch: externals/engrave-faces
commit 4e6026e1e8ef4e785ed57c72db4961248b4ad08f
Author: TEC <tec@tecosaur.com>
Commit: TEC <tec@tecosaur.com>
New backend: ANSI
---
README.org | 2 +-
engrave-faces-ansi.el | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/README.org b/README.org
index d4c1428..7c8f771 100644
--- a/README.org
+++ b/README.org
@@ -20,4 +20,4 @@ I fully expect some important items to have been forgotten.
*Included backends*
- [X] LaTeX
- [ ] HTML
-- [ ] ANSI
+- [X] ANSI
diff --git a/engrave-faces-ansi.el b/engrave-faces-ansi.el
new file mode 100644
index 0000000..4663256
--- /dev/null
+++ b/engrave-faces-ansi.el
@@ -0,0 +1,167 @@
+;;; engrave-faces-ansi.el --- Support for engraving buffers to LaTeX -*-
lexical-binding: t; -*-
+
+;; This file is part of engrave-faces.
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;;; Commentary:
+
+;; Support for engraving buffers to LaTeX.
+
+;;; Code:
+
+(require 'engrave-faces)
+
+(defcustom engrave-faces-ansi-color-mode '8-bit
+ "The ansi escape mode set to use.
+This accepts both n-bit and m-color forms.
+Possible values are:
+- `3-bit' (`8-color')
+- `4-bit' (`16-color')
+- `8-bit' (`256-color')
+- `24-bit' (`16m-color')"
+ :type '(choice
+ (const 3-bit)
+ (const 4-bit)
+ (const 8-bit)
+ (const 24-bit))
+ :group 'engrave-faces)
+
+(defcustom engrave-faces-ansi-use-face-colours t
+ "Whether to apply face colours"
+ :group 'engrave-faces)
+
+(defvar engrave-faces-ansi-face-nesting nil)
+
+(defun engrave-faces-ansi-code (attrs)
+ "Genrerate ANSI commands which apply ATTRS to the succeeding text."
+ (concat
+ (when (member (plist-get attrs :weight) '(bold extra-bold)) "\uE000[1m")
+ (when (eq 'italic (plist-get attrs :slant)) "\uE000[3m")
+ (when (eq t (plist-get attrs :underline)) "\uE000[4m")
+ (when (and engrave-faces-ansi-use-face-colours
+ (plist-get attrs :foreground))
+ (engrave-faces-ansi-color-to-ansi
+ (plist-get attrs :foreground)))
+ (when (and engrave-faces-ansi-use-face-colours
+ (plist-get attrs :background))
+ (engrave-faces-ansi-color-to-ansi
+ (plist-get attrs :background) t))))
+
+;;;;; Color conversion
+
+(defun engrave-faces-ansi-color-to-ansi (color &optional background)
+ (if (eq color 'unspecified) nil
+ (apply (pcase engrave-faces-ansi-color-mode
+ ((or '3-bit '8-color) #'engrave-faces-ansi-color-3bit-code)
+ ((or '4-bit '16-color) #'engrave-faces-ansi-color-4bit-code)
+ ((or '8-bit '256-color) #'engrave-faces-ansi-color-8bit-code)
+ ((or '24-bit '16m-color) #'engrave-faces-ansi-color-24bit-code))
+ (append (mapcar (lambda (c) (/ c 257)) (color-values color)) (list
background)))))
+
+(defun engrave-faces-ansi-color-dist-squared (reference rgb)
+ "Squared L2 distance between a REFERENCE and RBG values, each a list of 3
values (r g b)."
+ (+ (* (nth 0 reference)
+ (nth 0 rgb))
+ (* (nth 1 reference)
+ (nth 1 rgb))
+ (* (nth 2 reference)
+ (nth 2 rgb))))
+
+;;;;;; 3-bit / 8-color
+
+(defun engrave-faces-ansi-color-3bit-code (r g b &optional background)
+ "Convert the (R G B) colour code to a correspanding 4bit ansi escape
sequence."
+ (format "\uE000[%sm"
+ (% (pcase (nth (engrave-faces-ansi-color-rbg-to-256 r g b)
+ engrave-faces-ansi-256-to-16-map)) 8)))
+
+;;;;;; 4-bit / 16-color
+
+(defvar engrave-faces-ansi-256-to-16-map
+ '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ 0 4 4 4 12 12 2 6 4 4 12 12 2 2 6 4
+ 12 12 2 2 2 6 12 12 10 10 10 10 14 12 10 10
+ 10 10 10 14 1 5 4 4 12 12 3 8 4 4 12 12
+ 2 2 6 4 12 12 2 2 2 6 12 12 10 10 10 10
+ 14 12 10 10 10 10 10 14 1 1 5 4 12 12 1 1
+ 5 4 12 12 3 3 8 4 12 12 2 2 2 6 12 12
+ 10 10 10 10 14 12 10 10 10 10 10 14 1 1 1 5
+ 12 12 1 1 1 5 12 12 1 1 1 5 12 12 3 3
+ 3 7 12 12 10 10 10 10 14 12 10 10 10 10 10 14
+ 9 9 9 9 13 12 9 9 9 9 13 12 9 9 9 9
+ 13 12 9 9 9 9 13 12 11 11 11 11 7 12 10 10
+ 10 10 10 14 9 9 9 9 9 13 9 9 9 9 9 13
+ 9 9 9 9 9 13 9 9 9 9 9 13 9 9 9 9
+ 9 13 11 11 11 11 11 15 0 0 0 0 0 0 8 8
+ 8 8 8 8 7 7 7 7 7 7 15 15 15 15 15 15))
+
+(defun engrave-faces-ansi-color-4bit-code (r g b &optional background)
+ "Convert the (R G B) colour code to a correspanding 4bit ansi escape
sequence."
+ (format "\uE000[%sm"
+ (pcase (nth (engrave-faces-ansi-color-rbg-to-256 r g b)
+ engrave-faces-ansi-256-to-16-map)
+ ((and (pred (> 8)) n)
+ (+ 30 (if background 10 0) n))
+ (n
+ (format "1;%d" (+ 22 (if background 10 0) n))))))
+
+;;;;;; 8-bit / 256-color
+
+(defvar engrave-faces-ansi-color-6cube-values '(0 95 135 175 215 255))
+(defun engrave-faces-ansi-color-to-6cube (value)
+ "Map VALUE to the associated 6x6 colour cube value."
+ (pcase value
+ ((pred (> 48)) 0)
+ ((pred (> 114)) 1)
+ (_ (/ (- value 35) 40))))
+
+(defun engrave-faces-ansi-color-8bit-code (r g b &optional background)
+ "Convert the (R G B) colour code to a correspanding 8bit ansi escape
sequence."
+ (format (if background "\uE000[48;5;%dm" "\uE000[38;5;%dm")
+ (engrave-faces-ansi-color-rbg-to-256 r g b)))
+
+(defun engrave-faces-ansi-color-rbg-to-256 (r g b &optional background)
+ "Convert the (R G B) colour code to the nearest 256-colour."
+ (let ((6cube-r (engrave-faces-ansi-color-to-6cube r))
+ (6cube-g (engrave-faces-ansi-color-to-6cube g))
+ (6cube-b (engrave-faces-ansi-color-to-6cube b)))
+ (let ((nearest-r (nth 6cube-r engrave-faces-ansi-color-6cube-values))
+ (nearest-g (nth 6cube-g engrave-faces-ansi-color-6cube-values))
+ (nearest-b (nth 6cube-b engrave-faces-ansi-color-6cube-values)))
+ (if (and (= nearest-r r) (= nearest-g g) (= nearest-b b))
+ (+ 16 (* 36 6cube-r) (* 6 6cube-g) 6cube-b)
+ (let* ((grey-avg (/ (+ r g b) 3))
+ (grey-index (if (> grey-avg 238) 23
+ (/ (- grey-avg 3) 10)))
+ (grey (+ 8 (* 10 grey-index))))
+ (if (> (engrave-faces-ansi-color-dist-squared (list grey grey grey)
+ (list r g b))
+ (engrave-faces-ansi-color-dist-squared (list nearest-r
nearest-g nearest-b)
+ (list r g b)))
+ (+ 232 grey-index)
+ (+ 16 (* 36 6cube-r) (* 6 6cube-g) 6cube-b)))))))
+
+
+;;;;;; 24-bit / 16m-color
+
+(defun engrave-faces-ansi-color-24bit-code (r g b &optional background)
+ (format (if background "\uE000[48;2;%d;%d;%dm" "\uE000[38;2;%d;%d;%dm") r g
b))
+
+;;; Applying the transformation
+
+(defun engrave-faces-ansi-face-apply (faces content)
+ "TODO record faces, and use `engrave-faces-ansi-face-nesting' to diff
properties
+with parent form more intelligent use of escape codes, and renewing properties
which
+are collateral damage from \"[0m\"."
+ (let* ((face-str (engrave-faces-ansi-code (engrave-faces-merge-attributes
faces))))
+ (concat face-str content (if (string= face-str "") "" "\uE000[0m"))))
+
+(defun engrave-faces-unescape-escape ()
+ (goto-char (point-min))
+ (while (re-search-forward "\uE000" nil t)
+ (replace-match "\e")))
+
+;;;###autoload
+(engrave-faces-define-backend "ansi" ".txt" #'engrave-faces-ansi-face-apply nil
+ (lambda () (ansi-color-apply-on-region
(point-min) (point-max) t)))
+(add-hook 'engrave-faces-ansi-after-hook #'engrave-faces-unescape-escape)
- [elpa] externals/engrave-faces 7fc664a 20/36: Add interactive commands for backends, (continued)
- [elpa] externals/engrave-faces 7fc664a 20/36: Add interactive commands for backends, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces ccebbdd 18/36: Add the org-block face to the preset, improve doc, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 2fee4f7 24/36: Create engrave-faces-BACKEND-file command, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 2b03748 26/36: html: set page bg to default face bg (if given), ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 1f68496 27/36: LaTeX: use named colour for fg when possible, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 8bbaaf8 28/36: Missing subr-x requirement, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 8b5e1fc 29/36: Move copyright to the FSF, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 67de75f 31/36: html: allow for css classes without a :slug, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 581b594 33/36: html: apply background & foreground color to page, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 1d73b8e 23/36: Fix inaccurate comments, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 4e6026e 21/36: New backend: ANSI,
ELPA Syncer <=
- [elpa] externals/engrave-faces d4b95ce 16/36: Replace apply append with mapcan, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 69f0e59 22/36: New backend: HTML, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces e22391c 35/36: latex: refactor initial \color string insertion, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 95d25d4 36/36: minor refactor: face extraction from text property, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 97c9ad7 25/36: When style is missing attribute, don't check face, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces e9a9b37 17/36: More face inheritance form edge cases, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces 36320d5 34/36: Declare ansi-color-apply-on-region function, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces fdfaf14 30/36: Set the :group in defcustom statements, ELPA Syncer, 2021/08/31
- [elpa] externals/engrave-faces e063673 32/36: html: add support for weight and height, ELPA Syncer, 2021/08/31