;;; redvai.el --- Description -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2024 Tristan Druyen ;; ;; Filename: redvai-mini.el ;; Author: Tristan Druyen ;; Maintainer: Tristan Druyen ;; 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