fix: fix lsp adding two @
This commit is contained in:
parent
3b116782cc
commit
036d57176f
1 changed files with 46 additions and 25 deletions
|
|
@ -113,28 +113,6 @@ pub fn completions_for_line(
|
||||||
|
|
||||||
let after_at = &line_prefix[at_pos + 1..];
|
let after_at = &line_prefix[at_pos + 1..];
|
||||||
|
|
||||||
// Temporal snippet: `@` followed by a digit → offer date/time format snippets.
|
|
||||||
if after_at.starts_with(|c: char| c.is_ascii_digit()) {
|
|
||||||
return vec![
|
|
||||||
CompletionItem {
|
|
||||||
label: "YYYYMMDD".to_string(),
|
|
||||||
kind: Some(CompletionItemKind::SNIPPET),
|
|
||||||
detail: Some("Date marker (R16)".to_string()),
|
|
||||||
insert_text: Some("${1:YYYYMMDD}".to_string()),
|
|
||||||
insert_text_format: Some(InsertTextFormat::SNIPPET),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
CompletionItem {
|
|
||||||
label: "HHMMSS".to_string(),
|
|
||||||
kind: Some(CompletionItemKind::SNIPPET),
|
|
||||||
detail: Some("Time marker (R16)".to_string()),
|
|
||||||
insert_text: Some("${1:HHMMSS}".to_string()),
|
|
||||||
insert_text_format: Some(InsertTextFormat::SNIPPET),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Markers already on this line (for conditional suggestion logic).
|
// Markers already on this line (for conditional suggestion logic).
|
||||||
let existing: Vec<String> = extract_markers_from_line(line);
|
let existing: Vec<String> = extract_markers_from_line(line);
|
||||||
|
|
||||||
|
|
@ -166,6 +144,7 @@ pub fn completions_for_line(
|
||||||
label: format!("@{}", name),
|
label: format!("@{}", name),
|
||||||
kind: Some(CompletionItemKind::KEYWORD),
|
kind: Some(CompletionItemKind::KEYWORD),
|
||||||
detail: Some(marker.display_name.clone()),
|
detail: Some(marker.display_name.clone()),
|
||||||
|
insert_text: Some(name.clone()),
|
||||||
// Conditional completions sort before unconditional ones.
|
// Conditional completions sort before unconditional ones.
|
||||||
sort_text: Some(if is_conditional {
|
sort_text: Some(if is_conditional {
|
||||||
format!("0_{}", name)
|
format!("0_{}", name)
|
||||||
|
|
@ -177,6 +156,28 @@ pub fn completions_for_line(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// Offer date/time snippets when prefix is empty or starts with a digit.
|
||||||
|
if prefix.is_empty() || prefix.starts_with(|c: char| c.is_ascii_digit()) {
|
||||||
|
items.push(CompletionItem {
|
||||||
|
label: "@YYYYMMDD".to_string(),
|
||||||
|
kind: Some(CompletionItemKind::SNIPPET),
|
||||||
|
detail: Some("Date marker (R16)".to_string()),
|
||||||
|
insert_text: Some("${1:YYYYMMDD}".to_string()),
|
||||||
|
insert_text_format: Some(InsertTextFormat::SNIPPET),
|
||||||
|
sort_text: Some("2_date".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
items.push(CompletionItem {
|
||||||
|
label: "@HHMMSS".to_string(),
|
||||||
|
kind: Some(CompletionItemKind::SNIPPET),
|
||||||
|
detail: Some("Time marker (R16)".to_string()),
|
||||||
|
insert_text: Some("${1:HHMMSS}".to_string()),
|
||||||
|
insert_text_format: Some(InsertTextFormat::SNIPPET),
|
||||||
|
sort_text: Some("2_time".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
items.sort_by(|a, b| {
|
items.sort_by(|a, b| {
|
||||||
a.sort_text
|
a.sort_text
|
||||||
.as_deref()
|
.as_deref()
|
||||||
|
|
@ -1035,17 +1036,37 @@ mod tests {
|
||||||
.starts_with("0_"));
|
.starts_with("0_"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_completions_temporal_snippet_at_sign() {
|
||||||
|
let config = make_config();
|
||||||
|
// Timestamps suggested when prefix is empty (just @)
|
||||||
|
let items = completions_for_line("@", 1, &config);
|
||||||
|
let labels: Vec<&str> = items.iter().map(|i| i.label.as_str()).collect();
|
||||||
|
assert!(labels.contains(&"@YYYYMMDD"));
|
||||||
|
assert!(labels.contains(&"@HHMMSS"));
|
||||||
|
assert!(items
|
||||||
|
.iter()
|
||||||
|
.any(|i| i.kind == Some(CompletionItemKind::SNIPPET)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_completions_temporal_snippet_digit_after_at() {
|
fn test_completions_temporal_snippet_digit_after_at() {
|
||||||
let config = make_config();
|
let config = make_config();
|
||||||
let items = completions_for_line("@2", 2, &config);
|
let items = completions_for_line("@2", 2, &config);
|
||||||
assert!(!items.is_empty());
|
assert!(!items.is_empty());
|
||||||
let labels: Vec<&str> = items.iter().map(|i| i.label.as_str()).collect();
|
let labels: Vec<&str> = items.iter().map(|i| i.label.as_str()).collect();
|
||||||
assert!(labels.contains(&"YYYYMMDD"));
|
assert!(labels.contains(&"@YYYYMMDD"));
|
||||||
assert!(labels.contains(&"HHMMSS"));
|
assert!(labels.contains(&"@HHMMSS"));
|
||||||
// Temporal items use snippet format
|
|
||||||
assert!(items
|
assert!(items
|
||||||
.iter()
|
.iter()
|
||||||
.any(|i| i.kind == Some(CompletionItemKind::SNIPPET)));
|
.any(|i| i.kind == Some(CompletionItemKind::SNIPPET)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_completions_no_double_at() {
|
||||||
|
let config = make_config();
|
||||||
|
let items = completions_for_line("@Br", 3, &config);
|
||||||
|
let break_item = items.iter().find(|i| i.label == "@Break").unwrap();
|
||||||
|
assert_eq!(break_item.insert_text.as_deref(), Some("Break"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue