<commit_before>(defpackage :lem.listener-mode
  (:use :cl :lem)
  (:export :listener-prompt-attribute
           :listener-mode
           :*listener-mode-keymap*
           :listener-start
           :listener-update-point
           :listener-reset-prompt
           :listener-return
           :listener-prev-input
           :listener-next-input
           :listener-reset-interactive
           :listener-get-prompt-function
           :listener-check-confirm-function
           :listener-confirm-function
           :clear-listener))
(in-package :lem.listener-mode)

(define-attribute listener-prompt-attribute
  (:light :foreground "blue" :bold-p t)
  (:dark :foreground "cyan" :bold-p t))

(defvar %listener-point-indicator (gensym))
(defmacro %listener-point (buffer)
  `(buffer-value ,buffer %listener-point-indicator))

(defvar %listener-history-indicator (gensym))
(defmacro %listener-history ()
  `(buffer-value (current-buffer) %listener-history-indicator))

(define-editor-variable listener-get-prompt-function)
(define-editor-variable listener-check-confirm-function)
(define-editor-variable listener-confirm-function)

(define-minor-mode listener-mode
    (:name "listener"
     :keymap *listener-mode-keymap*)
  (setf (variable-value 'enable-syntax-highlight) nil)
  (unless (%listener-history)
    (setf (%listener-history)
          (lem.history:make-history))))

(define-key *listener-mode-keymap* "C-m" 'listener-return)
(define-key *listener-mode-keymap* "M-p" 'listener-prev-input)
(define-key *listener-mode-keymap* "M-n" 'listener-next-input)
(define-key *listener-mode-keymap* "M-r" 'listener-previous-matching-input)
(define-key *listener-mode-keymap* "C-c M-o" 'listener-clear-buffer)
(define-key *listener-mode-keymap* "C-c C-u" 'listener-clear-input)

(defun listener-start-point (buffer)
  (%listener-point buffer))

(defun listener-start (buffer-name mode)
  (let ((buffer (make-buffer buffer-name)))
    (setf (current-window) (pop-to-buffer buffer))
    (funcall mode)
    (listener-reset-prompt buffer)))

(defun listener-update-point (&optional (point (current-point)))
  (when (%listener-point (point-buffer point))
    (delete-point (%listener-point (point-buffer point))))
  (setf (%listener-point (point-buffer point))
        (if point
            (copy-point point :right-inserting)
            (copy-point (current-point) :right-inserting))))

(defun listener-reset-prompt (&optional (buffer (current-buffer)))
  (let ((cur-point (buffer-point buffer)))
    (buffer-end cur-point)
    (unless (start-line-p cur-point)
      (insert-character cur-point #\newline 1)
      (buffer-end cur-point))
    (insert-string cur-point
                   (princ-to-string
                    (funcall
                     (variable-value 'listener-get-prompt-function :buffer buffer)))
                   :attribute 'listener-prompt-attribute
                   :read-only t
                   :field t)
    (buffer-end cur-point)
    (buffer-undo-boundary buffer)
    (listener-update-point cur-point)))

(define-command listener-return () ()
  (with-point ((point (buffer-end (current-point)) :left-inserting))
    (if (not (funcall (variable-value 'listener-check-confirm-function) point))
        (insert-character point #\newline)
        (let ((start (listener-start-point (current-buffer))))
          (unless (point< start point)
            (listener-reset-prompt)
            (return-from listener-return t))
          (let ((str (points-to-string start point)))
            (lem.history:add-history (%listener-history) str)<commit_msg>fix listener-return<commit_after>(defpackage :lem.listener-mode
  (:use :cl :lem)
  (:export :listener-prompt-attribute
           :listener-mode
           :*listener-mode-keymap*
           :listener-start
           :listener-update-point
           :listener-reset-prompt
           :listener-return
           :listener-prev-input
           :listener-next-input
           :listener-reset-interactive
           :listener-get-prompt-function
           :listener-check-confirm-function
           :listener-confirm-function
           :clear-listener))
(in-package :lem.listener-mode)

(define-attribute listener-prompt-attribute
  (:light :foreground "blue" :bold-p t)
  (:dark :foreground "cyan" :bold-p t))

(defvar %listener-point-indicator (gensym))
(defmacro %listener-point (buffer)
  `(buffer-value ,buffer %listener-point-indicator))

(defvar %listener-history-indicator (gensym))
(defmacro %listener-history ()
  `(buffer-value (current-buffer) %listener-history-indicator))

(define-editor-variable listener-get-prompt-function)
(define-editor-variable listener-check-confirm-function)
(define-editor-variable listener-confirm-function)

(define-minor-mode listener-mode
    (:name "listener"
     :keymap *listener-mode-keymap*)
  (setf (variable-value 'enable-syntax-highlight) nil)
  (unless (%listener-history)
    (setf (%listener-history)
          (lem.history:make-history))))

(define-key *listener-mode-keymap* "C-m" 'listener-return)
(define-key *listener-mode-keymap* "M-p" 'listener-prev-input)
(define-key *listener-mode-keymap* "M-n" 'listener-next-input)
(define-key *listener-mode-keymap* "M-r" 'listener-previous-matching-input)
(define-key *listener-mode-keymap* "C-c M-o" 'listener-clear-buffer)
(define-key *listener-mode-keymap* "C-c C-u" 'listener-clear-input)

(defun listener-start-point (buffer)
  (%listener-point buffer))

(defun listener-start (buffer-name mode)
  (let ((buffer (make-buffer buffer-name)))
    (setf (current-window) (pop-to-buffer buffer))
    (funcall mode)
    (listener-reset-prompt buffer)))

(defun listener-update-point (&optional (point (current-point)))
  (when (%listener-point (point-buffer point))
    (delete-point (%listener-point (point-buffer point))))
  (setf (%listener-point (point-buffer point))
        (if point
            (copy-point point :right-inserting)
            (copy-point (current-point) :right-inserting))))

(defun listener-reset-prompt (&optional (buffer (current-buffer)))
  (let ((cur-point (buffer-point buffer)))
    (buffer-end cur-point)
    (unless (start-line-p cur-point)
      (insert-character cur-point #\newline 1)
      (buffer-end cur-point))
    (insert-string cur-point
                   (princ-to-string
                    (funcall
                     (variable-value 'listener-get-prompt-function :buffer buffer)))
                   :attribute 'listener-prompt-attribute
                   :read-only t
                   :field t)
    (buffer-end cur-point)
    (buffer-undo-boundary buffer)
    (listener-update-point cur-point)))

(define-command listener-return () ()
  (with-point ((point (buffer-end (current-point)) :left-inserting))
    (if (not (funcall (variable-value 'listener-check-confirm-function) point))
        (insert-character point #\newline)
        (let ((start (listener-start-point (current-buffer))))
          (unless (point<= start point)
            (listener-reset-prompt)
            (return-from listener-return t))
          (let ((str (points-to-string start point)))
            (lem.history:add-history (%listener-history) str)
{'fraction_non_alphanumeric': 0.1473831123517097, 'fraction_numerical': 0.0002791346824842987, 'mean_word_length': 2.9700831024930747, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2855596', 'n_tokens_mistral': 2236, 'n_tokens_neox': 2166, 'n_words': 440}