Function: majutsu-interactive--build-hunk-patch

majutsu-interactive--build-hunk-patch is a natively compiled function defined in majutsu-interactive.el.

Signature

(majutsu-interactive--build-hunk-patch SECTION SPEC &optional INVERT)

Documentation

Build a patch hunk for SECTION using SPEC and INVERT.

SPEC is :all or list of (BEG . END) ranges. When INVERT is non-nil, invert selection for change lines. Return a hunk string or nil when no change lines remain.

Source Code

;; Defined in /nix/store/jagqw3nms546pad0gxi5f3wsckk6pji7-emacs-packages-deps/share/emacs/site-lisp/majutsu-interactive.el
(defun majutsu-interactive--build-hunk-patch (section spec &optional invert)
  "Build a patch hunk for SECTION using SPEC and INVERT.
SPEC is `:all' or list of (BEG . END) ranges.
When INVERT is non-nil, invert selection for change lines.
Return a hunk string or nil when no change lines remain."
  (let* ((header (majutsu-interactive--hunk-header section))
         (parsed (majutsu-interactive--parse-hunk-header header))
         (lines (majutsu-interactive--group-hunk-lines
                 (majutsu-interactive--hunk-lines section)))
         (ranges (cond
                  ((eq spec :all) nil)
                  ((consp spec) (if (and spec (consp (car spec))) spec (list spec)))
                  (t nil)))
         (decided
          (mapcar (lambda (line)
                    (pcase-let ((`(,text ,type ,bol ,eol ,meta) line))
                      (let ((selected (if ranges
                                          (majutsu-interactive--line-selected-p
                                           bol eol ranges)
                                        t)))
                        (list text type meta
                              (if invert (not selected) selected)))))
                  lines))
         (selected-lines nil)
         (old-skip 0)
         (new-skip 0)
         (old-len 0)
         (new-len 0)
         (has-change nil)
         (started nil)
         (rest decided))
    (while rest
      (pcase-let ((`(,text ,type ,meta ,include-change) (car rest)))
        (setq rest (cdr rest))
        (if (not (pcase type
                   ('context t)
                   ('added include-change)
                   ('removed t)))
            (unless started
              (pcase type
                ('added (setq new-skip (1+ new-skip)))
                ('removed (setq old-skip (1+ old-skip)))))
          (setq started t)
          (when (and (memq type '(added removed)) include-change)
            (setq has-change t))
          (cond
           ((and (eq type 'removed) (not include-change))
            ;; The line stays in both files.  A plain context conversion
            ;; is wrong when it carries a no-newline marker and kept
            ;; added lines extend the new file past it: the new file
            ;; copy must gain a newline, so remove and re-add it.
            (setq old-len (1+ old-len))
            (setq new-len (1+ new-len))
            (if (and meta
                     (seq-some (lambda (entry)
                                 (and (eq (nth 1 entry) 'added)
                                      (nth 3 entry)))
                               rest))
                (progn
                  (push text selected-lines)
                  (push meta selected-lines)
                  (push (concat "+" (substring text 1)) selected-lines))
              (push (concat " " (substring text 1)) selected-lines)
              (when meta (push meta selected-lines))))
           (t
            (pcase type
              ('context (setq old-len (1+ old-len))
                        (setq new-len (1+ new-len)))
              ('removed (setq old-len (1+ old-len)))
              ('added (setq new-len (1+ new-len))))
            (push text selected-lines)
            (when meta (push meta selected-lines)))))))
    (when (and has-change selected-lines)
      (let* ((body (mapconcat #'identity (nreverse selected-lines) ""))
             (hunk-header
              (if parsed
                  (pcase-let ((`(,old-start ,_old-len ,new-start ,_new-len ,suffix) parsed))
                    (majutsu-interactive--format-hunk-header
                     (+ old-start old-skip)
                     old-len
                     (+ new-start new-skip)
                     new-len
                     suffix))
                header)))
        (concat hunk-header body)))))