summaryrefslogtreecommitdiff
path: root/support/texlab/src/formatting/bibtex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/formatting/bibtex.rs')
-rw-r--r--support/texlab/src/formatting/bibtex.rs376
1 files changed, 0 insertions, 376 deletions
diff --git a/support/texlab/src/formatting/bibtex.rs b/support/texlab/src/formatting/bibtex.rs
deleted file mode 100644
index aba3299468..0000000000
--- a/support/texlab/src/formatting/bibtex.rs
+++ /dev/null
@@ -1,376 +0,0 @@
-use crate::syntax::*;
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct BibtexFormattingOptions {
- pub line_length: Option<i32>,
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct BibtexFormattingParams {
- pub tab_size: usize,
- pub insert_spaces: bool,
- pub options: BibtexFormattingOptions,
-}
-
-impl BibtexFormattingParams {
- pub fn line_length(&self) -> i32 {
- let line_length = self.options.line_length.unwrap_or(120);
- if line_length <= 0 {
- std::i32::MAX
- } else {
- line_length
- }
- }
-}
-
-impl Default for BibtexFormattingParams {
- fn default() -> Self {
- BibtexFormattingParams {
- tab_size: 4,
- insert_spaces: true,
- options: BibtexFormattingOptions::default(),
- }
- }
-}
-
-struct BibtexFormatter<'a> {
- params: &'a BibtexFormattingParams,
- indent: String,
- output: String,
-}
-
-impl<'a> BibtexFormatter<'a> {
- fn new(params: &'a BibtexFormattingParams) -> Self {
- let indent = if params.insert_spaces {
- let mut buffer = String::new();
- for _ in 0..params.tab_size {
- buffer.push(' ');
- }
- buffer
- } else {
- "\t".into()
- };
-
- Self {
- params,
- indent,
- output: String::new(),
- }
- }
-
- fn format_comment(&mut self, comment: &BibtexComment) {
- self.output.push_str(comment.token.text());
- }
-
- fn format_preamble(&mut self, preamble: &BibtexPreamble) {
- self.format_token(&preamble.ty);
- self.output.push('{');
- if let Some(ref content) = preamble.content {
- self.format_content(content, self.output.chars().count());
- self.output.push('}');
- }
- }
-
- fn format_string(&mut self, string: &BibtexString) {
- self.format_token(&string.ty);
- self.output.push('{');
- if let Some(ref name) = string.name {
- self.output.push_str(name.text());
- self.output.push_str(" = ");
- if let Some(ref value) = string.value {
- self.format_content(value, self.output.chars().count());
- self.output.push('}');
- }
- }
- }
-
- fn format_entry(&mut self, entry: &BibtexEntry) {
- self.format_token(&entry.ty);
- self.output.push('{');
- if let Some(ref key) = entry.key {
- self.output.push_str(key.text());
- self.output.push(',');
- self.output.push('\n');
- for field in &entry.fields {
- self.format_field(field);
- }
- self.output.push('}');
- }
- }
-
- fn format_field(&mut self, field: &BibtexField) {
- self.output.push_str(self.indent.as_ref());
- self.format_token(&field.name);
- self.output.push_str(" = ");
- let count = field.name.text().chars().count();
- let align = self.params.tab_size as usize + count + 3;
- if let Some(ref content) = field.content {
- self.format_content(content, align);
- self.output.push(',');
- self.output.push('\n');
- }
- }
-
- fn format_content(&mut self, content: &BibtexContent, align: usize) {
- let mut analyzer = BibtexContentAnalyzer::new();
- content.accept(&mut analyzer);
- let tokens = analyzer.tokens;
- self.output.push_str(tokens[0].text());
-
- let mut length = align + tokens[0].text().chars().count();
- for i in 1..tokens.len() {
- let previous = tokens[i - 1];
- let current = tokens[i];
- let current_length = current.text().chars().count();
-
- let insert_space = Self::should_insert_space(previous, current);
- let space_length = if insert_space { 1 } else { 0 };
-
- if length + current_length + space_length > self.params.line_length() as usize {
- self.output.push('\n');
- self.output.push_str(self.indent.as_ref());
- for _ in 0..=align - self.params.tab_size {
- self.output.push(' ');
- }
- length = align;
- } else if insert_space {
- self.output.push(' ');
- length += 1;
- }
- self.output.push_str(current.text());
- length += current_length;
- }
- }
-
- fn format_token(&mut self, token: &BibtexToken) {
- self.output.push_str(token.text().to_lowercase().as_ref());
- }
-
- fn should_insert_space(previous: &BibtexToken, current: &BibtexToken) -> bool {
- previous.start().line != current.start().line
- || previous.end().character < current.start().character
- }
-}
-
-struct BibtexContentAnalyzer<'a> {
- pub tokens: Vec<&'a BibtexToken>,
-}
-
-impl<'a> BibtexContentAnalyzer<'a> {
- pub fn new() -> Self {
- BibtexContentAnalyzer { tokens: Vec::new() }
- }
-}
-
-impl<'a> BibtexVisitor<'a> for BibtexContentAnalyzer<'a> {
- fn visit_root(&mut self, _root: &'a BibtexRoot) {}
-
- fn visit_comment(&mut self, _comment: &'a BibtexComment) {}
-
- fn visit_preamble(&mut self, _preamble: &'a BibtexPreamble) {}
-
- fn visit_string(&mut self, _string: &'a BibtexString) {}
-
- fn visit_entry(&mut self, _entry: &'a BibtexEntry) {}
-
- fn visit_field(&mut self, _field: &'a BibtexField) {}
-
- fn visit_word(&mut self, word: &'a BibtexWord) {
- self.tokens.push(&word.token);
- }
-
- fn visit_command(&mut self, command: &'a BibtexCommand) {
- self.tokens.push(&command.token);
- }
-
- fn visit_quoted_content(&mut self, content: &'a BibtexQuotedContent) {
- self.tokens.push(&content.left);
- BibtexWalker::walk_quoted_content(self, content);
- if let Some(ref right) = content.right {
- self.tokens.push(right);
- }
- }
-
- fn visit_braced_content(&mut self, content: &'a BibtexBracedContent) {
- self.tokens.push(&content.left);
- BibtexWalker::walk_braced_content(self, content);
- if let Some(ref right) = content.right {
- self.tokens.push(right);
- }
- }
-
- fn visit_concat(&mut self, concat: &'a BibtexConcat) {
- concat.left.accept(self);
- self.tokens.push(&concat.operator);
- if let Some(ref right) = concat.right {
- right.accept(self);
- }
- }
-}
-
-pub fn format_declaration(
- declaration: &BibtexDeclaration,
- params: &BibtexFormattingParams,
-) -> String {
- match declaration {
- BibtexDeclaration::Comment(comment) => format_comment(comment, params),
- BibtexDeclaration::Preamble(preamble) => format_preamble(preamble, params),
- BibtexDeclaration::String(string) => format_string(string, params),
- BibtexDeclaration::Entry(entry) => format_entry(entry, params),
- }
-}
-
-pub fn format_comment(comment: &BibtexComment, params: &BibtexFormattingParams) -> String {
- let mut formatter = BibtexFormatter::new(params);
- formatter.format_comment(&comment);
- formatter.output
-}
-
-pub fn format_preamble(preamble: &BibtexPreamble, params: &BibtexFormattingParams) -> String {
- let mut formatter = BibtexFormatter::new(params);
- formatter.format_preamble(&preamble);
- formatter.output
-}
-
-pub fn format_string(string: &BibtexString, params: &BibtexFormattingParams) -> String {
- let mut formatter = BibtexFormatter::new(params);
- formatter.format_string(&string);
- formatter.output
-}
-
-pub fn format_entry(entry: &BibtexEntry, params: &BibtexFormattingParams) -> String {
- let mut formatter = BibtexFormatter::new(params);
- formatter.format_entry(&entry);
- formatter.output
-}
-
-pub fn format_content(content: &BibtexContent, params: &BibtexFormattingParams) -> String {
- let mut formatter = BibtexFormatter::new(params);
- formatter.format_content(content, 0);
- formatter.output
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use indoc::indoc;
-
- fn verify(source: &str, expected: &str, line_length: i32) {
- let tree = BibtexSyntaxTree::from(source);
- let params = BibtexFormattingParams {
- tab_size: 4,
- insert_spaces: true,
- options: BibtexFormattingOptions {
- line_length: Some(line_length),
- },
- };
- assert_eq!(
- expected,
- format_declaration(&tree.root.children[0], &params)
- );
- }
-
- #[test]
- fn test_wrap_long_lines() {
- let source =
- "@article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}";
- let expected = indoc!(
- "
- @article{foo,
- bar = {Lorem ipsum dolor
- sit amet,
- consectetur
- adipiscing elit.},
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_line_length_zero() {
- let source =
- "@article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}";
- let expected = indoc!(
- "
- @article{foo,
- bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit.},
- }"
- );
- verify(source, expected, 0);
- }
-
- #[test]
- fn test_trailing_commas() {
- let source = "@article{foo, bar = baz}";
- let expected = indoc!(
- "
- @article{foo,
- bar = baz,
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_insert_braces() {
- let source = "@article{foo, bar = baz,";
- let expected = indoc!(
- "
- @article{foo,
- bar = baz,
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_commands() {
- let source = "@article{foo, bar = \"\\baz\",}";
- let expected = indoc!(
- "@article{foo,
- bar = \"\\baz\",
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_concatenation() {
- let source = "@article{foo, bar = \"baz\" # \"qux\"}";
- let expected = indoc!(
- "
- @article{foo,
- bar = \"baz\" # \"qux\",
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_parentheses() {
- let source = "@article(foo,)";
- let expected = indoc!(
- "
- @article{foo,
- }"
- );
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_string() {
- let source = "@string{foo=\"bar\"}";
- let expected = "@string{foo = \"bar\"}";
- verify(source, expected, 30);
- }
-
- #[test]
- fn test_preamble() {
- let source = "@preamble{\n\"foo bar baz\"}";
- let expected = "@preamble{\"foo bar baz\"}";
- verify(source, expected, 30);
- }
-}