diff options
| author | Lars Ingebrigtsen | 2022-04-14 01:00:44 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-04-14 01:00:44 +0200 |
| commit | 800998808a1ebf83263ffbdea833c155fcbae7a6 (patch) | |
| tree | 681525e5aa9743eaef1369b34e896888cec79f71 | |
| parent | 864c8013fdd0a548d98d81dd21af2f88f207858a (diff) | |
| download | emacs-800998808a1ebf83263ffbdea833c155fcbae7a6.tar.gz emacs-800998808a1ebf83263ffbdea833c155fcbae7a6.zip | |
Allow putting alternating colors on vtable rows
* doc/misc/vtable.texi (Making A Table): Document it.
* lisp/emacs-lisp/vtable.el (vtable): Add :row-colors.
(make-vtable): Ditto.
(vtable--compute-colors, vtable--color-blend): New functions.
(vtable--insert-line): Take a line number argument and adjust
callers.
| -rw-r--r-- | doc/misc/vtable.texi | 12 | ||||
| -rw-r--r-- | lisp/emacs-lisp/vtable.el | 61 |
2 files changed, 61 insertions, 12 deletions
diff --git a/doc/misc/vtable.texi b/doc/misc/vtable.texi index 4f7b722a289..77cb8663af4 100644 --- a/doc/misc/vtable.texi +++ b/doc/misc/vtable.texi | |||
| @@ -387,11 +387,21 @@ The face to be used. This defaults to @code{vtable}. This face | |||
| 387 | doesn't override the faces in the data, or the faces supplied by the | 387 | doesn't override the faces in the data, or the faces supplied by the |
| 388 | getter and formatter functions. | 388 | getter and formatter functions. |
| 389 | 389 | ||
| 390 | @item :row-colors | ||
| 391 | If present, this should be a list of color names to be used as the | ||
| 392 | background color on the rows. If there are fewer colors here than | ||
| 393 | there are rows, the rows will be repeated. The most common use | ||
| 394 | case here is to have alternating background colors on the rows, so | ||
| 395 | this would usually be a list of two colors. | ||
| 396 | |||
| 390 | @item :column-colors | 397 | @item :column-colors |
| 391 | If present, this should be a list of color names to be used as the | 398 | If present, this should be a list of color names to be used as the |
| 392 | background color on the columns. If there are fewer colors here than | 399 | background color on the columns. If there are fewer colors here than |
| 393 | there are columns, the colors will be repeated. The most common use | 400 | there are columns, the colors will be repeated. The most common use |
| 394 | case here is to have alternating background colors on the columns. | 401 | case here is to have alternating background colors on the columns, so |
| 402 | this would usually be a list of two colors. If both | ||
| 403 | @code{:row-colors} and @code{:column-colors} is present, the colors | ||
| 404 | will be ``blended'' to produce the final colors in the table. | ||
| 395 | 405 | ||
| 396 | @item :actions | 406 | @item :actions |
| 397 | This uses the same syntax as @code{define-keymap}, but doesn't refer | 407 | This uses the same syntax as @code{define-keymap}, but doesn't refer |
diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el index 3e521c94a5c..e0010434447 100644 --- a/lisp/emacs-lisp/vtable.el +++ b/lisp/emacs-lisp/vtable.el | |||
| @@ -64,6 +64,8 @@ | |||
| 64 | (sort-by :initarg :sort-by :accessor vtable-sort-by) | 64 | (sort-by :initarg :sort-by :accessor vtable-sort-by) |
| 65 | (ellipsis :initarg :ellipsis :accessor vtable-ellipsis) | 65 | (ellipsis :initarg :ellipsis :accessor vtable-ellipsis) |
| 66 | (column-colors :initarg :column-colors :accessor vtable-column-colors) | 66 | (column-colors :initarg :column-colors :accessor vtable-column-colors) |
| 67 | (row-colors :initarg :row-colors :accessor vtable-row-colors) | ||
| 68 | (-cached-colors :initform nil :accessor vtable--cached-colors) | ||
| 67 | (-cache :initform (make-hash-table :test #'equal))) | 69 | (-cache :initform (make-hash-table :test #'equal))) |
| 68 | "A object to hold the data for a table.") | 70 | "A object to hold the data for a table.") |
| 69 | 71 | ||
| @@ -91,6 +93,7 @@ | |||
| 91 | sort-by | 93 | sort-by |
| 92 | (ellipsis t) | 94 | (ellipsis t) |
| 93 | (insert t) | 95 | (insert t) |
| 96 | row-colors | ||
| 94 | column-colors) | 97 | column-colors) |
| 95 | "Create and insert a vtable at point. | 98 | "Create and insert a vtable at point. |
| 96 | The vtable object is returned. If INSERT is nil, the table won't | 99 | The vtable object is returned. If INSERT is nil, the table won't |
| @@ -130,10 +133,15 @@ be inserted." | |||
| 130 | :keymap keymap | 133 | :keymap keymap |
| 131 | :separator-width separator-width | 134 | :separator-width separator-width |
| 132 | :sort-by sort-by | 135 | :sort-by sort-by |
| 136 | :row-colors row-colors | ||
| 133 | :column-colors column-colors | 137 | :column-colors column-colors |
| 134 | :ellipsis ellipsis))) | 138 | :ellipsis ellipsis))) |
| 135 | ;; Compute missing column data. | 139 | ;; Compute missing column data. |
| 136 | (setf (vtable-columns table) (vtable--compute-columns table)) | 140 | (setf (vtable-columns table) (vtable--compute-columns table)) |
| 141 | ;; Compute colors if we have to mix them. | ||
| 142 | (when (and row-colors column-colors) | ||
| 143 | (setf (vtable--cached-colors table) | ||
| 144 | (vtable--compute-colors row-colors column-colors))) | ||
| 137 | (unless sort-by | 145 | (unless sort-by |
| 138 | (seq-do-indexed (lambda (column index) | 146 | (seq-do-indexed (lambda (column index) |
| 139 | (when (vtable-column-primary column) | 147 | (when (vtable-column-primary column) |
| @@ -144,6 +152,20 @@ be inserted." | |||
| 144 | (vtable-insert table)) | 152 | (vtable-insert table)) |
| 145 | table)) | 153 | table)) |
| 146 | 154 | ||
| 155 | (defun vtable--compute-colors (row-colors column-colors) | ||
| 156 | (cl-loop for row in row-colors | ||
| 157 | collect (cl-loop for column in column-colors | ||
| 158 | collect (vtable--color-blend row column)))) | ||
| 159 | |||
| 160 | ;;; FIXME: This is probably not the right way to blend two colors, is | ||
| 161 | ;;; it? | ||
| 162 | (defun vtable--color-blend (color1 color2) | ||
| 163 | (cl-destructuring-bind (r g b) | ||
| 164 | (mapcar (lambda (n) (* (/ n 2) 255.0)) | ||
| 165 | (cl-mapcar #'+ (color-name-to-rgb color1) | ||
| 166 | (color-name-to-rgb color2))) | ||
| 167 | (format "#%02X%02X%02X" r g b))) | ||
| 168 | |||
| 147 | ;;; Interface utility functions. | 169 | ;;; Interface utility functions. |
| 148 | 170 | ||
| 149 | (defun vtable-current-table () | 171 | (defun vtable-current-table () |
| @@ -219,7 +241,8 @@ If it can't be found, return nil and don't move point." | |||
| 219 | (error "Can't find the old object")) | 241 | (error "Can't find the old object")) |
| 220 | (setcar (cdr objects) object)) | 242 | (setcar (cdr objects) object)) |
| 221 | ;; Then update the cache... | 243 | ;; Then update the cache... |
| 222 | (let ((line (assq old-object (car (vtable--cache table))))) | 244 | (let* ((line-number (seq-position old-object (car (vtable--cache table)))) |
| 245 | (line (elt (car (vtable--cache table)) line-number))) | ||
| 223 | (unless line | 246 | (unless line |
| 224 | (error "Can't find cached object")) | 247 | (error "Can't find cached object")) |
| 225 | (setcar line object) | 248 | (setcar line object) |
| @@ -230,7 +253,8 @@ If it can't be found, return nil and don't move point." | |||
| 230 | (let ((keymap (get-text-property (point) 'keymap)) | 253 | (let ((keymap (get-text-property (point) 'keymap)) |
| 231 | (start (point))) | 254 | (start (point))) |
| 232 | (delete-line) | 255 | (delete-line) |
| 233 | (vtable--insert-line table line (nth 1 (vtable--cache table)) | 256 | (vtable--insert-line table line line-number |
| 257 | (nth 1 (vtable--cache table)) | ||
| 234 | (vtable--spacer table)) | 258 | (vtable--spacer table)) |
| 235 | (add-text-properties start (point) (list 'keymap keymap | 259 | (add-text-properties start (point) (list 'keymap keymap |
| 236 | 'vtable table)))) | 260 | 'vtable table)))) |
| @@ -285,7 +309,10 @@ This also updates the displayed table." | |||
| 285 | (unless (vtable-goto-object after-object) | 309 | (unless (vtable-goto-object after-object) |
| 286 | (vtable-end-of-table)))) | 310 | (vtable-end-of-table)))) |
| 287 | (let ((start (point))) | 311 | (let ((start (point))) |
| 288 | (vtable--insert-line table line (nth 1 cache) (vtable--spacer table)) | 312 | ;; FIXME: We have to adjust colors in lines below this if we |
| 313 | ;; have :row-colors. | ||
| 314 | (vtable--insert-line table line 0 | ||
| 315 | (nth 1 cache) (vtable--spacer table)) | ||
| 289 | (add-text-properties start (point) (list 'keymap keymap | 316 | (add-text-properties start (point) (list 'keymap keymap |
| 290 | 'vtable table))) | 317 | 'vtable table))) |
| 291 | ;; We may have inserted a non-numerical value into a previously | 318 | ;; We may have inserted a non-numerical value into a previously |
| @@ -374,20 +401,26 @@ This also updates the displayed table." | |||
| 374 | (setq start (point))) | 401 | (setq start (point))) |
| 375 | (vtable--sort table) | 402 | (vtable--sort table) |
| 376 | ;; Insert the data. | 403 | ;; Insert the data. |
| 377 | (dolist (line (car (vtable--cache table))) | 404 | (let ((line-number 0)) |
| 378 | (vtable--insert-line table line widths spacer | 405 | (dolist (line (car (vtable--cache table))) |
| 379 | ellipsis ellipsis-width)) | 406 | (vtable--insert-line table line line-number widths spacer |
| 407 | ellipsis ellipsis-width) | ||
| 408 | (setq line-number (1+ line-number)))) | ||
| 380 | (add-text-properties start (point) | 409 | (add-text-properties start (point) |
| 381 | (list 'keymap (vtable--make-keymap table) | 410 | (list 'keymap (vtable--make-keymap table) |
| 382 | 'rear-nonsticky t | 411 | 'rear-nonsticky t |
| 383 | 'vtable table)) | 412 | 'vtable table)) |
| 384 | (goto-char start))) | 413 | (goto-char start))) |
| 385 | 414 | ||
| 386 | (defun vtable--insert-line (table line widths spacer | 415 | (defun vtable--insert-line (table line line-number widths spacer |
| 387 | &optional ellipsis ellipsis-width) | 416 | &optional ellipsis ellipsis-width) |
| 388 | (let ((start (point)) | 417 | (let ((start (point)) |
| 389 | (columns (vtable-columns table)) | 418 | (columns (vtable-columns table)) |
| 390 | (colors (vtable-column-colors table))) | 419 | (column-colors |
| 420 | (if (vtable-row-colors table) | ||
| 421 | (elt (vtable--cached-colors table) | ||
| 422 | (mod line-number (length (vtable-row-colors table)))) | ||
| 423 | (vtable-column-colors table)))) | ||
| 391 | (seq-do-indexed | 424 | (seq-do-indexed |
| 392 | (lambda (elem index) | 425 | (lambda (elem index) |
| 393 | (let ((value (nth 0 elem)) | 426 | (let ((value (nth 0 elem)) |
| @@ -449,14 +482,20 @@ This also updates the displayed table." | |||
| 449 | (list 'space | 482 | (list 'space |
| 450 | :width (list spacer))))) | 483 | :width (list spacer))))) |
| 451 | (put-text-property start (point) 'vtable-column index) | 484 | (put-text-property start (point) 'vtable-column index) |
| 452 | (when colors | 485 | (when column-colors |
| 453 | (add-face-text-property | 486 | (add-face-text-property |
| 454 | start (point) | 487 | start (point) |
| 455 | (list :background | 488 | (list :background |
| 456 | (elt colors (mod index (length colors))))))))) | 489 | (elt column-colors (mod index (length column-colors))))))))) |
| 457 | (cdr line)) | 490 | (cdr line)) |
| 458 | (insert "\n") | 491 | (insert "\n") |
| 459 | (put-text-property start (point) 'vtable-object (car line)))) | 492 | (put-text-property start (point) 'vtable-object (car line)) |
| 493 | (unless column-colors | ||
| 494 | (when-let ((row-colors (vtable-row-colors table))) | ||
| 495 | (add-face-text-property | ||
| 496 | start (point) | ||
| 497 | (list :background | ||
| 498 | (elt row-colors (mod line-number (length row-colors))))))))) | ||
| 460 | 499 | ||
| 461 | (defun vtable--cache-key () | 500 | (defun vtable--cache-key () |
| 462 | (cons (frame-terminal) (window-width))) | 501 | (cons (frame-terminal) (window-width))) |