Function: ghostel--line-mode-enter

ghostel--line-mode-enter is a natively compiled function defined in ghostel-line-mode.el.

Signature

(ghostel--line-mode-enter)

Documentation

Set up line mode in the current buffer.

Internal helper used by the interactive ghostel-line-mode entry path and the auto-resume path in ghostel--line-mode-try-resume. Returns t on success, nil when the prompt cannot be located (no cursor and no OSC 133 marker — e.g. the prompt has not been redrawn yet after an alt-screen exit). Caller decides whether "no prompt" is a user-error or a deferred retry.

Assumes ghostel--term is non-nil and the buffer is not already in line mode (the interactive entry validates these).

Source Code

;; Defined in /nix/store/1252krff0gb2kisjcpp45m50cpdskfrl-emacs-packages-deps/share/emacs/site-lisp/ghostel-line-mode.el
(defun ghostel--line-mode-enter ()
  "Set up line mode in the current buffer.
Internal helper used by the interactive `ghostel-line-mode' entry
path and the auto-resume path in
`ghostel--line-mode-try-resume'.  Returns t on success, nil when
the prompt cannot be located (no cursor and no OSC 133 marker —
e.g. the prompt has not been redrawn yet after an alt-screen
exit).  Caller decides whether \"no prompt\" is a user-error or a
deferred retry.

Assumes `ghostel--term' is non-nil and the buffer is not already
in line mode (the interactive entry validates these)."
  (let ((prompt-end (ghostel-input-start-point))
        (was-frozen (eq ghostel--input-mode 'copy)))
    (when prompt-end
      (pcase ghostel--input-mode
        ('copy  (ghostel--leave-readonly-state))
        ('emacs (ghostel--leave-readonly-state)))
      ;; Line mode is the one user-editable ghostel state.  The rendered
      ;; scrollback is still protected below with read-only text properties.
      (setq buffer-read-only nil)
      ;; Copy mode froze the redraw timer; line mode is live, so the
      ;; timer must be running again before we exit this function or
      ;; the prompt sits there with no scheduled redraw until the next
      ;; PTY byte arrives.  `ghostel--invalidate' is idempotent, so the
      ;; emacs/semi-char paths (timer already live) are unaffected.
      (when (and was-frozen ghostel--term)
        (ghostel--invalidate))
      ;; Save `cursor-type' and force the editor's default for the
      ;; duration of line mode.  The user moves point freely here, so
      ;; the cursor must be visible regardless of any CSI ?25l the
      ;; running terminal app issued in semi-char/char mode.
      ;; `ghostel--apply-cursor-style' is a no-op in line mode, so
      ;; further terminal requests are ignored until teardown.
      (ghostel--cursor-blink-stop)
      (setq ghostel--line-mode-saved-cursor-type (list cursor-type))
      (setq cursor-type (default-value 'cursor-type))
      ;; If the user already typed something at this prompt via the
      ;; PTY (e.g. before switching from semi-char to line mode), the
      ;; renderer painted those cells with `ghostel-input'.  Adopt
      ;; the span as the initial line-mode input so the user does not
      ;; lose their typing.
      (let ((input-end (ghostel--line-mode-input-end-pos prompt-end)))
        ;; Trim only PURE-whitespace tails past the input.  Status
        ;; bars / multi-line UI drawn below the prompt row stay put.
        (ghostel--line-mode-trim-trailing-blank input-end)
        (setq ghostel--line-input-start (copy-marker prompt-end nil))
        (set-marker-insertion-type ghostel--line-input-start nil)
        (setq ghostel--line-input-end (copy-marker input-end t))
        (set-marker-insertion-type ghostel--line-input-end t)
        ;; Remember how many chars the shell's readline currently
        ;; holds for us — we'll erase them via backspaces before the
        ;; next PTY write so the shell doesn't append our line to its
        ;; existing input and echo a duplicated prefix.
        (setq ghostel--line-mode-adopted-count (- input-end prompt-end)))
      (setq ghostel--line-mode-history-index nil)
      (setq ghostel--char-mode-override-active nil)
      ;; A deliberate alt-screen entry must survive the next redraw's
      ;; auto-pause, and supersedes any armed sentinel.
      (setq ghostel--line-mode-on-alt-screen (ghostel-alt-screen-p))
      (setq ghostel--line-mode-paused nil)
      (setq ghostel--input-mode 'line)
      (ghostel--sync-read-only)
      (use-local-map ghostel-line-mode-map)
      (setq ghostel--mode-line-tag (ghostel--mode-line-tag-make 'line ":Line"))
      (ghostel--mode-line-refresh)
      ;; Protect everything before the input marker with a read-only
      ;; text property so commands that would modify the buffer
      ;; (self-insert, delete-char, yank, …) signal `text-read-only'
      ;; when point is in the scrollback / previous output region.
      ;; The redraw path binds `inhibit-read-only' so it is
      ;; unaffected.
      (ghostel--line-mode-apply-readonly
       (marker-position ghostel--line-input-start))
      ;; Make sure the adopted input carries `ghostel-input' (the
      ;; renderer should have applied it for PTY-typed cells; reapply
      ;; for consistency, and so URL detection skips the region even
      ;; if the property was missed for some cells).
      (let ((start-pos (marker-position ghostel--line-input-start))
            (end-pos (marker-position ghostel--line-input-end)))
        (when (< start-pos end-pos)
          (let ((inhibit-read-only t))
            (put-text-property start-pos end-pos 'ghostel-input t))))
      ;; Place point at end of (any adopted) input so the user
      ;; continues typing where the shell left them.
      (goto-char (marker-position ghostel--line-input-end))
      ;; Arm undo recording now that the entry plumbing is done, so the
      ;; user's first edit is the first thing recorded.
      (setq buffer-undo-list nil)
      (ghostel--line-mode-maybe-prespawn-bash-completion)
      t)))