diff --git a/README.md b/README.md index 8dbd089..4ed4e14 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ IWE functions in two modes: This tool lets you process thousands of documents in just a second. With IWE, you can reformat documents and update link titles across your entire library. You can also use the CLI mode to combine multiple files into one extended document. -Please see the documenation at [IWE](https://iwe.md) for more information and setup instructions. +Please see the [documenation](https://iwe.md/docs/) at [IWE](https://iwe.md) for more information and [setup instructions](https://iwe.md/docs/how-to-install/). ## Inspired by many other opens-source projects diff --git a/crates/iwes/src/router/server.rs b/crates/iwes/src/router/server.rs index 130d40d..3714c5b 100644 --- a/crates/iwes/src/router/server.rs +++ b/crates/iwes/src/router/server.rs @@ -49,6 +49,10 @@ impl DatabaseContext for &Server { fn parser(&self, id: &Key) -> Option { self.database().parser(id) } + + fn lines(&self, key: &Key) -> u32 { + self.database().lines(key) + } } impl Server { @@ -295,12 +299,16 @@ impl Server { .clone() .to_url(&self.base_path) .to_delete_file_op()]) - .chain(vec![{ - params.new_name.to_url(&self.base_path).to_override_file_op( - &self.base_path, - patch.export_key(¶ms.new_name).expect("to have key"), - ) - }]) + .chain(vec![ + params.new_name.to_url(&self.base_path).to_create_file_op(), + params + .new_name + .to_url(&self.base_path) + .to_override_new_file_op( + &self.base_path, + patch.export_key(¶ms.new_name).expect("to have key"), + ), + ]) .collect(); WorkspaceEdit { diff --git a/crates/iwes/src/router/server/extensions.rs b/crates/iwes/src/router/server/extensions.rs index f8b6f9e..7629523 100644 --- a/crates/iwes/src/router/server/extensions.rs +++ b/crates/iwes/src/router/server/extensions.rs @@ -161,6 +161,28 @@ pub impl Url { DocumentChangeOperation::Edit(self.to_override_file(base_path, text)) } + fn to_override_new_file_op( + &self, + base_path: &BasePath, + text: String, + ) -> DocumentChangeOperation { + DocumentChangeOperation::Edit(self.to_override_new_file(base_path, text)) + } + + fn to_override_new_file(&self, _: &BasePath, text: Content) -> TextDocumentEdit { + let insert_extracted_text = TextEdit { + range: Range::new(Position::new(0, 0), Position::new(0, 0)), + new_text: text, + }; + TextDocumentEdit { + text_document: OptionalVersionedTextDocumentIdentifier { + uri: self.clone(), + version: None, + }, + edits: vec![OneOf::Left(insert_extracted_text)], + } + } + fn to_override_file(&self, _: &BasePath, text: Content) -> TextDocumentEdit { let insert_extracted_text = TextEdit { range: Range::new(Position::new(0, 0), Position::new(u32::MAX, 0)), diff --git a/crates/iwes/tests/rename_test.rs b/crates/iwes/tests/rename_test.rs index ee96343..21c182d 100644 --- a/crates/iwes/tests/rename_test.rs +++ b/crates/iwes/tests/rename_test.rs @@ -1,9 +1,7 @@ -use std::u32; - use indoc::indoc; use lsp_server::ResponseError; use lsp_types::{ - DeleteFile, DocumentChangeOperation, DocumentChanges, OneOf, + CreateFile, CreateFileOptions, DeleteFile, DocumentChangeOperation, DocumentChanges, OneOf, OptionalVersionedTextDocumentIdentifier, Position, PrepareRenameResponse, Range, RenameParams, ResourceOp, TextDocumentEdit, TextDocumentIdentifier, TextDocumentPositionParams, TextEdit, WorkspaceEdit, @@ -147,6 +145,14 @@ fn assert_rename_at(source: &str, expected: &str, position: Position, new_name: uri: uri(1), options: None, })), + DocumentChangeOperation::Op(ResourceOp::Create(CreateFile { + uri: uri_from("new_name"), + options: Some(CreateFileOptions { + overwrite: Some(false), + ignore_if_exists: Some(false), + }), + annotation_id: None, + })), DocumentChangeOperation::Edit(TextDocumentEdit { text_document: OptionalVersionedTextDocumentIdentifier { uri: uri_from("new_name"), @@ -154,7 +160,7 @@ fn assert_rename_at(source: &str, expected: &str, position: Position, new_name: }, edits: vec![OneOf::Left(TextEdit { new_text: expected.to_string(), - range: Range::new(Position::new(0, 0), Position::new(u32::MAX, 0)), + range: Range::new(Position::new(0, 0), Position::new(0, 0)), })], }), ])), @@ -212,6 +218,14 @@ fn assert_rename_updates_second_file(source: &str, expected1: &str, expected2: & uri: uri(1), options: None, })), + DocumentChangeOperation::Op(ResourceOp::Create(CreateFile { + uri: uri_from("new_name"), + options: Some(CreateFileOptions { + overwrite: Some(false), + ignore_if_exists: Some(false), + }), + annotation_id: None, + })), DocumentChangeOperation::Edit(TextDocumentEdit { text_document: OptionalVersionedTextDocumentIdentifier { uri: uri_from("new_name"), @@ -219,7 +233,7 @@ fn assert_rename_updates_second_file(source: &str, expected1: &str, expected2: & }, edits: vec![OneOf::Left(TextEdit { new_text: expected1.to_string(), - range: Range::new(Position::new(0, 0), Position::new(u32::MAX, 0)), + range: Range::new(Position::new(0, 0), Position::new(0, 0)), })], }), ])), diff --git a/crates/liwe/src/action.rs b/crates/liwe/src/action.rs index 22cd323..f2b965d 100644 --- a/crates/liwe/src/action.rs +++ b/crates/liwe/src/action.rs @@ -342,39 +342,42 @@ pub fn inline_quote(target_id: NodeId, context: impl GraphContext) -> Option Option { Some(target_id) .filter(|target_id| context.is_reference(*target_id)) - .map(|target_id| { + .and_then(|target_id| { let key = context.get_key(target_id); let inline_key = context.get_reference_key(target_id); let mut patch = context.patch(); - - patch.add_key( - &key, - context - .visit(&key) - .collect_tree() - .remove_node(target_id) - .append_pre_header( - context.get_surrounding_section_id(target_id).unwrap(), - context.visit(&inline_key).collect_tree(), - ) - .iter(), - ); - - let markdown = patch.markdown(&key).unwrap(); - - Action { - title: "Inline section".to_string(), - changes: vec![ - Change::Remove(Remove { - key: context.get_reference_key(target_id), - }), - Change::Update(Update { - key: key, - markdown: markdown, - }), - ], - action_type: ActionType::ReferenceInlineSection, - } + context + .get_surrounding_section_id(target_id) + .map(|section_id| { + patch.add_key( + &key, + context + .visit(&key) + .collect_tree() + .remove_node(target_id) + .append_pre_header( + section_id, + context.visit(&inline_key).collect_tree(), + ) + .iter(), + ); + + let markdown = patch.markdown(&key).unwrap(); + + Action { + title: "Inline section".to_string(), + changes: vec![ + Change::Remove(Remove { + key: context.get_reference_key(target_id), + }), + Change::Update(Update { + key: key, + markdown: markdown, + }), + ], + action_type: ActionType::ReferenceInlineSection, + } + }) }) } diff --git a/crates/liwe/src/database.rs b/crates/liwe/src/database.rs index 422481d..9ddc1c8 100644 --- a/crates/liwe/src/database.rs +++ b/crates/liwe/src/database.rs @@ -13,6 +13,7 @@ pub struct Database { } pub trait DatabaseContext { + fn lines(&self, key: &Key) -> u32; fn parser(&self, key: &Key) -> Option; } @@ -26,6 +27,17 @@ impl DatabaseContext for &Database { .get(key) .map(|content| Parser::new(&content, MarkdownReader::new())) } + + fn lines(&self, key: &Key) -> u32 { + if key.ends_with(".md") { + panic!("Key should not end with .md") + } + + self.content + .get(key) + .map(|content| content.lines().count() as u32) + .unwrap_or(0) + } } impl Database { diff --git a/crates/liwe/src/fs.rs b/crates/liwe/src/fs.rs index 8a13021..0081b88 100644 --- a/crates/liwe/src/fs.rs +++ b/crates/liwe/src/fs.rs @@ -21,6 +21,7 @@ pub fn new_for_path(path: &PathBuf) -> State { .unwrap() .into_iter() .map(|entry| entry.unwrap().path()) + .filter(|path| path.extension().map_or(false, |ex| ex.eq("md"))) .collect::>() .par_iter() .flat_map(|path| read_file(path)) diff --git a/crates/liwe/src/key.rs b/crates/liwe/src/key.rs index a1bee37..9de3183 100644 --- a/crates/liwe/src/key.rs +++ b/crates/liwe/src/key.rs @@ -1,4 +1,4 @@ -use crate::model::{self, Key}; +use crate::model::Key; pub fn without_extension(key: &str) -> String { if !key.ends_with(".md") { @@ -7,7 +7,7 @@ pub fn without_extension(key: &str) -> String { key.trim_end_matches(".md").to_string() } -pub fn with_extension(link: &str) -> model::Key { +pub fn with_extension(link: &str) -> Key { if link.ends_with(".md") { return link.to_string(); } diff --git a/crates/liwe/src/markdown/reader.rs b/crates/liwe/src/markdown/reader.rs index 389a822..4640696 100644 --- a/crates/liwe/src/markdown/reader.rs +++ b/crates/liwe/src/markdown/reader.rs @@ -1,7 +1,6 @@ use std::iter::once; use std::ops::Range; -use itertools::Itertools; use pulldown_cmark::{CodeBlockKind, Options, Tag, TagEnd}; use pulldown_cmark::{Event::*, Parser}; @@ -63,7 +62,7 @@ impl MarkdownEventsReader { code_block.text = format!("{}{}", code_block.text, text.to_string()) } DocumentBlock::RawBlock(block) => block.text = text.to_string(), - default => { + _ => { self.push_inline( DocumentInline::Str(text.to_string()), self.to_line_range(range), @@ -106,7 +105,7 @@ impl MarkdownEventsReader { ); self.pop_inline(); } - FootnoteReference(cow_str) => {} + FootnoteReference(_) => {} SoftBreak => {} HardBreak => {} Rule => { @@ -164,22 +163,15 @@ impl MarkdownEventsReader { inlines: vec![], })); } - Tag::Heading { - level, - id, - classes, - attrs, - } => self.push_block(DocumentBlock::Header(Header { + Tag::Heading { level, .. } => self.push_block(DocumentBlock::Header(Header { line_range: self.to_line_range(range), level: level as u8, inlines: vec![], })), - Tag::BlockQuote(block_quote_kind) => { - self.push_block(DocumentBlock::BlockQuote(BlockQuote { - line_range: self.to_line_range(range), - blocks: Vec::new(), - })) - } + Tag::BlockQuote(_) => self.push_block(DocumentBlock::BlockQuote(BlockQuote { + line_range: self.to_line_range(range), + blocks: Vec::new(), + })), Tag::CodeBlock(code_block_kind) => { self.push_block(DocumentBlock::CodeBlock(CodeBlock { line_range: self.to_line_range(range), @@ -203,11 +195,11 @@ impl MarkdownEventsReader { Tag::Item => { self.top_block().append_item(); } - Tag::FootnoteDefinition(str) => {} + Tag::FootnoteDefinition(_) => {} Tag::DefinitionList => {} Tag::DefinitionListTitle => {} Tag::DefinitionListDefinition => {} - Tag::Table(vec) => {} + Tag::Table(_) => {} Tag::TableHead => {} Tag::TableRow => {} Tag::TableCell => {} @@ -239,10 +231,7 @@ impl MarkdownEventsReader { ); } Tag::Link { - link_type, - dest_url, - title, - id, + dest_url, title, .. } => { self.push_inline( DocumentInline::Link(Link { @@ -258,10 +247,7 @@ impl MarkdownEventsReader { ); } Tag::Image { - link_type, - dest_url, - title, - id, + dest_url, title, .. } => { self.push_inline( DocumentInline::Image(Image { @@ -276,17 +262,17 @@ impl MarkdownEventsReader { self.to_line_range(range), ); } - Tag::MetadataBlock(metadata_block_kind) => self.metadata_block = true, + Tag::MetadataBlock(_) => self.metadata_block = true, } } - fn end_tag(&mut self, tag: TagEnd, range: Range) { + fn end_tag(&mut self, tag: TagEnd, _: Range) { match tag { TagEnd::Paragraph => { self.pop_block(); } - TagEnd::Heading(heading_level) => self.pop_block(), - TagEnd::BlockQuote(block_quote_kind) => self.pop_block(), + TagEnd::Heading(_) => self.pop_block(), + TagEnd::BlockQuote(_) => self.pop_block(), TagEnd::CodeBlock => { self.pop_block(); } @@ -304,7 +290,7 @@ impl MarkdownEventsReader { TagEnd::DefinitionListTitle => {} TagEnd::FootnoteDefinition => {} TagEnd::Image => self.pop_inline(), - TagEnd::MetadataBlock(metadata_block_kind) => self.metadata_block = false, + TagEnd::MetadataBlock(_) => self.metadata_block = false, TagEnd::Table => {} TagEnd::TableCell => {} TagEnd::TableHead => {} @@ -377,7 +363,6 @@ fn line_starts(content: &str) -> Vec { mod tests { use indoc::indoc; - use crate::graph::graph_node::Document; use crate::markdown::reader::{line_starts, MarkdownEventsReader}; use crate::model::{document::*, InlineRange, Position}; diff --git a/crates/liwe/src/model/document.rs b/crates/liwe/src/model/document.rs index 1148562..b5a484e 100644 --- a/crates/liwe/src/model/document.rs +++ b/crates/liwe/src/model/document.rs @@ -1,11 +1,8 @@ -use std::default; - use crate::key::without_extension; use crate::model; use crate::model::graph::Inline; use crate::model::{Key, Lang, LineRange}; -use super::graph::to_node_inlines; use super::{InlineRange, Position}; pub struct Document { @@ -301,13 +298,6 @@ pub struct HorizontalRule { } impl DocumentInline { - fn is_ref_inline(&self) -> bool { - match self { - DocumentInline::Link(link) => model::is_ref_url(&link.target.url), - _ => false, - } - } - pub fn apppen(&mut self, inline: DocumentInline) { match self { DocumentInline::Emph(emph) => emph.inlines.push(inline), diff --git a/crates/liwe/src/model/graph.rs b/crates/liwe/src/model/graph.rs index 3e6e7ba..b221b07 100644 --- a/crates/liwe/src/model/graph.rs +++ b/crates/liwe/src/model/graph.rs @@ -243,14 +243,8 @@ pub struct Settings { pub library: LibraryOptions, } +#[allow(dead_code)] impl Block { - fn is_ref(&self) -> bool { - match self { - Block::Para(inlines) => inlines.len() == 1 && inlines[0].is_ref(), - _ => false, - } - } - fn is_sparce_list(&self) -> bool { match self { Block::BulletList(items) => items @@ -371,10 +365,10 @@ impl Inline { format!("[{}]({})", text, url) } } - Inline::Image(url, title, inlines) => { + Inline::Image(url, _, inlines) => { format!("![{}]({})", inlines_to_markdown(inlines, options), url) } - Inline::RawInline(lang, content) => format!("`{}`", content), + Inline::RawInline(_, content) => format!("`{}`", content), Inline::Math(math) => format!("${}$", math), } } diff --git a/crates/liwe/src/parser.rs b/crates/liwe/src/parser.rs index a0f877d..59e872e 100644 --- a/crates/liwe/src/parser.rs +++ b/crates/liwe/src/parser.rs @@ -5,7 +5,6 @@ use crate::{ Key, Position, }, }; -use indoc::indoc; pub struct Parser { document: Document, } @@ -30,7 +29,7 @@ impl Parser { #[test] pub fn link_in_paragraph() { let parser = Parser::new( - indoc! {" + indoc::indoc! {" # test test [test](link1) test diff --git a/crates/liwe/src/state.rs b/crates/liwe/src/state.rs index 9162cf2..e65fb69 100644 --- a/crates/liwe/src/state.rs +++ b/crates/liwe/src/state.rs @@ -1,4 +1,3 @@ -use indoc::indoc; use itertools::Itertools; use crate::{key::with_extension, model::State}; @@ -47,7 +46,7 @@ pub fn new_form_indoc(indoc: &str) -> State { #[test] fn test_store_new_form_indoc() { - let store = new_form_indoc(indoc! {" + let store = new_form_indoc(indoc::indoc! {" a _ b