refactor: share language IDs with indentation configuration
This commit is contained in:
@@ -3,9 +3,6 @@
|
||||
- whitespace kind -> character map should be configurable.
|
||||
- [x] add option to insert spaces instead tab character when pressing tab:
|
||||
- number of spaces should be configurable (per language)
|
||||
- [ ] diff view - design question:
|
||||
- is it possible to angle the hatchings for empty lines more?
|
||||
- if a character like the current one exists with a 45degree angle instead (and a top and bottom), we could use that across two columns. that would give us a perfectly 45 degree hatching.
|
||||
- [ ] github/gitlab/gitea integration (probably requries authentication with github)
|
||||
- github pr picker (floating window)
|
||||
- three tabs: open, closed, all
|
||||
|
||||
@@ -20,7 +20,7 @@ Vamp.configure do |config|
|
||||
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
||||
config.whitespace_scope = "all" # or "leading" for indentation only
|
||||
config.tab_spaces = nil # opt in with a fixed number of spaces per Tab, e.g. 4
|
||||
config.language_tab_spaces = {} # overrides: { "Ruby" => 2, "Makefile" => nil }
|
||||
config.language_tab_spaces = {} # overrides: { "ruby" => 2, "makefile" => nil }
|
||||
config.file_explorer_side = "right"
|
||||
config.file_explorer_view = "tree"
|
||||
config.file_picker_view = "tree"
|
||||
@@ -71,7 +71,7 @@ Markers appear in ordinary and historical buffers and both sides of split/unifie
|
||||
|
||||
`config.tab_spaces` defaults to `nil`, preserving literal tabs. Set an integer from `1` through `255` to insert that many spaces per Tab in Insert mode, at every caret. This is a fixed count, not alignment to the next tab stop; it does not change how existing tab characters are displayed.
|
||||
|
||||
`config.language_tab_spaces` defaults to `{}`. It overrides the global setting for the active buffer's detected syntax language, using the case-sensitive names shown in the language bar, for example `{ "Rust" => 4, "Ruby" => 2, "Python" => 4, "Makefile" => nil }`. A `nil` override preserves literal tabs for that language, even when the global setting uses spaces. Unlisted or unknown languages and unnamed buffers without a recognized shebang use `tab_spaces`. Detection reuses syntax highlighting's filename, extension, and shebang rules, independently of whether an LSP is enabled.
|
||||
`config.language_tab_spaces` defaults to `{}`. It overrides the global setting using the same case-sensitive language IDs as `config.lsp`, for example `{ "rust" => 4, "ruby" => 2, "python" => 4, "makefile" => nil }`. Syntax detection and built-in LSP presets share canonical IDs rather than maintaining separate naming conventions; other bundled IDs include `shellscript`, `cpp`, and `typescriptreact` for Bash, C++, and TSX. Display labels such as “Ruby” remain presentation-only. A `nil` override preserves literal tabs for that language, even when the global setting uses spaces. Unlisted or unknown languages and unnamed buffers without a recognized shebang use `tab_spaces`. Detection reuses syntax highlighting's filename, extension, and shebang rules, independently of whether an LSP is enabled.
|
||||
|
||||
Active snippets retain Tab/Shift+Tab argument navigation; after the final stop, Tab uses the configured insertion setting. Explicit Tab bindings still take precedence, and Ctrl+i remains a Tab alias. Bracketed paste, clipboard paste, completion payloads, and plugin text retain literal tab characters. Insert undo/redo and dot repeat preserve the resolved spaces or tab. Widths other than `nil` or integers in `1..255`, non-hash language overrides, and empty, non-string, or control-containing language keys reject the configuration.
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ Vamp.configure do |config|
|
||||
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
||||
config.whitespace_scope = "all" # or "leading" for indentation only; newline markers remain independent
|
||||
config.tab_spaces = nil # opt in: 4 inserts four spaces per Tab
|
||||
config.language_tab_spaces = {} # overrides: { "Ruby" => 2, "Makefile" => nil }
|
||||
config.language_tab_spaces = {} # overrides: { "ruby" => 2, "makefile" => nil }
|
||||
config.file_explorer_side = "right"
|
||||
config.file_explorer_view = "tree"
|
||||
config.file_picker_view = "tree"
|
||||
|
||||
+1
-1
@@ -8994,7 +8994,7 @@ impl Editor {
|
||||
let width = if self.language_tab_spaces.is_empty() {
|
||||
self.tab_spaces
|
||||
} else {
|
||||
crate::syntax::language_name(
|
||||
crate::syntax::language_id(
|
||||
self.active.path.as_deref(),
|
||||
self.active.lines.first().map(String::as_str),
|
||||
)
|
||||
|
||||
+3
-3
@@ -11,9 +11,9 @@ pub fn resolve(value: Value) -> Result<Vec<ServerConfig>, String> {
|
||||
return Err("LSP language keys must not be empty or contain control characters".into());
|
||||
}
|
||||
let preset: Option<(&[&[&str]], &str)> = match language_id.as_str() {
|
||||
"rust" => Some((&[&["rust-analyzer"]], "rs")),
|
||||
"python" => Some((&[&["ty", "server"], &["ruff", "server"]], "py")),
|
||||
"ruby" => Some((&[&["solargraph", "stdio"]], "rb")),
|
||||
crate::syntax::RUST_ID => Some((&[&["rust-analyzer"]], "rs")),
|
||||
crate::syntax::PYTHON_ID => Some((&[&["ty", "server"], &["ruff", "server"]], "py")),
|
||||
crate::syntax::RUBY_ID => Some((&[&["solargraph", "stdio"]], "rb")),
|
||||
_ => None,
|
||||
};
|
||||
let mut options = match value {
|
||||
|
||||
+5
-3
@@ -1006,7 +1006,7 @@ mod tests {
|
||||
r#"
|
||||
Vamp.configure do |c|
|
||||
c.tab_spaces = 4
|
||||
c.language_tab_spaces = { "Ruby" => 2, "Makefile" => nil, "JSON" => 1, "YAML" => 255 }
|
||||
c.language_tab_spaces = { "ruby" => 2, "makefile" => nil, "json" => 1, "yaml" => 255, "cpp" => 3, "typescriptreact" => 5 }
|
||||
end
|
||||
"#,
|
||||
);
|
||||
@@ -1021,6 +1021,8 @@ end
|
||||
("plain.txt", "", " "),
|
||||
("buffer.json", "", " "),
|
||||
("buffer.yaml", "", widest.as_str()),
|
||||
("buffer.cpp", "", " "),
|
||||
("buffer.tsx", "", " "),
|
||||
] {
|
||||
let source = format!("{prefix}αx\nβy");
|
||||
let path = fixture.file(name, &source);
|
||||
@@ -1066,7 +1068,7 @@ end
|
||||
for value in ["0", "-1", "256", "1.5", "true", r#""4""#, "[]", "{}"] {
|
||||
for assignment in [
|
||||
format!("c.tab_spaces = {value}"),
|
||||
format!(r#"c.language_tab_spaces = {{ "Ruby" => {value} }}"#),
|
||||
format!(r#"c.language_tab_spaces = {{ "ruby" => {value} }}"#),
|
||||
] {
|
||||
let config = fixture.file(
|
||||
"config.rb",
|
||||
@@ -1079,7 +1081,7 @@ end
|
||||
"nil",
|
||||
"[]",
|
||||
r#"{ "" => 2 }"#,
|
||||
r#"{ :Ruby => 2 }"#,
|
||||
r#"{ :ruby => 2 }"#,
|
||||
r#"{ "\n" => 2 }"#,
|
||||
] {
|
||||
let config = fixture.file(
|
||||
|
||||
+1
-1
@@ -262,7 +262,7 @@ module Vamp
|
||||
@tab_spaces = tab_spaces!(spaces)
|
||||
end
|
||||
|
||||
# @param languages [Hash{String => Integer, nil}] syntax language names to Tab widths
|
||||
# @param languages [Hash{String => Integer, nil}] LSP-style language IDs to Tab widths
|
||||
# @return [Hash{String => Integer, nil}]
|
||||
def language_tab_spaces=(languages)
|
||||
raise TypeError, "language_tab_spaces must be a Hash" unless languages.is_a?(Hash)
|
||||
|
||||
+7
-2
@@ -9,12 +9,16 @@ use tree_sitter::{
|
||||
mod languages;
|
||||
use languages::LanguageSpec;
|
||||
|
||||
pub(crate) const RUST_ID: &str = "rust";
|
||||
pub(crate) const RUBY_ID: &str = "ruby";
|
||||
pub(crate) const PYTHON_ID: &str = "python";
|
||||
|
||||
pub(crate) fn is_markdown_path(path: &Path) -> bool {
|
||||
languages::detect(Some(path), None).is_some_and(|syntax| syntax.name == "Markdown")
|
||||
}
|
||||
|
||||
pub(crate) fn language_name(path: Option<&Path>, first_line: Option<&str>) -> Option<&'static str> {
|
||||
languages::detect(path, first_line).map(|syntax| syntax.name)
|
||||
pub(crate) fn language_id(path: Option<&Path>, first_line: Option<&str>) -> Option<&'static str> {
|
||||
languages::detect(path, first_line).map(|syntax| syntax.id)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
@@ -2120,6 +2124,7 @@ mod tests {
|
||||
"((identifier) @function (#unsupported? @function))",
|
||||
]
|
||||
.map(|query| LanguageSpec {
|
||||
id: language.id,
|
||||
name: "invalid test grammar query",
|
||||
language: language.language.clone(),
|
||||
highlights: query,
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::path::Path;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub(super) struct LanguageSpec {
|
||||
pub id: &'static str,
|
||||
pub name: &'static str,
|
||||
pub language: tree_sitter::Language,
|
||||
pub highlights: &'static str,
|
||||
@@ -93,6 +94,7 @@ fn javascript_injections() -> &'static str {
|
||||
}
|
||||
|
||||
fn spec(
|
||||
id: &'static str,
|
||||
name: &'static str,
|
||||
language: tree_sitter::Language,
|
||||
highlights: &'static str,
|
||||
@@ -100,6 +102,7 @@ fn spec(
|
||||
locals: &'static str,
|
||||
) -> LanguageSpec {
|
||||
LanguageSpec {
|
||||
id,
|
||||
name,
|
||||
language,
|
||||
highlights,
|
||||
@@ -111,6 +114,7 @@ fn spec(
|
||||
static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
[
|
||||
spec(
|
||||
super::RUST_ID,
|
||||
"Rust",
|
||||
tree_sitter_rust::LANGUAGE.into(),
|
||||
tree_sitter_rust::HIGHLIGHTS_QUERY,
|
||||
@@ -118,6 +122,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
super::RUBY_ID,
|
||||
"Ruby",
|
||||
tree_sitter_ruby::LANGUAGE.into(),
|
||||
tree_sitter_ruby::HIGHLIGHTS_QUERY,
|
||||
@@ -125,6 +130,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
tree_sitter_ruby::LOCALS_QUERY,
|
||||
),
|
||||
spec(
|
||||
super::PYTHON_ID,
|
||||
"Python",
|
||||
tree_sitter_python::LANGUAGE.into(),
|
||||
tree_sitter_python::HIGHLIGHTS_QUERY,
|
||||
@@ -132,6 +138,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"json",
|
||||
"JSON",
|
||||
tree_sitter_json::LANGUAGE.into(),
|
||||
tree_sitter_json::HIGHLIGHTS_QUERY,
|
||||
@@ -139,6 +146,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"shellscript",
|
||||
"Bash",
|
||||
tree_sitter_bash::LANGUAGE.into(),
|
||||
tree_sitter_bash::HIGHLIGHT_QUERY,
|
||||
@@ -146,6 +154,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"makefile",
|
||||
"Makefile",
|
||||
tree_sitter_make::LANGUAGE.into(),
|
||||
tree_sitter_make::HIGHLIGHTS_QUERY,
|
||||
@@ -153,6 +162,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"markdown",
|
||||
"Markdown",
|
||||
tree_sitter_md::LANGUAGE.into(),
|
||||
MD_HIGHLIGHTS.as_str(),
|
||||
@@ -160,6 +170,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"javascript",
|
||||
"JavaScript",
|
||||
tree_sitter_javascript::LANGUAGE.into(),
|
||||
JS_HIGHLIGHTS.as_str(),
|
||||
@@ -167,6 +178,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
tree_sitter_javascript::LOCALS_QUERY,
|
||||
),
|
||||
spec(
|
||||
"typescript",
|
||||
"TypeScript",
|
||||
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
|
||||
TS_HIGHLIGHTS.as_str(),
|
||||
@@ -174,6 +186,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
TS_LOCALS.as_str(),
|
||||
),
|
||||
spec(
|
||||
"html",
|
||||
"HTML",
|
||||
tree_sitter_html::LANGUAGE.into(),
|
||||
tree_sitter_html::HIGHLIGHTS_QUERY,
|
||||
@@ -181,6 +194,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"css",
|
||||
"CSS",
|
||||
tree_sitter_css::LANGUAGE.into(),
|
||||
tree_sitter_css::HIGHLIGHTS_QUERY,
|
||||
@@ -188,6 +202,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"yaml",
|
||||
"YAML",
|
||||
tree_sitter_yaml::LANGUAGE.into(),
|
||||
tree_sitter_yaml::HIGHLIGHTS_QUERY,
|
||||
@@ -195,6 +210,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"toml",
|
||||
"TOML",
|
||||
tree_sitter_toml_ng::LANGUAGE.into(),
|
||||
tree_sitter_toml_ng::HIGHLIGHTS_QUERY,
|
||||
@@ -202,6 +218,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"c",
|
||||
"C",
|
||||
tree_sitter_c::LANGUAGE.into(),
|
||||
tree_sitter_c::HIGHLIGHT_QUERY,
|
||||
@@ -209,6 +226,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"cpp",
|
||||
"C++",
|
||||
tree_sitter_cpp::LANGUAGE.into(),
|
||||
CPP_HIGHLIGHTS.as_str(),
|
||||
@@ -216,6 +234,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"go",
|
||||
"Go",
|
||||
tree_sitter_go::LANGUAGE.into(),
|
||||
tree_sitter_go::HIGHLIGHTS_QUERY,
|
||||
@@ -223,6 +242,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
"",
|
||||
),
|
||||
spec(
|
||||
"typescriptreact",
|
||||
"TypeScript",
|
||||
tree_sitter_typescript::LANGUAGE_TSX.into(),
|
||||
TSX_HIGHLIGHTS.as_str(),
|
||||
@@ -230,6 +250,7 @@ static LANGUAGES: LazyLock<[LanguageSpec; 18]> = LazyLock::new(|| {
|
||||
TS_LOCALS.as_str(),
|
||||
),
|
||||
spec(
|
||||
"markdown",
|
||||
"Markdown inline",
|
||||
tree_sitter_md::INLINE_LANGUAGE.into(),
|
||||
tree_sitter_md::HIGHLIGHT_QUERY_INLINE,
|
||||
|
||||
Reference in New Issue
Block a user