Function: csv--jit-align

csv--jit-align is a natively compiled function defined in csv-mode.el.

Signature

(csv--jit-align BEG END)

Source Code

;; Defined in /nix/store/3gmjnyw9n226b7k7jamikx980vf8267p-emacs-packages-deps/share/emacs/site-lisp/elpa/csv-mode-1.27/csv-mode.el
(defun csv--jit-align (beg end)
  (save-excursion
    ;; This is run with inhibit-modification-hooks set, so the overlays'
    ;; modification-hook doesn't work :-(
    (and csv--header-line
         (<= beg (overlay-end csv--header-line))
         (>= end (overlay-start csv--header-line))
         (csv--header-flush))
    ;; First, round up to a whole number of lines.
    (goto-char end)
    (unless (bolp) (forward-line 1) (setq end (point)))
    (goto-char beg)
    (unless (bolp) (forward-line 1) (setq beg (point)))
    (csv--jit-unalign beg end)
    (put-text-property beg end 'csv--jit t)

    (pcase-let* ((`(,column-widths ,field-widths) (csv--column-widths beg end))
                 (changed (csv--jit-merge-columns column-widths))
                 (ellipsis-width (csv--ellipsis-width)))
      (when changed
        ;; Do it after the current redisplay is over.
        (run-with-timer jit-lock-context-time nil #'csv--jit-flush beg end))

      ;; Align fields:
      (goto-char beg)
      (while (< (point) end)
	(unless (csv-not-looking-at-record)
          (let ((w csv--jit-columns)
                (widths-config csv--config-column-widths)
                (column 0))      ;Desired position of left-side of this column.
            (while (and w (not (eolp)))
              (let* ((field-beg (point))
                     (width-config (pop widths-config))
                     (align-padding (if (bolp) 0 csv-align-padding))
                     (left-padding 0) (right-padding 0)
                     (field-width (pop field-widths))
                     (column-width
                      (min (max csv-align-min-width
                                (car (pop w)))
                           (or width-config
                               ;; Don't apply csv-align-max-width
                               ;; to the last field!
                               (if w csv-align-max-width
                                 most-positive-fixnum))))
                     (x (- column-width field-width)) ; Required padding.
                     (truncate nil))
                (csv-end-of-field)
                ;; beg = beginning of current field
                ;; end = (point) = end of current field
                (when (< x 0)
                  (setq truncate (max column
                                      (+ column column-width
                                         align-padding (- ellipsis-width))))
                  (setq x 0))
                ;; Compute required padding:
                (pcase csv-align-style
                  ('left
                   ;; Left align -- pad on the right:
                   (setq left-padding align-padding
                         right-padding x))
                  ('right
                   ;; Right align -- pad on the left:
                   (setq left-padding (+ align-padding x)))
                  ('auto
                   ;; Auto align -- left align text, right align numbers:
                   (if (string-match "\\`[-+.[:digit:]]+\\'"
                                     (buffer-substring field-beg (point)))
                       ;; Right align -- pad on the left:
                       (setq left-padding (+ align-padding x))
                     ;; Left align -- pad on the right:
                     (setq left-padding align-padding
                           right-padding x)))
                  ('centre
                   ;; Centre -- pad on both left and right:
                   (let ((y (/ x 2)))   ; truncated integer quotient
                     (setq left-padding (+ align-padding y)
                           right-padding (- x y)))))

                (cond

                 ((or (memq 'csv buffer-invisibility-spec)
                      ;; For TSV, hidden or not doesn't make much difference,
                      ;; but the behavior is slightly better when we "hide"
                      ;; the TABs with a `display' property than if we add
                      ;; before/after-strings.
                      (tsv--mode-p))

                  ;; Hide separators...
                  ;; Merge right-padding from previous field
                  ;; with left-padding from this field:
                  (if (zerop column)
                      (when (> left-padding 0)
                        ;; Display spaces before first field
                        ;; by overlaying first character:
			(csv--make-overlay
			 field-beg (1+ field-beg) nil nil nil
			 `(before-string ,(make-string left-padding ?\ )
                                         csv--jit t)))
                    ;; Display separator as spaces:
                    (with-silent-modifications
                      (put-text-property
                       (1- field-beg) field-beg
                       'display `(space :align-to
                                        ,(+ left-padding column))))))

                 (t ;; Do not hide separators...
                  (let ((overlay (csv--make-overlay field-beg (point)
                                                    nil nil t
                                                    '(csv--jit t))))
                    (when (> left-padding 0) ; Pad on the left.
                      ;; Display spaces before field:
                      (overlay-put overlay 'before-string
                                   (make-string left-padding ?\ )))
                    (unless (eolp)
                      (if (> right-padding 0) ; Pad on the right.
                          ;; Display spaces after field:
                          (overlay-put
                           overlay
                           'after-string (make-string right-padding ?\ )))))))
                (setq column (+ column column-width align-padding))
                ;; Do it after applying the property, so `move-to-column' can
                ;; take it into account.
                (when truncate
                  (let ((trunc-pos
                         (save-excursion
                           ;; ¡¡ BIG UGLY HACK !!
                           ;; `current-column' and `move-to-column' count
                           ;; text hidden with an ellipsis "as if" it were
                           ;; fully visible, which is completely wrong here,
                           ;; so circumvent this by temporarily pretending
                           ;; that `csv-truncate' is fully invisible (which
                           ;; isn't quite right either, but should work
                           ;; just well enough for us here).
                           (let ((buffer-invisibility-spec
                                  buffer-invisibility-spec))
                             (add-to-invisibility-spec 'csv-truncate)
                             (move-to-column truncate))
                           (point))))
                    (put-text-property trunc-pos (point)
                                       'invisible 'csv-truncate)
                    (when (> (- (point) trunc-pos) 1)
                      ;; Arrange to temporarily untruncate the string when
                      ;; cursor moves into it.
                      ;; FIXME: This only works if
                      ;; `global-disable-point-adjustment' is non-nil!
                      ;; Arguably this should be fixed by making
                      ;; point-adjustment code pay attention to
                      ;; cursor-sensor-functions!
                      (put-text-property
                       (1+ trunc-pos) (point)
                       'cursor-sensor-functions
                       (list #'csv-align--cursor-truncated)))))
                (unless (eolp) (forward-char)) ; Skip separator.
                ))))
	(forward-line)))
    `(jit-lock-bounds ,beg . ,end)))