change tree sitter to use crates

This commit is contained in:
Dongdong Zhou 2022-01-21 19:36:13 +00:00
parent 07a85e4ac6
commit 5592a6bcd0
20 changed files with 568 additions and 229 deletions

20
.gitmodules vendored
View File

@ -1,20 +0,0 @@
[submodule "core/languages/tree-sitter-rust"]
path = core/languages/tree-sitter-rust
url = https://github.com/tree-sitter/tree-sitter-rust
shallow = true
[submodule "core/languages/tree-sitter-toml"]
path = core/languages/tree-sitter-toml
url = https://github.com/ikatyang/tree-sitter-toml
shallow = true
[submodule "core/languages/tree-sitter-javascript"]
path = core/languages/tree-sitter-javascript
url = https://github.com/tree-sitter/tree-sitter-javascript
shallow = true
[submodule "core/languages/tree-sitter-yaml"]
path = core/languages/tree-sitter-yaml
url = https://github.com/ikatyang/tree-sitter-yaml
shallow = true
[submodule "core/languages/tree-sitter-go"]
path = core/languages/tree-sitter-go
url = https://github.com/tree-sitter/tree-sitter-go
shallow = true

40
Cargo.lock generated
View File

@ -1027,6 +1027,12 @@ dependencies = [
"syn",
]
[[package]]
name = "diff"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
[[package]]
name = "digest"
version = "0.8.1"
@ -2157,6 +2163,7 @@ dependencies = [
"config",
"crossbeam-channel 0.5.1",
"crossbeam-utils 0.8.5",
"diff",
"directories",
"druid",
"flate2",
@ -2184,7 +2191,10 @@ dependencies = [
"tinyfiledialogs",
"toml",
"tree-sitter",
"tree-sitter-go",
"tree-sitter-highlight",
"tree-sitter-javascript",
"tree-sitter-rust",
"unicode-segmentation",
"unicode-width",
"usvg",
@ -4739,6 +4749,16 @@ dependencies = [
"regex",
]
[[package]]
name = "tree-sitter-go"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71967701c8214be4aa77e0260e98361e6fd71ceec1d9d03abb37a22c9f60d0ff"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-highlight"
version = "0.20.1"
@ -4750,6 +4770,26 @@ dependencies = [
"tree-sitter",
]
[[package]]
name = "tree-sitter-javascript"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2490fab08630b2c8943c320f7b63473cbf65511c8d83aec551beb9b4375906ed"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-rust"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df540a493d754015d22eaf57c38f58804be3713a22f6062db983ec15f85c3c9"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "try-lock"
version = "0.2.3"

View File

@ -5,6 +5,7 @@ authors = ["Dongdong Zhou <dzhou121@gmail.com>"]
edition = "2021"
[dependencies]
diff = "0.1.12"
libloading = "0.7"
flate2 = "1.0.22"
reqwest = { version = "0.11", features = ["blocking", "json"] }
@ -30,6 +31,9 @@ parking_lot = { version = "0.11.0", features = ["deadlock_detection"] }
include_dir = "0.6.0"
tree-sitter = "0.20.2"
tree-sitter-highlight = "0.20.1"
tree-sitter-rust = "0.20.0"
tree-sitter-go = "0.19.1"
tree-sitter-javascript = "0.20.0"
anyhow = "1.0.32"
strum = "0.19"
strum_macros = "0.19"

View File

@ -1,94 +0,0 @@
use anyhow::{anyhow, Context, Result};
use std::fs;
use std::path::{Path, PathBuf};
fn collect_tree_sitter_dirs(ignore: &[String]) -> Result<Vec<String>> {
let mut dirs = Vec::new();
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("languages");
for entry in fs::read_dir(path)? {
let entry = entry?;
let path = entry.path();
if !entry.file_type()?.is_dir() {
continue;
}
let dir = path.file_name().unwrap().to_str().unwrap().to_string();
// filter ignores
if ignore.contains(&dir) {
continue;
}
dirs.push(dir)
}
Ok(dirs)
}
fn build_library(src_dir: &Path, language: &str) -> Result<()> {
let mut config = cc::Build::new();
config.include(&src_dir);
config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
config.file(&parser_path);
let scanner_path = src_dir.join("scanner.c");
if scanner_path.exists() {
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
config.file(&scanner_path);
}
let scanner_path = src_dir.join("scanner.cc");
if scanner_path.exists() {
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
config.file(&scanner_path);
config.cpp(true);
}
config.out_dir(src_dir);
config.compile(language);
Ok(())
}
fn build_dir(dir: &str, language: &str) {
println!("Build language {}", language);
if PathBuf::from("languages")
.join(dir)
.read_dir()
.unwrap()
.next()
.is_none()
{
eprintln!(
"The directory {} is empty, you probably need to use 'git submodule update --init --recursive'?",
dir
);
std::process::exit(1);
}
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("languages")
.join(dir)
.join("src");
build_library(&path, language).unwrap();
}
fn main() {
let ignore = vec![
"tree-sitter-typescript".to_string(),
"tree-sitter-ocaml".to_string(),
];
let dirs = collect_tree_sitter_dirs(&ignore).unwrap();
for dir in dirs {
let language = &dir.strip_prefix("tree-sitter-").unwrap();
build_dir(&dir, language);
}
}

@ -1 +0,0 @@
Subproject commit 0fa917a7022d1cd2e9b779a6a8fc5dc7fad69c75

@ -1 +0,0 @@
Subproject commit fdeb68ac8d2bd5a78b943528bb68ceda3aade2eb

@ -1 +0,0 @@
Subproject commit eeb0702ebdac504b97196577b1dac43c80913d7b

@ -1 +0,0 @@
Subproject commit 8bd2056818b21860e3d756b5a58c4f6e05fb744e

@ -1 +0,0 @@
Subproject commit 0e36bed171768908f331ff7dff9d956bae016efb

View File

@ -10,7 +10,7 @@
};
use druid::{Env, FontFamily, PaintCtx, Point};
use language::{new_highlight_config, new_parser, LapceLanguage};
use lapce_proxy::dispatch::NewBufferResponse;
use lapce_proxy::dispatch::{BufferHeadResponse, NewBufferResponse};
use lsp_types::SemanticTokensServerCapabilities;
use lsp_types::{CallHierarchyOptions, SemanticTokensLegend};
use lsp_types::{
@ -35,10 +35,6 @@
use std::{collections::HashMap, fs::File};
use std::{fs, str::FromStr};
use tree_sitter::{Node, Parser, Tree};
use tree_sitter_highlight::{
Highlight, HighlightConfiguration, HighlightEvent, Highlighter,
};
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
use xi_core_lib::selection::InsertDrift;
use xi_rope::{
@ -58,8 +54,6 @@
use crate::{
command::LapceUICommand,
command::LAPCE_UI_COMMAND,
data::LapceEditorViewData,
editor::EditorOperator,
find::Find,
language,
movement::{ColPosition, LinePosition, Movement, SelRegion, Selection},
@ -217,6 +211,7 @@ pub struct BufferNew {
pub local: bool,
update_sender: Arc<Sender<UpdateEvent>>,
pub line_changes: HashMap<usize, char>,
pub histories: im::HashMap<String, Rope>,
pub find: Rc<RefCell<Find>>,
pub find_progress: Rc<RefCell<FindProgress>>,
@ -270,6 +265,7 @@ pub fn new(
update_sender,
local: false,
line_changes: HashMap::new(),
histories: im::HashMap::new(),
revs: vec![Revision {
max_undo_so_far: 0,
@ -362,6 +358,44 @@ pub fn notify_update(&self) {
}
}
pub fn retrieve_file_head(
&self,
tab_id: WidgetId,
proxy: Arc<LapceProxy>,
event_sink: ExtEventSink,
) {
let id = self.id;
if let BufferContent::File(path) = &self.content {
let path = path.clone();
thread::spawn(move || {
proxy.get_buffer_head(
id,
path.clone(),
Box::new(move |result| {
if let Ok(res) = result {
if let Ok(resp) =
serde_json::from_value::<BufferHeadResponse>(res)
{
println!("load buffer head {}", resp.content);
event_sink.submit_command(
LAPCE_UI_COMMAND,
LapceUICommand::LoadBufferHead {
path,
content: Rope::from(resp.content),
id: resp.id,
},
Target::Widget(tab_id),
);
}
}
}),
)
});
}
}
pub fn retrieve_file_history(&self) {}
pub fn retrieve_file(
&self,
tab_id: WidgetId,

View File

@ -16,7 +16,7 @@
use strum_macros::{Display, EnumIter, EnumMessage, EnumProperty, EnumString};
use tree_sitter::Tree;
use tree_sitter_highlight::Highlight;
use xi_rope::spans::Spans;
use xi_rope::{spans::Spans, Rope};
use crate::{
buffer::BufferId,
@ -411,6 +411,11 @@ pub enum LapceUICommand {
content: String,
locations: Vec<(WidgetId, EditorLocationNew)>,
},
LoadBufferHead {
path: PathBuf,
id: String,
content: Rope,
},
LoadBufferAndGoToPosition {
path: PathBuf,
content: String,
@ -420,6 +425,7 @@ pub enum LapceUICommand {
SetWorkspace(LapceWorkspace),
SetTheme(String, bool),
OpenFile(PathBuf),
OpenFileDiff(PathBuf, String),
CancelCompletion(usize),
ResolveCompletion(BufferId, u64, usize, CompletionItem),
UpdateCompletion(usize, String, CompletionResponse),

View File

@ -829,6 +829,7 @@ pub fn run_workbench_command(
path: path.clone(),
position: None,
scroll_offset: None,
hisotry: None,
},
&self.config,
);
@ -853,6 +854,7 @@ pub fn run_workbench_command(
path: path.clone(),
position: None,
scroll_offset: None,
hisotry: None,
},
&self.config,
);
@ -1592,6 +1594,7 @@ pub fn jump_to_position(
path: path.clone(),
position: Some(position),
scroll_offset: None,
hisotry: None,
};
self.jump_to_location(ctx, editor_view_id, location, config);
}
@ -1653,8 +1656,19 @@ pub fn go_to_location(
None => (buffer.cursor_offset, Some(&buffer.scroll_offset)),
};
if let Some(compare) = location.hisotry.as_ref() {
if !buffer.histories.contains_key(compare) {
buffer.retrieve_file_head(
*self.tab_id,
self.proxy.clone(),
ctx.get_external_handle(),
);
}
}
let editor = self.get_editor_or_new(ctx, Some(editor_view_id), config);
editor.content = BufferContent::File(path.clone());
editor.compare = location.hisotry.clone();
editor.cursor = if config.lapce.modal {
Cursor::new(CursorMode::Normal(offset), None)
} else {
@ -1751,6 +1765,7 @@ pub fn new(
e.scroll_offset.0,
e.scroll_offset.1,
)),
hisotry: None,
},
));
@ -1883,6 +1898,7 @@ pub struct LapceEditorData {
pub split_id: Option<WidgetId>,
pub view_id: WidgetId,
pub content: BufferContent,
pub compare: Option<String>,
pub scroll_offset: Vec2,
pub cursor: Cursor,
pub size: Rc<RefCell<Size>>,
@ -1913,6 +1929,7 @@ pub fn new(
Cursor::new(CursorMode::Insert(Selection::caret(0)), None)
},
size: Rc::new(RefCell::new(Size::ZERO)),
compare: None,
window_origin: Point::ZERO,
snippet: None,
locations: vec![],
@ -1956,6 +1973,7 @@ pub fn save_jump_location(&mut self, buffer: &BufferNew) {
path: path.clone(),
position: Some(buffer.offset_to_position(self.cursor.offset())),
scroll_offset: Some(self.scroll_offset.clone()),
hisotry: None,
};
self.locations.push(location);
self.current_location = self.locations.len();
@ -2302,6 +2320,7 @@ pub fn next_error(&mut self, ctx: &mut EventCtx, env: &Env) {
path,
position: Some(position),
scroll_offset: None,
hisotry: None,
};
ctx.submit_command(Command::new(
LAPCE_UI_COMMAND,
@ -2775,6 +2794,7 @@ fn process_get_references(
path: PathBuf::from(location.uri.path()),
position: Some(location.range.start.clone()),
scroll_offset: None,
hisotry: None,
},
),
Target::Auto,

View File

@ -71,6 +71,8 @@
FontWeight,
};
use fzyr::has_match;
use hashbrown::HashSet;
use indexmap::IndexMap;
use itertools::Itertools;
use lsp_types::CompletionTextEdit;
use lsp_types::{
@ -79,6 +81,7 @@
Location, Position, SignatureHelp, TextEdit, Url, WorkspaceEdit,
};
use serde_json::Value;
use std::ops::Range;
use std::thread;
use std::{cmp::Ordering, iter::Iterator, path::PathBuf};
use std::{collections::HashMap, sync::Arc};
@ -139,6 +142,7 @@ pub struct EditorLocationNew {
pub path: PathBuf,
pub position: Option<Position>,
pub scroll_offset: Option<Vec2>,
pub hisotry: Option<String>,
}
#[derive(Clone, Debug)]
@ -222,6 +226,19 @@ pub struct LapceEditorBufferData {
pub config: Arc<Config>,
}
pub enum DiffLines {
Left(Range<usize>),
Both(Range<usize>, Range<usize>),
Right(Range<usize>),
}
#[derive(Hash, Eq, PartialEq, Clone)]
pub enum DiffCurrentLine {
Left(usize),
Both(usize, usize),
Right(usize),
}
impl LapceEditorBufferData {
fn buffer_mut(&mut self) -> &mut BufferNew {
Arc::make_mut(&mut self.buffer)
@ -994,6 +1011,7 @@ fn next_error(&mut self, ctx: &mut EventCtx, env: &Env) {
path,
position: Some(position),
scroll_offset: None,
hisotry: None,
};
ctx.submit_command(Command::new(
LAPCE_UI_COMMAND,
@ -1325,7 +1343,9 @@ fn paint_content(
let line_height = self.config.editor.line_height as f64;
self.paint_cursor(ctx, is_focused, placeholder, config);
self.paint_find(ctx);
let self_size = ctx.size();
let rect = ctx.region().bounding_box();
let last_line = self.buffer.last_line();
let start_line = (rect.y0 / line_height).floor() as usize;
let end_line = (rect.y1 / line_height).ceil() as usize;
@ -1340,6 +1360,340 @@ fn paint_content(
.unwrap();
let y_shift = (line_height - text_layout.size().height) / 2.0;
if let Some(compare) = self.editor.compare.as_ref() {
if let Some(history) = self.buffer.histories.get(compare) {
let mut left_line = 0;
let mut right_line = 0;
let mut changes = IndexMap::new();
let left_str = &history.slice_to_cow(0..history.len());
let right_str =
&self.buffer.rope.slice_to_cow(0..self.buffer.rope.len());
for diff in diff::lines(left_str, right_str) {
match diff {
diff::Result::Left(l) => {
let key = DiffCurrentLine::Right(right_line);
if !changes.contains_key(&key) {
changes.insert(
key.clone(),
DiffLines::Left(left_line..left_line),
);
}
if let DiffLines::Left(range) =
changes.get_mut(&key).unwrap()
{
range.end = left_line;
}
left_line += 1;
}
diff::Result::Both(_, _) => {
if !changes
.last()
.map(|(key, value)| match key {
DiffCurrentLine::Both(_, _) => true,
_ => false,
})
.unwrap_or(false)
{
changes.insert(
DiffCurrentLine::Both(left_line, right_line),
DiffLines::Both(
left_line..left_line,
right_line..right_line,
),
);
}
if let DiffLines::Both(left, right) =
changes.last_mut().unwrap().1
{
left.end = left_line;
right.end = right_line;
}
left_line += 1;
right_line += 1;
}
diff::Result::Right(_) => {
let key = DiffCurrentLine::Left(left_line);
if !changes.contains_key(&key) {
changes.insert(
key.clone(),
DiffLines::Right(right_line..right_line),
);
}
if let DiffLines::Right(range) =
changes.get_mut(&key).unwrap()
{
range.end = right_line;
}
right_line += 1;
}
}
}
let mut line = 0;
for (key, change) in changes.iter() {
match change {
DiffLines::Left(range) => {
line += range.len();
if line < start_line {
continue;
}
ctx.fill(
Size::new(
self_size.width,
line_height * range.len() as f64,
)
.to_rect()
.with_origin(
Point::new(
0.0,
line_height * (line - range.len()) as f64,
),
),
&Color::RED,
);
if line > end_line {
break;
}
}
DiffLines::Both(left, right) => {
line += right.len().min(6);
if line < start_line {
continue;
}
if line > end_line {
break;
}
}
DiffLines::Right(range) => {
line += range.len();
if line < start_line {
continue;
}
ctx.fill(
Size::new(
self_size.width,
line_height * range.len() as f64,
)
.to_rect()
.with_origin(
Point::new(
0.0,
line_height * (line - range.len()) as f64,
),
),
&Color::GREEN,
);
if line > end_line {
break;
}
}
}
}
return;
let mut line = 0;
let mut left_line = 0;
let mut changes = IndexMap::new();
let mut deletes = IndexMap::new();
let mut adds = HashSet::new();
for diff in diff::lines(
&history.slice_to_cow(0..history.len()),
&self.buffer.rope.slice_to_cow(0..self.buffer.rope.len()),
) {
match diff {
diff::Result::Left(l) => {
if !deletes.contains_key(&line) {
deletes.insert(line, vec![]);
}
deletes.get_mut(&line).unwrap().push(l.to_string());
if !changes.contains_key(&line) {
changes.insert(line, 0);
}
*changes.get_mut(&line).unwrap() -= 1;
}
diff::Result::Both(_, _) => {
line += 1;
}
diff::Result::Right(_) => {
adds.insert(line);
let mut had_previous = false;
if let Some((last_line, last)) = changes.last_mut() {
if *last > 0 && *last_line + *last == line {
*last += 1;
had_previous = true;
}
}
if !had_previous {
changes.insert(line, 1);
}
line += 1;
}
}
}
let mut line = 0;
let mut deleted_lines = 0;
let mut skipped_lines = 0;
for (changed_line, change) in changes.iter() {}
for (delete_line, delete) in deletes.iter() {
if delete_line + deleted_lines + delete.len() < start_line {
deleted_lines += delete.len();
continue;
}
if delete_line + deleted_lines < start_line {
for (i, deleted_str) in delete
[start_line - (delete_line + deleted_lines)..]
.iter()
.enumerate()
{
line = delete_line + deleted_lines + i;
if line > end_line {
break;
}
ctx.fill(
Size::new(self_size.width, line_height)
.to_rect()
.with_origin(Point::new(
0.0,
line_height * line as f64,
)),
&Color::RED,
);
let text_layout = ctx
.text()
.new_text_layout(deleted_str.to_string())
.font(
config.editor.font_family(),
config.editor.font_size as f64,
)
.build_with_bounds([rect.x0, rect.x1]);
ctx.draw_text(
&text_layout,
Point::new(0.0, line_height * line as f64 + y_shift),
);
}
line += 1;
deleted_lines += delete.len();
continue;
}
if line < start_line {
line = start_line;
}
for i in line..delete_line + deleted_lines {
if line > end_line {
break;
}
let actual_line = line - deleted_lines;
if actual_line > last_line {
break;
}
if adds.contains(&actual_line) {
ctx.fill(
Size::new(self_size.width, line_height)
.to_rect()
.with_origin(Point::new(
0.0,
line_height * line as f64,
)),
&Color::GREEN,
);
}
let text_layout = self.buffer.new_text_layout(
ctx,
actual_line,
&self.buffer.line_content(actual_line),
None,
[rect.x0, rect.x1],
&self.config,
);
ctx.draw_text(
&text_layout,
Point::new(0.0, line_height * line as f64 + y_shift),
);
line += 1;
}
for (i, deleted_str) in delete.iter().enumerate() {
line = delete_line + deleted_lines + i;
if line > end_line {
break;
}
ctx.fill(
Size::new(self_size.width, line_height)
.to_rect()
.with_origin(Point::new(
0.0,
line_height * line as f64,
)),
&Color::RED,
);
let text_layout = ctx
.text()
.new_text_layout(deleted_str.to_string())
.font(
config.editor.font_family(),
config.editor.font_size as f64,
)
.build_with_bounds([rect.x0, rect.x1]);
ctx.draw_text(
&text_layout,
Point::new(0.0, line_height * line as f64 + y_shift),
);
}
line += 1;
deleted_lines += delete.len();
}
if line < start_line {
line = start_line;
}
for i in line..end_line {
let actual_line = line - deleted_lines;
if actual_line > last_line {
break;
}
if adds.contains(&actual_line) {
ctx.fill(
Size::new(self_size.width, line_height)
.to_rect()
.with_origin(Point::new(
0.0,
line_height * line as f64,
)),
&Color::GREEN,
);
}
let text_layout = self.buffer.new_text_layout(
ctx,
actual_line,
&self.buffer.line_content(actual_line),
None,
[rect.x0, rect.x1],
&self.config,
);
ctx.draw_text(
&text_layout,
Point::new(0.0, line_height * line as f64 + y_shift),
);
line += 1;
}
return;
}
}
let cursor_offset = self.editor.cursor.offset();
let cursor_line = self.buffer.line_of_offset(cursor_offset);
let start_offset = self.buffer.offset_of_line(start_line);
@ -2586,6 +2940,7 @@ fn run_command(
location.range.start,
),
scroll_offset: None,
hisotry: None,
},
),
Target::Auto,
@ -4306,36 +4661,6 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) {
let is_focused = data.focus == self.view_id;
let data = data.editor_view_content(self.view_id);
data.paint_content(ctx, is_focused, self.placeholder.as_ref(), &data.config);
// LapceEditorViewContent::None => {
// let svg = logo_svg();
// let size = ctx.size();
// let svg_size = 100.0;
// let rect = Size::ZERO
// .to_rect()
// .with_origin(
// Point::new(size.width / 2.0, size.height / 2.0)
// + (0.0, -svg_size),
// )
// .inflate(svg_size, svg_size);
// ctx.draw_svg(
// &svg,
// rect,
// Some(
// &data
// .config
// .get_color_unchecked(LapceTheme::EDITOR_DIM)
// .clone()
// .with_alpha(0.5),
// ),
// );
// for (cmd, text, rect, keymap) in &self.commands {
// ctx.draw_text(text, rect.origin());
// ctx.draw_text(
// keymap,
// rect.origin() + (20.0 + rect.width(), 0.0),
// );
// }
// }
}
}
@ -4473,6 +4798,7 @@ fn process_get_references(
path: PathBuf::from(location.uri.path()),
position: Some(location.range.start.clone()),
scroll_offset: None,
hisotry: None,
},
),
Target::Auto,

View File

@ -7,12 +7,6 @@
use tree_sitter::{Language, Parser};
use tree_sitter_highlight::HighlightConfiguration;
#[cfg(unix)]
const DYLIB_EXTENSION: &str = "so";
#[cfg(windows)]
const DYLIB_EXTENSION: &str = "dll";
pub const QUERIES_DIR: Dir = include_dir!("../runtime/queries");
lazy_static! {
pub static ref SCOPES: Vec<String> = vec![
@ -43,10 +37,8 @@
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
pub enum LapceLanguage {
Rust,
Toml,
Javascript,
Go,
Yaml,
}
impl LapceLanguage {
@ -54,12 +46,12 @@ pub fn from_path(path: &PathBuf) -> Option<LapceLanguage> {
let extension = path.extension()?.to_str()?;
Some(match extension {
"rs" => LapceLanguage::Rust,
"toml" => LapceLanguage::Toml,
"js" => LapceLanguage::Javascript,
"jsx" => LapceLanguage::Javascript,
"go" => LapceLanguage::Go,
"yaml" => LapceLanguage::Yaml,
"yml" => LapceLanguage::Yaml,
// "toml" => LapceLanguage::Toml,
// "yaml" => LapceLanguage::Yaml,
// "yml" => LapceLanguage::Yaml,
_ => return None,
})
}
@ -73,7 +65,7 @@ pub fn new_highlight_config(language: LapceLanguage) -> HighlightConfiguration {
match language {
LapceLanguage::Rust => {
let mut configuration = HighlightConfiguration::new(
unsafe { tree_sitter_rust() },
tree_sitter_rust::language(),
QUERIES_DIR
.get_file("rust/highlights.scm")
.unwrap()
@ -86,24 +78,9 @@ pub fn new_highlight_config(language: LapceLanguage) -> HighlightConfiguration {
configuration.configure(&SCOPES);
configuration
}
LapceLanguage::Toml => {
let mut configuration = HighlightConfiguration::new(
unsafe { tree_sitter_toml() },
QUERIES_DIR
.get_file("toml/highlights.scm")
.unwrap()
.contents_utf8()
.unwrap(),
"",
"",
)
.unwrap();
configuration.configure(&SCOPES);
configuration
}
LapceLanguage::Javascript => {
let mut configuration = HighlightConfiguration::new(
unsafe { tree_sitter_javascript() },
tree_sitter_javascript::language(),
QUERIES_DIR
.get_file("javascript/highlights.scm")
.unwrap()
@ -116,24 +93,9 @@ pub fn new_highlight_config(language: LapceLanguage) -> HighlightConfiguration {
configuration.configure(&SCOPES);
configuration
}
LapceLanguage::Yaml => {
let mut configuration = HighlightConfiguration::new(
unsafe { tree_sitter_yaml() },
QUERIES_DIR
.get_file("yaml/highlights.scm")
.unwrap()
.contents_utf8()
.unwrap(),
"",
"",
)
.unwrap();
configuration.configure(&SCOPES);
configuration
}
LapceLanguage::Go => {
let mut configuration = HighlightConfiguration::new(
unsafe { tree_sitter_go() },
tree_sitter_go::language(),
QUERIES_DIR
.get_file("go/highlights.scm")
.unwrap()
@ -151,34 +113,11 @@ pub fn new_highlight_config(language: LapceLanguage) -> HighlightConfiguration {
pub fn new_parser(language: LapceLanguage) -> Parser {
let language = match language {
LapceLanguage::Rust => unsafe { tree_sitter_rust() },
LapceLanguage::Toml => unsafe { tree_sitter_toml() },
LapceLanguage::Javascript => unsafe { tree_sitter_javascript() },
LapceLanguage::Go => unsafe { tree_sitter_go() },
LapceLanguage::Yaml => unsafe { tree_sitter_yaml() },
LapceLanguage::Rust => tree_sitter_rust::language(),
LapceLanguage::Javascript => tree_sitter_javascript::language(),
LapceLanguage::Go => tree_sitter_go::language(),
};
let mut parser = Parser::new();
parser.set_language(language).unwrap();
parser
}
extern "C" {
fn tree_sitter_rust() -> Language;
fn tree_sitter_toml() -> Language;
fn tree_sitter_yaml() -> Language;
fn tree_sitter_go() -> Language;
fn tree_sitter_javascript() -> Language;
}
// impl TreeSitter {
// pub fn new() -> TreeSitter {
// let mut parsers = HashMap::new();
//
// let mut parser = Parser::new();
// let language = tree_sitter_rust::language();
// parser.set_language(language);
// parsers.insert(LapceLanguage::Rust, parser);
//
// TreeSitter { parsers }
// }
// }

View File

@ -147,6 +147,7 @@ fn mouse_down(
.unwrap_or(d.diagnositc.range.start.clone()),
),
scroll_offset: None,
hisotry: None,
},
),
Target::Widget(data.id),
@ -175,6 +176,7 @@ fn mouse_down(
related.location.range.start.clone(),
),
scroll_offset: None,
hisotry: None,
},
),
Target::Widget(data.id),

View File

@ -277,6 +277,20 @@ pub fn install_plugin(&self, plugin: &PluginDescription) {
.send_rpc_notification("install_plugin", &json!({ "plugin": plugin }));
}
pub fn get_buffer_head(
&self,
buffer_id: BufferId,
path: PathBuf,
f: Box<dyn Callback>,
) {
self.wait();
self.peer.lock().as_ref().unwrap().send_rpc_request_async(
"buffer_head",
&json!({ "buffer_id": buffer_id, "path": path, }),
f,
);
}
pub fn new_buffer(
&self,
buffer_id: BufferId,

View File

@ -1650,7 +1650,6 @@ pub fn handle_scroll(
) {
if !ctx.is_handled() {
if let Event::Wheel(mouse) = event {
println!("view port {} {}", port.rect, port.content_size);
if port.pan_by(mouse.wheel_delta.round()) {}
ctx.request_paint();
self.reset_scrollbar_fade(|d| ctx.request_timer(d), env);

View File

@ -239,6 +239,15 @@ fn event(
source_control.file_list_index = line;
if mouse_event.pos.x < line_height {
self.mouse_down = Some(line);
} else {
ctx.submit_command(Command::new(
LAPCE_UI_COMMAND,
LapceUICommand::OpenFileDiff(
source_control.diff_files[line].0.clone(),
"head".to_string(),
),
Target::Widget(data.id),
));
}
}
}

View File

@ -279,6 +279,13 @@ fn event(
}
ctx.set_handled();
}
LapceUICommand::LoadBufferHead { path, id, content } => {
let buffer =
data.main_split.open_files.get_mut(path).unwrap();
let buffer = Arc::make_mut(buffer);
buffer.histories.insert(id.clone(), content.clone());
ctx.set_handled();
}
LapceUICommand::UpdateTerminalTitle(term_id, title) => {
let terminal_panel = Arc::make_mut(&mut data.terminal);
if let Some(mut terminal) =
@ -427,6 +434,21 @@ fn event(
);
ctx.set_handled();
}
LapceUICommand::OpenFileDiff(path, history) => {
let editor_view_id = data.main_split.active.clone();
data.main_split.jump_to_location(
ctx,
*editor_view_id,
EditorLocationNew {
path: path.clone(),
position: None,
scroll_offset: None,
hisotry: Some(history.to_string()),
},
&data.config,
);
ctx.set_handled();
}
LapceUICommand::OpenFile(path) => {
let editor_view_id = data.main_split.active.clone();
data.main_split.jump_to_location(
@ -436,6 +458,7 @@ fn event(
path: path.clone(),
position: None,
scroll_offset: None,
hisotry: None,
},
&data.config,
);
@ -555,6 +578,7 @@ fn event(
path: PathBuf::from(l.uri.path()),
position: Some(l.range.start.clone()),
scroll_offset: None,
hisotry: None,
})
.collect();
ctx.submit_command(Command::new(

View File

@ -5,7 +5,7 @@
use crate::terminal::{TermId, Terminal};
use alacritty_terminal::event_loop::Msg;
use alacritty_terminal::term::SizeInfo;
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use crossbeam_channel::{unbounded, Receiver, Sender};
use git2::{DiffOptions, Oid, Repository};
use jsonrpc_lite::{self, JsonRpc};
@ -145,6 +145,10 @@ pub enum Request {
buffer_id: BufferId,
path: PathBuf,
},
BufferHead {
buffer_id: BufferId,
path: PathBuf,
},
GetCompletion {
request_id: usize,
buffer_id: BufferId,
@ -194,6 +198,12 @@ pub struct NewBufferResponse {
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BufferHeadResponse {
pub id: String,
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct FileNodeItem {
pub path_buf: PathBuf,
@ -521,6 +531,20 @@ fn handle_request(&self, id: RequestId, rpc: Request) {
"result": resp,
}));
}
Request::BufferHead { buffer_id, path } => {
let workspace = self.workspace.lock().clone();
let result = file_get_head(&workspace, &path);
if let Ok((blob_id, content)) = result {
let resp = BufferHeadResponse {
id: "head".to_string(),
content,
};
self.sender.send(json!({
"id": id,
"result": resp,
}));
}
}
Request::GetCompletion {
buffer_id,
position,
@ -706,6 +730,23 @@ fn git_diff(workspace_path: &PathBuf) -> Option<Vec<String>> {
Some(diff_files)
}
fn file_get_head(
workspace_path: &PathBuf,
path: &PathBuf,
) -> Result<(String, String)> {
let repo =
Repository::open(workspace_path.to_str().ok_or(anyhow!("can't to str"))?)?;
let head = repo.head()?;
let tree = head.peel_to_tree()?;
let tree_entry = tree.get_path(path.strip_prefix(workspace_path)?)?;
let blob = repo.find_blob(tree_entry.id())?;
let id = blob.id().to_string();
let content = std::str::from_utf8(blob.content())
.with_context(|| "content bytes to string")?
.to_string();
Ok((id, content))
}
fn file_git_diff(
workspace_path: &PathBuf,
path: &PathBuf,