Add new redvai.el

This commit is contained in:
Tristan D. 2025-01-31 12:30:01 +01:00
parent b3be9d2624
commit 589490128e
Signed by: tristan
SSH key fingerprint: SHA256:9oFM1J63hYWJjCnLG6C0fxBS15rwNcWwdQNMOHYKJ/4

View file

@ -0,0 +1,202 @@
;;; redvai.el --- Description -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2024 Tristan Druyen
;;
;; Filename: redvai-mini.el
;; Author: Tristan Druyen <tristand@nixos-fw16>
;; Maintainer: Tristan Druyen <tristand@nixos-fw16>
;; Created: Oktober 09, 2024
;; Modified: November 27, 2024
;; Version: 0.0.1
;; Keywords: convenience extensions tools
;; Homepage: https://git.vlt81.de/vault81/redvault-ai
;; Package-Requires: ((emacs "25.0"))
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;; - only tested on bleeding-edge emacs, might work on older versions
;; - needs to be compiled with dynamic module support
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Change log:
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
(require 's)
(require 'cl-lib)
(defface redvai-overlay-face
'((t :inherit shadow))
"Face for redvai overlay")
(defun redvai--set-overlay-text (ov completion)
"Set overlay OV with COMPLETION."
(save-restriction
(widen)
(let* ((suffix-replace-chars (overlay-get ov 'suffix-replace-chars))
(p-completion (propertize completion 'face 'redvai-overlay-face)))
(add-text-properties 0 1 '(cursor 1) p-completion)
(overlay-put ov 'after-string p-completion)
(overlay-put ov 'display (char-to-string ?\u200B)) ;; \u200B is a zero-width space. Trick to fix the wrong character inserted position.
(move-overlay ov (point) (+ (point) 1))
(overlay-put ov 'completion completion))))
(defvar-local redvai--overlay nil
"Overlay for redvai completion.")
(defconst redvai-completion-map (make-sparse-keymap)
"Keymap for Redvai completion overlay.")
(defun redvai--get-overlay ()
"Create or get overlay for redvai."
(unless (overlayp redvai--overlay)
(setq redvai--overlay (make-overlay 1 1 nil nil t))
(overlay-put redvai--overlay 'keymap redvai-completion-map)
(overlay-put redvai--overlay 'after-string ""))
redvai--overlay)
(defun redvai--overlay-visible ()
"Return t if the overlay is visible."
(and (overlayp redvai--overlay)
(overlay-buffer redvai--overlay)))
(defun redvai--test-overlay ()
"Bla"
(interactive)
(redvai--set-overlay-text (redvai--get-overlay) "Test123"))
(defun redvai-complete ()
(interactive)
;; TODO call into module
;; (redvai--set-overlay-text (redvai--get-overlay) "Test123")
)
(defun redvai--clear-overlay ()
(message "%S" "Cleared")
(when (redvai--overlay-visible)
(delete-overlay redvai--overlay)))
(defun redvai-dismiss ()
"Clear overlay."
(interactive)
(redvai--clear-overlay))
(defun redvai--current-completion ()
(substring-no-properties (overlay-get (redvai--get-overlay) 'after-string)))
(defun redvai-accept-completion ()
"Bla"
(interactive)
(when (redvai--overlay-visible)
(insert (redvai--current-completion))
(clear-overlay)))
;;; redvai-mode
(defun redvai--self-insert (command)
"Handle the case where the char just inserted is the start of the completion.
If so, update the overlays and continue. COMMAND is the
command that triggered `post-command-hook'."
(when (and (eq command 'self-insert-command)
(redvai--overlay-visible))
(let* ((ov redvai--overlay)
(completion (redvai--current-completion)))
;; The char just inserted is the next char of completion
(when (eq last-command-event (elt completion 0))
(if (= (length completion) 1)
;; If there is only one char in the completion, accept it
(progn
(overlay-put ov 'completion "")
(redvai-accept-completion))
(redvai--set-overlay-text ov (substring completion 1)))))))
(defcustom redvai-idle-delay 0.2
"Time in seconds to wait before starting completion.
Complete immediately if set to 0.
Disable idle completion if set to nil."
:type '(choice
(number :tag "Seconds of delay")
(const :tag "Idle completion disabled" nil))
:group 'redvai)
(defun redvai--mode-enter ()
"Set up redvai mode when entering."
(add-hook 'post-command-hook 'redvai--post-command nil 'local))
(defun redvai--mode-exit ()
"Clean up redvai mode when exiting."
(remove-hook 'post-command-hook #'redvai--post-command 'local))
(defun redvai-turn-on-unless-buffer-read-only ()
"Turn on `redvai-mode' if the buffer is writable."
(unless buffer-read-only
(redvai-mode 1)))
(defun redvai--post-command-debounce (buffer)
"Complete in BUFFER."
(when (and (buffer-live-p buffer)
(equal (current-buffer) buffer)
redvai-mode)
(redvai-complete)))
(defun redvai--post-command ()
"Complete in `post-command-hook' hook."
(when (and this-command
(not (and (symbolp this-command)
(or
(s-starts-with-p "redvai-" (symbol-name this-command))
(redvai--self-insert this-command)))))
(redvai-dismiss)
(when redvai--post-command-timer
(cancel-timer redvai--post-command-timer))
(setq redvai--post-command-timer
(run-with-idle-timer redvai-idle-delay
nil
'redvai--post-command-debounce
(current-buffer)))))
(advice-add 'keyboard-quit :after #'redvai-dismiss)
;;;###autoload
(define-minor-mode redvai-mode
"Minor mode for Redvai."
:init-value nil
:lighter " Redvai"
(redvai-dismiss)
(if redvai-mode
(redvai--mode-enter)
(redvai--mode-exit)))
(provide 'redvai)
;;; redvai.el ends here