From cb1fe7cb77c9d53f1f44122af92c6b2fe3705c1f Mon Sep 17 00:00:00 2001 From: Paul Eichler Date: Fri, 27 Feb 2026 12:38:42 +0100 Subject: [PATCH] feature: add support for configuring quote symbols This commit adds support for customizing the quote symbols per language. It achieves this by adding a new field 'quote_symbols' to the 'Syntax' type. Unfortunately, the addition of this field will break backwards compatibility. --- src/highlighting.rs | 5 +++-- src/syntax/asm.rs | 3 +++ src/syntax/lua.rs | 3 +++ src/syntax/mod.rs | 14 ++++++++++++-- src/syntax/python.rs | 3 +++ src/syntax/rust.rs | 3 +++ src/syntax/shell.rs | 3 +++ src/syntax/sql.rs | 3 +++ 8 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/highlighting.rs b/src/highlighting.rs index 79b21e7..51106a4 100644 --- a/src/highlighting.rs +++ b/src/highlighting.rs @@ -1,7 +1,7 @@ #[cfg(feature = "editor")] use super::Editor; -use super::syntax::{Syntax, TokenType, QUOTES, SEPARATORS}; +use super::syntax::{SEPARATORS, Syntax, TokenType}; use std::mem; #[derive(Default, Debug, PartialEq, PartialOrd, Eq, Ord)] @@ -39,6 +39,7 @@ impl Token { c if syntax.is_special(c.to_string().as_str()) => TokenType::Special, c if syntax.comment == c.to_string().as_str() => TokenType::Comment(false), c if syntax.comment_multiline[0] == c.to_string().as_str() => TokenType::Comment(true), + c if syntax.is_quote_symbol(&c) => TokenType::Str(c), _ => TokenType::from(c), }; token @@ -136,7 +137,7 @@ impl Token { c if !c.is_alphanumeric() && !SEPARATORS.contains(&c) => { tokens.extend(self.drain(self.ty)); self.buffer.push(c); - self.ty = if QUOTES.contains(&c) { + self.ty = if syntax.is_quote_symbol(&c) { Ty::Str(c) } else { Ty::Punctuation(c) diff --git a/src/syntax/asm.rs b/src/syntax/asm.rs index f772886..4e85b2c 100644 --- a/src/syntax/asm.rs +++ b/src/syntax/asm.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -1177,6 +1179,7 @@ impl Syntax { "ZMM10", "ZMM11", "ZMM12", "ZMM13", "ZMM14", "ZMM15", // ZMM ]), + quote_symbols: &DEFAULT_QUOTES, } } } diff --git a/src/syntax/lua.rs b/src/syntax/lua.rs index 8899024..5976290 100644 --- a/src/syntax/lua.rs +++ b/src/syntax/lua.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -17,6 +19,7 @@ impl Syntax { "boolean", "number", "string", "function", "userdata", "thread", "table", ]), special: BTreeSet::from(["false", "nil", "true"]), + quote_symbols: &DEFAULT_QUOTES, } } } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 88ac5cc..4a59eef 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -10,7 +10,7 @@ use std::collections::BTreeSet; use std::hash::{Hash, Hasher}; pub const SEPARATORS: [char; 1] = ['_']; -pub const QUOTES: [char; 3] = ['\'', '"', '`']; +pub const DEFAULT_QUOTES: [char; 3] = ['\'', '"', '`']; type MultiLine = bool; type Float = bool; @@ -83,7 +83,6 @@ impl From for TokenType { fn from(c: char) -> Self { match c { c if c.is_whitespace() => TokenType::Whitespace(c), - c if QUOTES.contains(&c) => TokenType::Str(c), c if c.is_numeric() => TokenType::Numeric(false), c if c.is_alphabetic() || SEPARATORS.contains(&c) => TokenType::Literal, c if c.is_ascii_punctuation() => TokenType::Punctuation(c), @@ -103,6 +102,7 @@ pub struct Syntax { pub keywords: BTreeSet<&'static str>, pub types: BTreeSet<&'static str>, pub special: BTreeSet<&'static str>, + pub quote_symbols: &'static [char], } impl Default for Syntax { fn default() -> Self { @@ -160,6 +160,12 @@ impl Syntax { ..self } } + pub fn with_quote_symbols>(self, quote_symbols: T) -> Self { + Syntax { + quote_symbols: quote_symbols.into(), + ..self + } + } pub fn language(&self) -> &str { self.language @@ -191,6 +197,9 @@ impl Syntax { self.special.contains(word.to_ascii_uppercase().as_str()) } } + pub fn is_quote_symbol(&self, c: &char) -> bool { + self.quote_symbols.contains(c) + } } impl Syntax { @@ -204,6 +213,7 @@ impl Syntax { keywords: BTreeSet::new(), types: BTreeSet::new(), special: BTreeSet::new(), + quote_symbols: &[], } } } diff --git a/src/syntax/python.rs b/src/syntax/python.rs index 8ce0492..71552e8 100644 --- a/src/syntax/python.rs +++ b/src/syntax/python.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -32,6 +34,7 @@ impl Syntax { "frozenset", ]), special: BTreeSet::from(["False", "None", "True"]), + quote_symbols: &DEFAULT_QUOTES, } } } diff --git a/src/syntax/rust.rs b/src/syntax/rust.rs index 6d7278c..4e80177 100644 --- a/src/syntax/rust.rs +++ b/src/syntax/rust.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -83,6 +85,7 @@ impl Syntax { "Weak", ]), special: BTreeSet::from(["Self", "static", "true", "false"]), + quote_symbols: &DEFAULT_QUOTES, } } } diff --git a/src/syntax/shell.rs b/src/syntax/shell.rs index 154c859..7ee7ec0 100644 --- a/src/syntax/shell.rs +++ b/src/syntax/shell.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -36,6 +38,7 @@ impl Syntax { "alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs", "kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait", ]), + quote_symbols: &DEFAULT_QUOTES, } } } diff --git a/src/syntax/sql.rs b/src/syntax/sql.rs index 2b5b5d9..fe7b274 100644 --- a/src/syntax/sql.rs +++ b/src/syntax/sql.rs @@ -1,3 +1,5 @@ +use crate::syntax::DEFAULT_QUOTES; + use super::Syntax; use std::collections::BTreeSet; @@ -133,6 +135,7 @@ impl Syntax { "DATABASE", ]), special: BTreeSet::from(["PUBLIC"]), + quote_symbols: &DEFAULT_QUOTES, } } }