Skip to content

Commit

Permalink
refactor logic so handlers::copilot::copilot_completion only effects …
Browse files Browse the repository at this point in the history
…updating the completion state, and no longer effects rendering
  • Loading branch information
AlexanderDickie committed Jul 3, 2024
1 parent 5510e47 commit e2b0b96
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 83 deletions.
10 changes: 5 additions & 5 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6123,16 +6123,16 @@ fn copilot_apply_completion(cx: &mut Context) {

fn copilot_show_completion(cx: &mut Context) {
let (_, doc) = current!(cx.editor);
if let Some(copilot) = doc.copilot.as_mut() {
copilot.should_render = true;
}
doc.copilot.show_completion();
}

fn copilot_toggle_auto_render(cx: &mut Context) {
cx.editor.auto_render_copilot = !cx.editor.auto_render_copilot;
let (_, doc) = current!(cx.editor);
let auto_render = doc.copilot.toggle_auto_render();

cx.editor.set_status(format!(
"copilot-auto-render = {}",
cx.editor.auto_render_copilot
auto_render,
));
}

Expand Down
54 changes: 20 additions & 34 deletions helix-term/src/handlers/copilot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,54 @@ use helix_event::{
};
use helix_lsp::copilot_types::DocCompletion;
use helix_lsp::util::{lsp_pos_to_pos, lsp_range_to_range};
use helix_view::document::{Copilot, Mode};
use helix_view::document::Mode;
use helix_view::Editor;
use helix_view::events::DocumentDidChange;
use tokio::time::Instant;
use crate::events::OnModeSwitch;
use crate::handlers::Handlers;
use helix_view::{handlers::lsp::CopilotEvent, DocumentId};
use helix_view::handlers::lsp::CopilotRequestCompletionEvent;
use crate::job::{dispatch, dispatch_blocking};

pub struct CopilotHandler {
doc_id: Option<DocumentId>,
cancel: Option<CancelTx>,
}

impl CopilotHandler {
pub fn new() -> Self {
Self {
doc_id: None,
cancel: None,
}
}
}

impl helix_event::AsyncHook for CopilotHandler {
type Event = CopilotEvent;
type Event = CopilotRequestCompletionEvent;
fn handle_event(
&mut self,
event: Self::Event,
_: Self::Event,
_: Option<Instant>,
) -> Option<Instant> {
match event {
CopilotEvent::RequestCompletion { doc_id } => {
self.doc_id = Some(doc_id);
self.cancel.take();
Some(Instant::now() + Duration::from_millis(100))
}
CopilotEvent::CancelInFlightCompletion => {
self.cancel.take();
None
}
}
self.cancel.take();
Some(Instant::now() + Duration::from_millis(100))
}

fn finish_debounce(&mut self) {
let Some(doc_id) = self.doc_id else {return;};
let (tx, rx) = cancelation();
self.cancel = Some(tx);

dispatch_blocking(move |editor, _| {
copilot_completion(editor, doc_id, rx);
copilot_completion(editor, rx);
});
}
}

fn copilot_completion(editor: &mut Editor, doc_id: DocumentId, cancel: CancelRx) {
fn copilot_completion(editor: &mut Editor, cancel: CancelRx) {
let (view, doc) = current_ref!(editor);
if doc.id() != doc_id || editor.mode() != Mode::Insert { return; }
// check editor mode since we request a completion on DocumentDidChange even when not in Insert Mode
// (this cannot be checked within try_register_hooks unforunately)
// (the completion will not render, but there is still not point sending the request to the copilot lsp)
if editor.mode() != Mode::Insert { return; }

let Some(copilot_ls) = doc
.language_servers()
Expand All @@ -86,9 +77,8 @@ fn copilot_completion(editor: &mut Editor, doc_id: DocumentId, cancel: CancelRx)
return;
};

if editor.mode() != Mode::Insert { return; }
let (view, doc) = current!(editor);
let doc_completion = completions
let doc_completions = completions
.into_iter()
.filter_map(|completion| {
/*
Expand Down Expand Up @@ -139,12 +129,7 @@ fn copilot_completion(editor: &mut Editor, doc_id: DocumentId, cancel: CancelRx)
})
.collect::<Vec<DocCompletion>>();

doc.copilot = Some(Copilot {
should_render: editor.auto_render_copilot,
completions: doc_completion,
idx: 0,
offset_encoding,
});
doc.copilot.fill_with_completions(doc_completions, offset_encoding);
})
.await;
}
Expand All @@ -157,19 +142,20 @@ pub(super) fn try_register_hooks(handlers: &Handlers) {

let tx = copilot_handler.clone();
register_hook!(move |event: &mut DocumentDidChange<'_>| {
event.doc.clear_copilot_completions();
send_blocking(&tx, CopilotEvent::RequestCompletion { doc_id: event.doc.id() });
event.doc.copilot.delete_state_and_reset_should_render();
send_blocking(&tx, CopilotRequestCompletionEvent);
Ok(())
});

let tx = copilot_handler.clone();
register_hook!(move |event: &mut OnModeSwitch<'_, '_>| {
let (_, doc) = current!(event.cx.editor);
doc.clear_copilot_completions();

if event.old_mode == Mode::Insert {
send_blocking(&tx, CopilotEvent::CancelInFlightCompletion);
doc.copilot.delete_state_and_should_not_render();
} else if event.new_mode == Mode::Insert {
send_blocking(&tx, CopilotEvent::RequestCompletion { doc_id: doc.id() });
doc.copilot.delete_state_and_reset_should_render();
send_blocking(&tx, CopilotRequestCompletionEvent);
}
Ok(())
});
Expand Down
76 changes: 76 additions & 0 deletions helix-view/src/copilot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use helix_lsp::{copilot_types::DocCompletion, OffsetEncoding};
use parking_lot::Mutex;
use std::sync::Arc;

static GLOBAL_AUTO_RENDER: once_cell::sync::OnceCell<Arc<Mutex<bool>>> = once_cell::sync::OnceCell::new();

#[derive(Clone, Debug)]
pub struct Copilot {
completion_response: Option<(Vec<DocCompletion>, OffsetEncoding)> ,
render: Render
}

#[derive(Clone, Debug)]
struct Render {
global_auto_render: Arc<Mutex<bool>>,
should_render: Option<usize>,
}

impl Render {
pub fn reset(& mut self) {
let lock = self.global_auto_render.lock();
self.should_render = if *lock {Some(0)} else {None};
}
pub fn should_not_render(&mut self) {
self.should_render = None;
}
}

impl Copilot {
pub fn new(editor_auto_render: bool) -> Copilot {
let global_auto_render_completion = GLOBAL_AUTO_RENDER.get_or_init(|| Arc::new(Mutex::new(editor_auto_render))).clone();

return Self {
completion_response: None,
render: Render {
global_auto_render: global_auto_render_completion,
should_render: None
}
}
}

pub fn delete_state_and_reset_should_render(&mut self) {
self.render.reset();
self.completion_response = None;
}

pub fn delete_state_and_should_not_render(&mut self) {
self.render.should_not_render();
self.completion_response = None;
}

pub fn show_completion(&mut self) {
self.render.should_render = Some(0);
}

pub fn fill_with_completions(&mut self, completions: Vec<DocCompletion>, offset_encoding: OffsetEncoding) {
self.completion_response = Some((completions, offset_encoding));
}

pub fn get_completion_if_should_render(&self) -> Option<&DocCompletion> {
let idx = self.render.should_render?;
let completions = &self.completion_response.as_ref()?.0;
completions.get(idx)
}

pub fn offset_encoding(&self) -> Option<OffsetEncoding> {
Some(self.completion_response.as_ref()?.1)
}

pub fn toggle_auto_render(&self) -> bool {
let mut lock = self.render.global_auto_render.lock();
*lock = !(*lock);
return *lock;
}

}
47 changes: 10 additions & 37 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use helix_core::{
ChangeSet, Diagnostic, LineEnding, Rope, RopeBuilder, Selection, Syntax, Transaction,
};

use crate::copilot::Copilot;
use crate::editor::Config;
use crate::events::{DocumentDidChange, SelectionDidChange};
use crate::{DocumentId, Editor, Theme, View, ViewId};
Expand Down Expand Up @@ -129,16 +130,8 @@ pub enum DocumentOpenError {
IoError(#[from] io::Error),
}

#[derive(Clone, Debug)]
pub struct Copilot {
pub should_render: bool,
pub completions: Vec<DocCompletion>,
pub idx: usize,
pub offset_encoding: OffsetEncoding,
}

pub struct Document {
pub copilot: Option<Copilot>,
pub copilot: Copilot,
pub(crate) id: DocumentId,
text: Rope,
selections: HashMap<ViewId, Selection>,
Expand Down Expand Up @@ -649,46 +642,25 @@ use helix_lsp::{copilot_types, Client, LanguageServerId, LanguageServerName};
use url::Url;

impl Document {
pub fn clear_copilot_completions(&mut self) {
self.copilot = None;
}

pub fn get_copilot_completion_for_rendering(&self) -> Option<&DocCompletion> {
let Some(copilot) = self.copilot.as_ref() else {
return None;
};
if !copilot.should_render {
return None;
}
let completion = self.copilot.get_completion_if_should_render()?;

let completion = copilot.completions.get(copilot.idx)?;
if self.version as usize != completion.doc_version {
return None;
}
return Some(completion);
Some(completion)
}

pub fn apply_copilot_completion(&mut self, view_id: ViewId) {
if let None = self.get_copilot_completion_for_rendering() {
return;
}
let Some(copilot) = self.copilot.as_ref() else {
return;
};

let Some(completion) = copilot.completions.get(copilot.idx) else {
return;
};
if completion.doc_version != self.version as usize {
return;
}
pub fn apply_copilot_completion(&mut self, view_id: ViewId) {
let Some(completion) = self.copilot.get_completion_if_should_render() else { return; };
let Some(offset_encoding) = self.copilot.offset_encoding() else { return; };

let edit = lsp::TextEdit {
range: completion.lsp_range,
new_text: completion.text.clone(),
};
let transaction =
generate_transaction_from_edits(self.text(), vec![edit], copilot.offset_encoding);
generate_transaction_from_edits(self.text(), vec![edit], offset_encoding);

self.apply(&transaction, view_id);
}
Expand All @@ -702,9 +674,10 @@ impl Document {
let line_ending = config.load().default_line_ending.into();
let changes = ChangeSet::new(text.slice(..));
let old_state = None;
let copilot_auto_render = config.load().copilot_auto_render;

Self {
copilot: None,
copilot: Copilot::new(copilot_auto_render),
id: DocumentId::default(),
path: None,
encoding,
Expand Down
2 changes: 0 additions & 2 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,6 @@ pub struct Breakpoint {
use futures_util::stream::{Flatten, Once};

pub struct Editor {
pub auto_render_copilot: bool,
/// Current editing mode.
pub mode: Mode,
pub tree: Tree,
Expand Down Expand Up @@ -1164,7 +1163,6 @@ impl Editor {
area.height -= 1;

Self {
auto_render_copilot: conf.copilot_auto_render,
mode: Mode::Normal,
tree: Tree::new(area),
next_document_id: DocumentId::default(),
Expand Down
2 changes: 1 addition & 1 deletion helix-view/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Handlers {
pub completions: Sender<lsp::CompletionEvent>,
pub signature_hints: Sender<lsp::SignatureHelpEvent>,
pub auto_save: Sender<AutoSaveEvent>,
pub copilot: Option<Sender<lsp::CopilotEvent>>,
pub copilot: Option<Sender<lsp::CopilotRequestCompletionEvent>>,
}

impl Handlers {
Expand Down
5 changes: 1 addition & 4 deletions helix-view/src/handlers/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use crate::{DocumentId, ViewId};
use helix_lsp::util::generate_transaction_from_edits;
use helix_lsp::{lsp, OffsetEncoding};

pub enum CopilotEvent {
RequestCompletion { doc_id: DocumentId },
CancelInFlightCompletion,
}
pub struct CopilotRequestCompletionEvent;

pub enum CompletionEvent {
/// Auto completion was triggered by typing a word char
Expand Down
1 change: 1 addition & 0 deletions helix-view/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod register;
pub mod theme;
pub mod tree;
pub mod view;
pub mod copilot;

use std::num::NonZeroUsize;

Expand Down

0 comments on commit e2b0b96

Please sign in to comment.