@@ -1122,14 +1122,106 @@ pub fn goto_reference(cx: &mut Context) {
11221122 goto(cx, res);
11231123}
11241124
1125+pub fn signature_help(cx: &mut Context) {
1126+ let doc = cx.doc();
1127+
1128+ let language_server = match doc.language_server() {
1129+ Some(language_server) => language_server,
1130+ None => return,
1131+ };
1132+
1133+ // TODO: blocking here is not ideal
1134+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1135+
1136+ // TODO: handle fails
1137+
1138+ let res = smol::block_on(language_server.text_document_signature_help(doc.identifier(), pos))
1139+ .unwrap_or_default();
1140+
1141+ if let Some(signature_help) = res {
1142+ log::info!("{:?}", signature_help);
1143+ // signatures
1144+ // active_signature
1145+ // active_parameter
1146+ // render as:
1147+
1148+ // signature
1149+ // ----------
1150+ // doc
1151+
1152+ // with active param highlighted
1153+ }
1154+}
1155+
11251156// NOTE: Transactions in this module get appended to history when we switch back to normal mode.
11261157pub mod insert {
11271158 use super::*;
11281159 pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;
1160+ pub type PostHook = fn(&mut Context, char);
11291161
11301162 use helix_core::auto_pairs;
11311163 const HOOKS: &[Hook] = &[auto_pairs::hook];
11321164
1165+ fn completion(cx: &mut Context, ch: char) {
1166+ // if ch matches completion char, trigger completion
1167+ let doc = cx.doc();
1168+ let language_server = match doc.language_server() {
1169+ Some(language_server) => language_server,
1170+ None => return,
1171+ };
1172+
1173+ let capabilities = language_server.capabilities();
1174+
1175+ if let lsp::ServerCapabilities {
1176+ completion_provider:
1177+ Some(lsp::CompletionOptions {
1178+ trigger_characters: Some(triggers),
1179+ ..
1180+ }),
1181+ ..
1182+ } = capabilities
1183+ {
1184+ // TODO: what if trigger is multiple chars long
1185+ let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch));
1186+
1187+ if is_trigger {
1188+ super::completion(cx);
1189+ }
1190+ }
1191+ }
1192+
1193+ // TODO: the pre-hook handles ( so post hook never gets called
1194+ fn signature_help(cx: &mut Context, ch: char) {
1195+ // if ch matches signature_help char, trigger
1196+ let doc = cx.doc();
1197+ let language_server = match doc.language_server() {
1198+ Some(language_server) => language_server,
1199+ None => return,
1200+ };
1201+
1202+ let capabilities = language_server.capabilities();
1203+
1204+ if let lsp::ServerCapabilities {
1205+ signature_help_provider:
1206+ Some(lsp::SignatureHelpOptions {
1207+ trigger_characters: Some(triggers),
1208+ // TODO: retrigger_characters
1209+ ..
1210+ }),
1211+ ..
1212+ } = capabilities
1213+ {
1214+ // TODO: what if trigger is multiple chars long
1215+ let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch));
1216+
1217+ if is_trigger {
1218+ super::signature_help(cx);
1219+ }
1220+ }
1221+ }
1222+
1223+ const POST_HOOKS: &[PostHook] = &[completion, signature_help];
1224+
11331225 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
11341226 pub fn insert_char(cx: &mut Context, c: char) {
11351227 let doc = cx.doc();
@@ -1142,10 +1234,17 @@ pub mod insert {
11421234 }
11431235 }
11441236
1145− let c = Tendril::from_char(c);
1146− let transaction = Transaction::insert(doc.text(), doc.selection(), c);
1237+ let t = Tendril::from_char(c);
1238+ let transaction = Transaction::insert(doc.text(), doc.selection(), t);
11471239
11481240 doc.apply(&transaction);
1241+
1242+ // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
1243+ // this could also generically look at Transaction, but it's a bit annoying to look at
1244+ // Operation instead of Change.
1245+ for hook in POST_HOOKS {
1246+ hook(cx, c);
1247+ }
11491248 }
11501249
11511250 pub fn insert_tab(cx: &mut Context) {
@@ -1162,6 +1261,7 @@ pub mod insert {
11621261 let doc = cx.doc();
11631262 let text = doc.text().slice(..);
11641263 let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1264+ // TODO: offset range.head by 1? when calculating?
11651265 let indent_level =
11661266 helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, range.head, true);
11671267 let indent = doc.indent_unit().repeat(indent_level);
@@ -1514,6 +1614,7 @@ pub fn completion(cx: &mut Context) {
15141614 //
15151615 // or we could simply use doc.undo + apply when changing between options
15161616
1617+ // always present here
15171618 let item = item.unwrap();
15181619
15191620 use helix_lsp::{lsp, util};