code_blocks_server/
lib.rs1pub mod types;
2use std::path::PathBuf;
3
4use anyhow::{Context, Result};
5use code_blocks::{Block, BlockTree};
6use tree_sitter::{Language, Parser, Query};
7use tree_sitter_installer::parser_installer::{self, InstallationStatus};
8
9pub use types::*;
10
11#[derive(Debug)]
12pub struct InstallLanguageArgs<F: FnMut(InstallationStatus)> {
13 pub download_cmd: String,
14 pub library_name: String,
15 pub install_dir: PathBuf,
16 pub report_progress: Option<F>,
17}
18
19pub type InstallLanguageResponse = PathBuf;
20
21pub fn install_language<F: FnMut(InstallationStatus)>(
22 args: InstallLanguageArgs<F>,
23) -> Result<InstallLanguageResponse> {
24 if !parser_installer::is_installed_at(&args.library_name, &args.install_dir) {
25 parser_installer::install_parser(
26 &args.download_cmd,
27 &args.library_name,
28 &args.install_dir,
29 args.report_progress,
30 )
31 } else {
32 Ok(parser_installer::get_compiled_lib_path(
33 &args.library_name,
34 &args.install_dir,
35 ))
36 }
37}
38
39#[derive(Debug)]
40pub struct GetSubtreesArgs {
41 pub queries: Vec<String>,
42 pub text: String,
43 pub language: Language,
44}
45
46pub type GetSubtreesResponse = Vec<BlockLocationTree>;
47
48pub fn get_subtrees(args: GetSubtreesArgs) -> Result<GetSubtreesResponse> {
49 let mut parser = Parser::new();
50 parser.set_language(args.language)?;
51
52 let text = args.text;
53 let tree = parser.parse(&text, None).context("Failed to parse text")?;
54
55 let mut queries = vec![];
56 for query in args.queries {
57 queries.push(Query::new(args.language, &query)?);
58 }
59
60 let items = code_blocks::get_query_subtrees(&queries, &tree, &text);
61
62 Ok(items.iter().map(Into::into).collect())
63}
64
65#[derive(Debug)]
66pub struct MoveBlockArgs<C: Fn(&Block, &Block) -> Result<()>> {
67 pub queries: Vec<String>,
68 pub text: String,
69 pub language: Language,
70 pub src_block: BlockLocation,
71 pub dst_block: BlockLocation,
72 pub assert_move_legal_fn: Option<C>,
73 pub force: bool,
74}
75
76#[derive(Debug)]
77pub struct MoveBlockResponse {
78 pub text: String,
79 pub new_src_start: usize,
80 pub new_dst_start: usize,
81}
82
83pub fn move_block<C: Fn(&Block, &Block) -> Result<()>>(
84 args: MoveBlockArgs<C>,
85) -> Result<MoveBlockResponse> {
86 fn copy_item_at<'tree>(
87 location: &BlockLocation,
88 trees: &[BlockTree<'tree>],
89 ) -> Option<Block<'tree>> {
90 for tree in trees {
91 if &BlockLocation::from(&tree.block) == location {
92 return Some(tree.block.clone());
93 }
94 if let Some(node) = copy_item_at(location, &tree.children) {
95 return Some(node);
96 }
97 }
98 None
99 }
100
101 let mut parser = Parser::new();
102 parser.set_language(args.language)?;
103
104 let tree = parser
105 .parse(&args.text, None)
106 .context("Failed to parse text")?;
107
108 let mut queries = vec![];
109 for query in args.queries {
110 queries.push(Query::new(args.language, &query)?);
111 }
112
113 let subtrees = code_blocks::get_query_subtrees(&queries, &tree, &args.text);
114
115 let src_block = copy_item_at(&args.src_block, &subtrees).context("Failed to find src item")?;
116 let dst_item = copy_item_at(&args.dst_block, &subtrees).context("Failed to find dst item")?;
117
118 let (text, new_src_start, new_dst_start) = code_blocks::move_block(
119 src_block,
120 dst_item,
121 &args.text,
122 args.assert_move_legal_fn,
123 args.force,
124 )?;
125
126 Ok(MoveBlockResponse {
127 text,
128 new_src_start,
129 new_dst_start,
130 })
131}