Compare commits
5 commits
932faab35b
...
589490128e
Author | SHA1 | Date | |
---|---|---|---|
589490128e | |||
b3be9d2624 | |||
f1eda67c1e | |||
78f89dcd8b | |||
81c0e953f7 |
26 changed files with 388 additions and 30 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -170,9 +170,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.89"
|
version = "1.0.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
]
|
]
|
||||||
|
@ -2374,6 +2374,10 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "garnix"
|
||||||
|
version = "0.1.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk"
|
name = "gdk"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -6156,8 +6160,10 @@ dependencies = [
|
||||||
name = "redvault_el_rs"
|
name = "redvault_el_rs"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"emacs",
|
"emacs",
|
||||||
"emacs-rs-module",
|
"emacs-rs-module",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -8148,9 +8154,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.40.0"
|
version = "1.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
|
checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -8161,6 +8167,7 @@ dependencies = [
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
|
"tracing",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ lto = "fat"
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["llama_forge_rs", "leptos_stub", "frozen_llama", "llama_proxy_man", "redvault_el_rs"]
|
members = ["llama_forge_rs", "frozen_llama", "llama_proxy_man", "redvault_el_rs", "garnix"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|
12
garnix/Cargo.toml
Normal file
12
garnix/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "garnix"
|
||||||
|
authors.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
publish.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
46
garnix/PLAN.md
Normal file
46
garnix/PLAN.md
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
# Time tracker/watcher with intervention mode
|
||||||
|
|
||||||
|
- integrations
|
||||||
|
- awatcher for tracking
|
||||||
|
- nix for config enforcement/focus profile creation
|
||||||
|
- oproject
|
||||||
|
- time tracking submission
|
||||||
|
- profile selection(based on planned task/vacation tasks for the day??)
|
||||||
|
- completion checking
|
||||||
|
- general task config via yaml comment in task desk ????
|
||||||
|
- e.g. `garnix-magic-str profile: coding, pomodoro:20/10`
|
||||||
|
- blocking via nix conf?
|
||||||
|
- user based ? (seems easiest)
|
||||||
|
- force logout for user & do not allow relogin ?
|
||||||
|
- high level config
|
||||||
|
- focus profiles
|
||||||
|
- set of alow/denylists apps/window titles/binarys/pkgs/hostnames!/websites!
|
||||||
|
- e.g.
|
||||||
|
- coding for work
|
||||||
|
- coding for fun
|
||||||
|
- nix config hacking
|
||||||
|
- tasks
|
||||||
|
- attrs
|
||||||
|
- profile while ongoing
|
||||||
|
- allowed and or forced enable/disable times with rules
|
||||||
|
- e.g. for freetime/fun 18:00-09:00 allowed
|
||||||
|
- e.g. for daily oproject 17:00-completed forced
|
||||||
|
- completion criteria
|
||||||
|
- forced steps ?
|
||||||
|
- e.g. task creation/selection via webview browser in leptos UI
|
||||||
|
- via of links to guide through
|
||||||
|
- (how to get completion from webview ????)
|
||||||
|
- get completion otherwise/show overlay button?
|
||||||
|
- day filled in oproject
|
||||||
|
- time psased
|
||||||
|
- commit (with refid for ticket?)
|
||||||
|
- customScript (e.g. wget url for fix when website breaks)
|
||||||
|
- examples
|
||||||
|
- daily timetrack/bookkepping
|
||||||
|
- complete coding task
|
||||||
|
- checkins (maybe just a category of repeating task?)
|
||||||
|
- enforce task completion
|
||||||
|
|
||||||
|
|
||||||
|
# MVP
|
||||||
|
- force me to create oproject track (no ui, just nix foo & completion checking)
|
56
garnix/TODOS.md
Normal file
56
garnix/TODOS.md
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# TODOs
|
||||||
|
|
||||||
|
### Add a simple DIY module framework
|
||||||
|
|
||||||
|
#### Features in order of importance
|
||||||
|
- import files by directory structure like modname/default.nix or modname.nix (both ideally)
|
||||||
|
- enable/disable wrap with modname.enable merged with provided config attrs, maybe more default config attrs ? order? tag a.la os/hm/both ?
|
||||||
|
- variant with common code for home-manager OR nixOsConfig
|
||||||
|
- variant with merged modules than can export config._home or sth??
|
||||||
|
- declare like:
|
||||||
|
```nix
|
||||||
|
attrs: {
|
||||||
|
commonConfig= {}; // nil (default enable)
|
||||||
|
nixosModule=(attrs: {}) attrs;
|
||||||
|
hmModule=(attrs: {}) attrs;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- or ?
|
||||||
|
```nix
|
||||||
|
{isHomeManagerModule, homeOnly, nixosOnly, homeOrNix, pkgs, ... }: {
|
||||||
|
// write module and use if isHomeManagerModule inside it to seperate?
|
||||||
|
asd = if isHomeMangerModule
|
||||||
|
# ...
|
||||||
|
// or via utilFunction which only evals in correct system?
|
||||||
|
def = homeOrNix {args: home.asd.def=true;} {args: boot.kernel.bla='bla'};
|
||||||
|
// the lsat one seems kinda similar to #1, big difference is that it's reusable at multiple places in the config
|
||||||
|
// is that usseful ? for programx.xyz at least likely?
|
||||||
|
};
|
||||||
|
```
|
||||||
|
- import time interface
|
||||||
|
- module-based?
|
||||||
|
- ```nix
|
||||||
|
nixosModules.myMods.default // with sensible defs
|
||||||
|
nixosModules.myMods.custom { path=./dir; autoconf.addEnable=false; } // but customization(maybe also regex?
|
||||||
|
```
|
||||||
|
- or lib-like?
|
||||||
|
lib.mylib.modularizer.custom {path ./; #...};
|
||||||
|
- both?! (liblike needs more detailed setup, module can integrate with homeManager seamlessly with one call? or can it?, where to place calls in existing config???)
|
||||||
|
- 2 calls could be needed, to get both hm and nixos integration?
|
||||||
|
- or would they?
|
||||||
|
- prevent double eval? uneeded cause lazyness? benchmark?
|
||||||
|
- idea provide higher-level entrypoint which also replaces ./system foo and has several dirs as config e.g.
|
||||||
|
- ```nix
|
||||||
|
nixSystems=v81magicfunction {
|
||||||
|
attrs = {
|
||||||
|
inherit @pkgs, lib, inputs?
|
||||||
|
};
|
||||||
|
systemsDir = ./systems;
|
||||||
|
homeModules = ./hmModules;
|
||||||
|
osModules = ./hmModules;
|
||||||
|
magicModules = './v81Modules;
|
||||||
|
override = {
|
||||||
|
hook running last
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
garnix/src/main.rs
Normal file
3
garnix/src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"keepSettings": {
|
|
||||||
"type": 1,
|
|
||||||
"amount": 30
|
|
||||||
},
|
|
||||||
"auditFilename": "audit.json",
|
|
||||||
"hashType": "md5",
|
|
||||||
"extension": ".log",
|
|
||||||
"files": [
|
|
||||||
{
|
|
||||||
"date": 1726742235723,
|
|
||||||
"name": "/home/tristand/.tabby-client/agent/logs/20240919.0.log",
|
|
||||||
"hash": "13392f16f09c9e264d7c9b82880ae40c"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -315,7 +315,7 @@ async fn handle_request(
|
||||||
|
|
||||||
// Proxy the request
|
// Proxy the request
|
||||||
let retry_policy = reqwest_retry::policies::ExponentialBackoff::builder()
|
let retry_policy = reqwest_retry::policies::ExponentialBackoff::builder()
|
||||||
.retry_bounds(Duration::from_secs(1), Duration::from_secs(8))
|
.retry_bounds(Duration::from_millis(500), Duration::from_secs(8))
|
||||||
.jitter(reqwest_retry::Jitter::None)
|
.jitter(reqwest_retry::Jitter::None)
|
||||||
.base(2)
|
.base(2)
|
||||||
.build_with_max_retries(8);
|
.build_with_max_retries(8);
|
||||||
|
|
|
@ -13,8 +13,10 @@ edition.workspace = true
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.93"
|
||||||
emacs = "0.19"
|
emacs = "0.19"
|
||||||
emacs-rs-module = { version = "0.19.0" }
|
emacs-rs-module = { version = "0.19.0" }
|
||||||
|
tokio = { version = "1.41.1", features = ["full", "tracing"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
emacs-rs-module = { version = "0.19.0" }
|
emacs-rs-module = { version = "0.19.0" }
|
||||||
|
|
|
@ -3,12 +3,20 @@
|
||||||
## Hot reload for dev
|
## Hot reload for dev
|
||||||
```elisp
|
```elisp
|
||||||
|
|
||||||
(module-load "~/code/redvault-ai/target/release/deps/libemacs_rs_module-9ad53dadcc38727d.so")
|
(module-load "/home/tristand/code/redvault-ai/target/release/deps/libemacs_rs_module-9ad53dadcc38727d.so")
|
||||||
|
|
||||||
|
|
||||||
(defun hotreload-el-rs ()
|
(defun hotreload-el-rs ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(rs-module/load "~/code/redvault-ai/target/debug/libredvault_el_rs.so")
|
(rs-module/load "/home/tristand/code/redvault-ai/target/release/libredvault_el_rs.so"))
|
||||||
|
|
||||||
|
|
||||||
|
(defun el-res-say-hello-2 ()
|
||||||
|
(interactive)
|
||||||
|
(asd/say-hello "Asd"))
|
||||||
|
|
||||||
|
(defun el-res-say-hello ()
|
||||||
|
(interactive)
|
||||||
(redvault-el-rs/say-hello "Asd"))
|
(redvault-el-rs/say-hello "Asd"))
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,11 +1,36 @@
|
||||||
use emacs::{defun, Env, IntoLisp, Result, Value};
|
use emacs::{defun, Env, IntoLisp, Result, Value};
|
||||||
|
use std::sync::Once;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
use tokio::runtime::{Builder, Runtime};
|
||||||
|
|
||||||
// Emacs won't load the module without this.
|
// Emacs won't load the module without this.
|
||||||
emacs::plugin_is_GPL_compatible!();
|
emacs::plugin_is_GPL_compatible!();
|
||||||
|
|
||||||
|
// Global static runtime that's lazily initialized
|
||||||
|
static RUNTIME: OnceLock<Runtime> = OnceLock::new();
|
||||||
|
|
||||||
|
// Initialization function for the Emacs module
|
||||||
|
fn initialize_tokio_runtime() -> &'static Runtime {
|
||||||
|
RUNTIME.get_or_init(|| {
|
||||||
|
Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.worker_threads(4) // Adjust number of worker threads as needed
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Tokio runtime")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Register the initialization hook that Emacs will call when it loads the module.
|
// Register the initialization hook that Emacs will call when it loads the module.
|
||||||
#[emacs::module(separator = "/")]
|
#[emacs::module(separator = "/")]
|
||||||
fn init(env: &Env) -> Result<Value<'_>> {
|
fn init(env: &Env) -> Result<Value<'_>> {
|
||||||
|
let runtime = initialize_tokio_runtime();
|
||||||
|
|
||||||
|
// Spawn a task without blocking
|
||||||
|
runtime.spawn(async {
|
||||||
|
// Your async code here
|
||||||
|
println!("Running an async task");
|
||||||
|
});
|
||||||
|
|
||||||
env.message("Test loading!")?;
|
env.message("Test loading!")?;
|
||||||
|
|
||||||
env.message("Done loading!")
|
env.message("Done loading!")
|
||||||
|
@ -26,11 +51,24 @@ fn say_hello(env: &Env, name: String) -> Result<Value<'_>> {
|
||||||
// env.message(&format!("Helloo Broooooooo, {}!", name))
|
// env.message(&format!("Helloo Broooooooo, {}!", name))
|
||||||
env.call(
|
env.call(
|
||||||
"message",
|
"message",
|
||||||
[format!("Henlo whatup, {}!", name).as_str().into_lisp(env)?],
|
[format!("Henlo whatsup, {}!!!!", name)
|
||||||
)
|
.as_str()
|
||||||
|
.into_lisp(env)?],
|
||||||
|
)?;
|
||||||
|
RUNTIME
|
||||||
|
.get()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("No runtime"))?
|
||||||
|
.spawn(async {
|
||||||
|
for _i in 1..5 {
|
||||||
|
println!("A");
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||||
|
println!("B");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
().into_lisp(env)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[defun]
|
// #[defun]
|
||||||
fn open_test_overlay(_env: &Env) -> Result<Value<'_>> {
|
// fn open_test_overlay(_env: &Env) -> Result<Value<'_>> {
|
||||||
todo!()
|
// todo!()
|
||||||
}
|
// }
|
||||||
|
|
202
redvault_el_rs/src/redvai-mini.el
Normal file
202
redvault_el_rs/src/redvai-mini.el
Normal 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
|
Loading…
Add table
Reference in a new issue