Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve hover support #38

Merged
merged 1 commit into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lsp/src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
};
use log::{debug, error, warn};
use lsp_server::{Message, Notification, Request, RequestId};
use lsp_types::{CompletionContext, CompletionParams, CompletionTriggerKind};
use lsp_types::{CompletionContext, CompletionParams, CompletionTriggerKind, HoverParams};

#[derive(serde::Deserialize, Debug)]
struct Text {
Expand Down Expand Up @@ -141,12 +141,12 @@ fn handle_completion(req: Request) -> Option<HtmxResult> {
}

fn handle_hover(req: Request) -> Option<HtmxResult> {
let completion: CompletionParams = serde_json::from_value(req.params).ok()?;
debug!("handle_hover: {:?}", completion.context);
let hover: HoverParams = serde_json::from_value(req.params).ok()?;
debug!("handle_hover: {:?}", hover);

let text_params = completion.text_document_position;
let text_params = hover.text_document_position_params;

debug!("handle_hover text_params: {:?}", text_params);
debug!("handle_hover text_position_params: {:?}", text_params);

let attribute = hx_hover(text_params)?;

Expand Down
14 changes: 10 additions & 4 deletions lsp/src/htmx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use log::debug;
use lsp_types::TextDocumentPositionParams;
use serde::{Deserialize, Serialize};

use crate::tree_sitter::Position;
use crate::{text_store::get_word_from_pos_params, tree_sitter::Position};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct HxCompletion {
Expand Down Expand Up @@ -39,12 +39,18 @@ pub fn hx_completion(text_params: TextDocumentPositionParams) -> Option<&'static
}

pub fn hx_hover(text_params: TextDocumentPositionParams) -> Option<HxCompletion> {
let result = crate::tree_sitter::get_position_from_lsp_completion(text_params.clone())?;
let result = match get_word_from_pos_params(&text_params) {
Ok(word) => Position::AttributeName(word),
Err(_) => {
return None;
}
};
debug!("handle_hover result: {:?}", result);

match result {
Position::AttributeName(name) => HX_TAGS.iter().find(|x| x.name == name).cloned(),
Position::AttributeValue { name, .. } => HX_TAGS.iter().find(|x| x.name == name).cloned(),
Position::AttributeName(name) | Position::AttributeValue { name, .. } => {
HX_TAGS.iter().find(|x| x.name == name).cloned()
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use htmx::HxCompletion;
use log::{debug, error, info, warn};
use lsp_types::{
CompletionItem, CompletionItemKind, CompletionList, HoverContents, InitializeParams,
LanguageString, MarkedString, ServerCapabilities, TextDocumentSyncCapability,
TextDocumentSyncKind, WorkDoneProgressOptions,
MarkupContent, ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind,
WorkDoneProgressOptions,
};

use lsp_server::{Connection, Message, Response};
Expand Down Expand Up @@ -80,10 +80,10 @@ fn main_loop(connection: Connection, params: serde_json::Value) -> Result<()> {
Some(HtmxResult::AttributeHover(hover_resp)) => {
debug!("main_loop - hover response: {:?}", hover_resp);
let hover_response = lsp_types::Hover {
contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString {
language: "html".to_string(),
value: hover_resp.value.clone(),
})),
contents: HoverContents::Markup(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: hover_resp.value.to_string(),
}),
range: None,
};

Expand Down
54 changes: 52 additions & 2 deletions lsp/src/text_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
sync::{Arc, Mutex, OnceLock},
};

use lsp_types::Url;
use lsp_types::{TextDocumentPositionParams, Url};

type TxtStore = HashMap<String, String>;

Expand All @@ -29,7 +29,7 @@ pub fn init_text_store() {
_ = TEXT_STORE.set(Arc::new(Mutex::new(TextStore(HashMap::new()))));
}

pub fn get_text_document(uri: Url) -> Option<String> {
pub fn get_text_document(uri: &Url) -> Option<String> {
return TEXT_STORE
.get()
.expect("text store not initialized")
Expand All @@ -38,3 +38,53 @@ pub fn get_text_document(uri: Url) -> Option<String> {
.get(&uri.to_string())
.cloned();
}

/// Find the start and end indices of a word inside the given line
/// Borrowed from RLS
fn find_word_at_pos(line: &str, col: usize) -> (usize, usize) {
let line_ = format!("{} ", line);
let is_ident_char = |c: char| c.is_alphanumeric() || c == '_' || c == '-';

let start = line_
.chars()
.enumerate()
.take(col)
.filter(|&(_, c)| !is_ident_char(c))
.last()
.map(|(i, _)| i + 1)
.unwrap_or(0);

#[allow(clippy::filter_next)]
let mut end = line_
.chars()
.enumerate()
.skip(col)
.filter(|&(_, c)| !is_ident_char(c));

let end = end.next();
(start, end.map(|(i, _)| i).unwrap_or(col))
}

pub fn get_word_from_pos_params(pos_params: &TextDocumentPositionParams) -> anyhow::Result<String> {
let uri = &pos_params.text_document.uri;
let line = pos_params.position.line as usize;
let col = pos_params.position.character as usize;

match get_text_document(uri) {
Some(text) => {
let line_conts = match text.lines().nth(line) {
Some(conts) => conts,
None => {
return Err(anyhow::anyhow!(
"get_word_from_pos_params Failed to get word under cursor"
));
}
};
let (start, end) = find_word_at_pos(line_conts, col);
Ok(String::from(&line_conts[start..end]))
}
None => Err(anyhow::anyhow!(
"get_word_from_pos_params Failed to get word under cursor"
)),
}
}
2 changes: 1 addition & 1 deletion lsp/src/tree_sitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn get_position_from_lsp_completion(
text_params: TextDocumentPositionParams,
) -> Option<Position> {
error!("get_position_from_lsp_completion");
let text = get_text_document(text_params.text_document.uri)?;
let text = get_text_document(&text_params.text_document.uri)?;
error!("get_position_from_lsp_completion: text {}", text);
let pos = text_params.position;
error!("get_position_from_lsp_completion: pos {:?}", pos);
Expand Down
Loading