Skip to content

Commit

Permalink
Minor refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
liuchengxu committed Nov 15, 2023
1 parent c180005 commit 2575858
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 104 deletions.
49 changes: 28 additions & 21 deletions crates/maple_core/src/stdio_server/plugin/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,28 @@ struct TreeSitterInfo {
}

#[derive(Debug, Clone, maple_derive::ClapPlugin)]
#[clap_plugin(id = "syntax", actions = ["on", "tree-sitter-props-at-cursor", "tree-sitter-highlight", "list-themes", "toggle"])]
#[clap_plugin(id = "syntax", actions = [
"list-sublime-themes",
"sublime-syntax-highlight",
"tree-sitter-highlight",
"tree-sitter-props-at-cursor",
"toggle",
])]
pub struct Syntax {
vim: Vim,
bufs: HashMap<usize, String>,
toggle: Toggle,
tree_sitter_info: HashMap<usize, TreeSitterInfo>,
ts_bufs: HashMap<usize, TreeSitterInfo>,
sublime_bufs: HashMap<usize, String>,
tree_sitter_enabled: bool,
}

impl Syntax {
pub fn new(vim: Vim) -> Self {
Self {
vim,
bufs: HashMap::new(),
toggle: Toggle::Off,
tree_sitter_info: HashMap::new(),
ts_bufs: HashMap::new(),
sublime_bufs: HashMap::new(),
tree_sitter_enabled: false,
}
}
Expand All @@ -86,7 +92,7 @@ impl Syntax {
.extension()
.and_then(|e| e.to_str())
{
self.bufs.insert(bufnr, extension.to_string());
self.sublime_bufs.insert(bufnr, extension.to_string());

if self.tree_sitter_enabled {
if tree_sitter::Language::try_from_extension(extension).is_some() {
Expand All @@ -101,8 +107,8 @@ impl Syntax {

/// Highlight the visual lines of specified buffer.
// TODO: this may be inaccurate, e.g., the lines are part of a bigger block of comments.
async fn syntect_highlight(&mut self, bufnr: usize) -> Result<(), PluginError> {
let Some(extension) = self.bufs.get(&bufnr) else {
async fn sublime_syntax_highlight(&mut self, bufnr: usize) -> Result<(), PluginError> {
let Some(extension) = self.sublime_bufs.get(&bufnr) else {
return Ok(());
};

Expand Down Expand Up @@ -174,7 +180,7 @@ impl Syntax {
Some(line_start - 1..line_end),
)?;

self.tree_sitter_info.insert(
self.ts_bufs.insert(
bufnr,
TreeSitterInfo {
language,
Expand Down Expand Up @@ -247,7 +253,7 @@ impl Syntax {
Some(line_start - 1..line_end),
)?;

self.tree_sitter_info.entry(bufnr).and_modify(|i| {
self.ts_bufs.entry(bufnr).and_modify(|i| {
i.highlights = new_highlights.into();
});

Expand All @@ -257,7 +263,7 @@ impl Syntax {
async fn tree_sitter_props_at_cursor(&mut self) -> Result<(), PluginError> {
let (bufnr, row, column) = self.vim.get_cursor_pos().await?;

if let Some(ts_info) = self.tree_sitter_info.get(&bufnr) {
if let Some(ts_info) = self.ts_bufs.get(&bufnr) {
if let Some(props) =
ts_info
.highlights
Expand Down Expand Up @@ -313,19 +319,20 @@ impl ClapPlugin for Syntax {
BufWritePost => {
if self.tree_sitter_enabled {
if self.vim.bufmodified(bufnr).await? {
if let Some(ts_info) = self.tree_sitter_info.get(&bufnr) {
if let Some(ts_info) = self.ts_bufs.get(&bufnr) {
self.refresh_tree_sitter_highlight(bufnr, ts_info.language)
.await?;
}
}
}
}
BufDelete => {
self.bufs.remove(&bufnr);
self.ts_bufs.remove(&bufnr);
self.sublime_bufs.remove(&bufnr);
}
CursorMoved => {
if self.tree_sitter_enabled {
if let Some(ts_info) = self.tree_sitter_info.get(&bufnr) {
if let Some(ts_info) = self.ts_bufs.get(&bufnr) {
// TODO: more efficient syntax highlighting update
let (_winid, line_start, line_end) =
self.vim.get_screen_lines_range().await?;
Expand All @@ -338,7 +345,7 @@ impl ClapPlugin for Syntax {
)?;
}
} else {
self.syntect_highlight(bufnr).await?;
self.sublime_syntax_highlight(bufnr).await?;
}
}
event => return Err(PluginError::UnhandledEvent(event)),
Expand All @@ -350,11 +357,6 @@ impl ClapPlugin for Syntax {
async fn handle_action(&mut self, action: ActionRequest) -> Result<(), PluginError> {
let ActionRequest { method, params: _ } = action;
match self.parse_action(method)? {
SyntaxAction::On => {
let bufnr = self.vim.bufnr("").await?;
self.on_buf_enter(bufnr).await?;
self.syntect_highlight(bufnr).await?;
}
SyntaxAction::TreeSitterHighlight => {
let bufnr = self.vim.bufnr("").await?;
self.tree_sitter_highlight(bufnr).await?;
Expand All @@ -364,11 +366,16 @@ impl ClapPlugin for Syntax {
SyntaxAction::TreeSitterPropsAtCursor => {
self.tree_sitter_props_at_cursor().await?;
}
SyntaxAction::ListThemes => {
SyntaxAction::ListSublimeThemes => {
let highlighter = &SUBLIME_SYNTAX_HIGHLIGHTER;
let theme_list = highlighter.get_theme_list();
self.vim.echo_info(theme_list.into_iter().join(","))?;
}
SyntaxAction::SublimeSyntaxHighlight => {
let bufnr = self.vim.bufnr("").await?;
self.on_buf_enter(bufnr).await?;
self.sublime_syntax_highlight(bufnr).await?;
}
SyntaxAction::Toggle => {
match self.toggle {
Toggle::On => {}
Expand Down
196 changes: 113 additions & 83 deletions crates/maple_core/src/stdio_server/provider/hooks/on_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use std::time::Duration;
use sublime_syntax::TokenHighlight;
use utils::display_width;

type SyntaxHighlights = Vec<(usize, Vec<TokenHighlight>)>;

/// Preview content.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Preview {
Expand All @@ -26,7 +28,7 @@ pub struct Preview {
pub fname: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hi_lnum: Option<usize>,
pub line_highlights: Vec<(usize, Vec<TokenHighlight>)>,
pub line_highlights: SyntaxHighlights,
#[serde(skip_serializing_if = "Option::is_none")]
pub scrollbar: Option<(usize, usize)>,
}
Expand Down Expand Up @@ -419,94 +421,28 @@ impl<'a> CachedPreviewImpl<'a> {
highlight_lnum,
lines,
}) => {
let mut context_lines = Vec::new();

// Some checks against the latest preview line.
if let Some(latest_line) = lines.get(highlight_lnum - 1) {
// TODO: No long needed once switched to libgrep officically.
// self.try_refresh_cache(latest_line);

if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
const BLACK_LIST: &[&str] =
&["log", "txt", "lock", "toml", "yaml", "mod", "conf"];

if !BLACK_LIST.contains(&ext)
&& !dumb_analyzer::is_comment(latest_line, ext)
{
match context_tag_with_timeout(path, lnum).await {
Some(tag) if tag.line_number < start => {
context_lines.reserve_exact(3);

let border_line = "─".repeat(if self.ctx.env.is_nvim {
container_width
} else {
// Vim has a different border width.
container_width - 2
});

context_lines.push(border_line.clone());

// Truncate the right of pattern, 2 whitespaces + 💡
let max_pattern_len = container_width - 4;
let pattern = tag.trimmed_pattern();
let (mut context_line, to_push) = if pattern.len()
> max_pattern_len
{
// Use the chars instead of indexing the str to avoid the char boundary error.
let p: String =
pattern.chars().take(max_pattern_len - 4 - 2).collect();
(p, ".. 💡")
} else {
(String::from(pattern), " 💡")
};
context_line.reserve(to_push.len());
context_line.push_str(to_push);
context_lines.push(context_line);

context_lines.push(border_line);
}
_ => {}
}
}
}
}

let context_lines = fetch_context_lines(
&lines,
highlight_lnum,
lnum,
start,
container_width,
path,
self.ctx.env.is_nvim,
)
.await;
let highlight_lnum = highlight_lnum + context_lines.len();

let context_lines_is_empty = context_lines.is_empty();

// 1 (header line) + 1 (1-based line number)
let line_number_offset = context_lines.len() + 1 + 1;
let maybe_line_highlights = if let Some(theme) =
&crate::config::config().provider.syntect_highlight_theme
{
const THEME: &str = "Visual Studio Dark+";
let theme = if SUBLIME_SYNTAX_HIGHLIGHTER.theme_exists(theme) {
theme
} else {
THEME
};
path.extension()
.and_then(|s| s.to_str())
.and_then(|extension| {
SUBLIME_SYNTAX_HIGHLIGHTER
.syntax_set
.find_syntax_by_extension(extension)
})
.map(|syntax| {
// Same reason as [`Self::truncate_preview_lines()`], if a line is too
// long and the query is short, the highlights can be enomerous and
// cause the Vim frozen due to the too many highlight works.
let max_len = self.max_line_width();
let lines = lines.iter().map(|s| {
let len = s.len().min(max_len);
&s[..len]
});
sublime_syntax_highlight(syntax, lines, line_number_offset, theme)
})
} else {
None
};
let maybe_line_highlights = fetch_syntax_highlights(
&lines,
path,
line_number_offset,
self.max_line_width(),
);

let header_line = truncated_preview_header();
let lines = std::iter::once(header_line)
Expand Down Expand Up @@ -662,3 +598,97 @@ async fn context_tag_with_timeout(path: &Path, lnum: usize) -> Option<BufferTag>
}
}
}

async fn fetch_context_lines(
lines: &[String],
highlight_lnum: usize,
lnum: usize,
start: usize,
container_width: usize,
path: &Path,
is_nvim: bool,
) -> Vec<String> {
let mut context_lines = Vec::new();

// Some checks against the latest preview line.
if let Some(latest_line) = lines.get(highlight_lnum - 1) {
// TODO: No long needed once switched to libgrep officically.
// self.try_refresh_cache(latest_line);

if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
const BLACK_LIST: &[&str] = &["log", "txt", "lock", "toml", "yaml", "mod", "conf"];

if !BLACK_LIST.contains(&ext) && !dumb_analyzer::is_comment(latest_line, ext) {
match context_tag_with_timeout(path, lnum).await {
Some(tag) if tag.line_number < start => {
context_lines.reserve_exact(3);

let border_line = "─".repeat(if is_nvim {
container_width
} else {
// Vim has a different border width.
container_width - 2
});

context_lines.push(border_line.clone());

// Truncate the right of pattern, 2 whitespaces + 💡
let max_pattern_len = container_width - 4;
let pattern = tag.trimmed_pattern();
let (mut context_line, to_push) = if pattern.len() > max_pattern_len {
// Use the chars instead of indexing the str to avoid the char boundary error.
let p: String = pattern.chars().take(max_pattern_len - 4 - 2).collect();
(p, ".. 💡")
} else {
(String::from(pattern), " 💡")
};
context_line.reserve(to_push.len());
context_line.push_str(to_push);
context_lines.push(context_line);

context_lines.push(border_line);
}
_ => {}
}
}
}
}

context_lines
}

fn fetch_syntax_highlights(
lines: &[String],
path: &Path,
line_number_offset: usize,
max_line_width: usize,
) -> Option<SyntaxHighlights> {
if let Some(theme) = &crate::config::config().provider.syntect_highlight_theme {
const THEME: &str = "Visual Studio Dark+";
let theme = if SUBLIME_SYNTAX_HIGHLIGHTER.theme_exists(theme) {
theme
} else {
THEME
};
path.extension()
.and_then(|s| s.to_str())
.and_then(|extension| {
SUBLIME_SYNTAX_HIGHLIGHTER
.syntax_set
.find_syntax_by_extension(extension)
})
.map(|syntax| {
// Same reason as [`Self::truncate_preview_lines()`], if a line is too
// long and the query is short, the highlights can be enomerous and
// cause the Vim frozen due to the too many highlight works.
let max_len = max_line_width;
let lines = lines.iter().map(|s| {
let len = s.len().min(max_len);
&s[..len]
});
sublime_syntax_highlight(syntax, lines, line_number_offset, theme)
})
} else {
None
}
}

0 comments on commit 2575858

Please sign in to comment.