Skip to content

Commit 29669bd

Browse files
authored
[209_7] 修复bash代码模式下的错误高亮 (#2672)
Co-authored-by: notfoundzzz <[email protected]>
1 parent 576518d commit 29669bd

File tree

5 files changed

+141
-3
lines changed

5 files changed

+141
-3
lines changed

TeXmacs/plugins/bash/progs/code/bash-lang.scm

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@
139139
"##" "#" "%%" "%" ;; ${var##pat} ${var%pat} ...
140140
)))
141141

142+
;; Paths / urls
143+
(tm-define (parser-feature lan key)
144+
(:require (and (== lan "bash") (== key "path")))
145+
`(,(string->symbol key)
146+
(enable)))
147+
142148
;; Numbers
143149
(tm-define (parser-feature lan key)
144150
(:require (and (== lan "bash") (== key "number")))
@@ -163,7 +169,8 @@
163169
(tm-define (parser-feature lan key)
164170
(:require (and (== lan "bash") (== key "comment")))
165171
`(,(string->symbol key)
166-
(inline "#")))
172+
(inline "#")
173+
(inline_require_space)))
167174

168175
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
169176
;; Preferences for syntax highlighting

TeXmacs/tests/tmu/209_7.tmu

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<TMU|<tuple|1.1.0|2026.1.1>>
1+
<TMU|<tuple|1.1.0|2026.1.2>>
22

33
<style|<tuple|generic|chinese|table-captions-above|number-europe|preview-ref|bash>>
44

@@ -24,6 +24,38 @@
2424

2525
IFS=$'\\n\\t'
2626

27+
# ---------- path -------------
28+
29+
\;
30+
31+
tar xzvf nvim-linux-x86_64.tar.gz
32+
33+
sudo mv nvim-linux-x86_64 /opt/nvim
34+
35+
git clone [email protected]:XmacsLabs/mogan.git
36+
37+
cat chapter-3.1.tmu
38+
39+
3.2 4.5
40+
41+
\;
42+
43+
# ----------- commment ---------
44+
45+
echo $# # 行尾注释
46+
47+
\;
48+
49+
echo ${#PATH}#not_comment
50+
51+
echo "${#PATH}#still_not_comment"
52+
53+
\;
54+
55+
echo ${#PATH} # 这里才是注释
56+
57+
\;
58+
2759
\;
2860

2961
# ---------- globals ----------

devel/209_7.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,13 @@
3333

3434
关联 issue #2607
3535

36+
## 2026/01/29
37+
### What
38+
- 修复 Bash 代码模式下 `#``$#``${#...}` 中被误识别为注释的问题
39+
- 增加路径/URL 识别规则,避免路径/文件名中的关键字与数字误高亮(如 `abc.git`
40+
41+
### How
42+
-`prog_language.cpp` 增加可配置的 `path` 解析步骤,位于 `string_parser` 之后、`keyword/number` 之前;匹配到路径/URL token 则整体消费
43+
- `bash-lang.scm` 中启用 `path` 解析
44+
- 注释规则增加 `inline_require_space`:仅当 `#` 位于行首或空白后才作为注释起始
45+

src/System/Language/impl_language.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ struct prog_language_rep : abstract_language_rep {
9090
void customize_string (tree config);
9191
void customize_preprocessor (tree config);
9292
void customize_comment (tree config);
93+
void customize_path (tree config);
9394
tree get_parser_config (string lan, string key);
95+
96+
bool inline_comment_requires_space;
97+
bool path_parser_enabled;
9498
};
9599

96100
struct scheme_language_rep : language_rep {

src/System/Language/prog_language.cpp

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ prog_language_rep::prog_language_rep (string name)
2525
: abstract_language_rep (name) {
2626
if (DEBUG_PARSER)
2727
debug_packrat << "Building the " * name * " language parser" << LF;
28+
inline_comment_requires_space= false;
29+
path_parser_enabled = false;
2830

2931
string use_modules= "(use-modules (code " * name * "-lang))";
3032
eval (use_modules);
@@ -49,6 +51,9 @@ prog_language_rep::prog_language_rep (string name)
4951

5052
tree preprocessor_config= get_parser_config (name, "preprocessor");
5153
customize_preprocessor (preprocessor_config);
54+
55+
tree path_config= get_parser_config (name, "path");
56+
customize_path (path_config);
5257
}
5358

5459
tree
@@ -207,6 +212,9 @@ prog_language_rep::customize_comment (tree config) {
207212
}
208213
inline_comment_parser.set_starts (inline_comment_starts);
209214
}
215+
else if (label == "inline_require_space") {
216+
inline_comment_requires_space= true;
217+
}
210218
}
211219
}
212220

@@ -227,6 +235,78 @@ prog_language_rep::customize_preprocessor (tree config) {
227235
if (DEBUG_PARSER) debug_packrat << preprocessor_parser.to_string ();
228236
}
229237

238+
void
239+
prog_language_rep::customize_path (tree config) {
240+
for (int i= 0; i < N (config); i++) {
241+
tree feature= config[i];
242+
string label = get_label (feature);
243+
if (label == "enable") {
244+
path_parser_enabled= true;
245+
}
246+
}
247+
}
248+
249+
static bool
250+
is_path_token_delim (char c) {
251+
return is_space (c) || c == '(' || c == ')' || c == '{' || c == '}' ||
252+
c == '[' || c == ']' || c == ';' || c == '|' || c == '&' || c == '<' ||
253+
c == '>';
254+
}
255+
256+
static bool
257+
looks_like_path_token (string token) {
258+
if (is_empty (token)) return false;
259+
if (token == "." || token == "..") return false;
260+
261+
url parsed= url_path (token);
262+
if (is_rooted (parsed) || is_rooted_web (parsed) || is_concat (parsed))
263+
return true;
264+
265+
bool has_dot = false;
266+
bool has_alpha= false;
267+
bool has_digit= false;
268+
bool has_at = false;
269+
bool has_colon= false;
270+
bool has_dash = false;
271+
for (int i= 0; i < N (token); i++) {
272+
char c= token[i];
273+
if (c == '/' || c == '\\') return true;
274+
if (c == '.') has_dot= true;
275+
if (is_alpha (c)) has_alpha= true;
276+
if (is_digit (c)) has_digit= true;
277+
if (c == '-') has_dash= true;
278+
if (c == '@') has_at= true;
279+
if (c == ':') has_colon= true;
280+
if (c == ':' && i + 2 < N (token) && token[i + 1] == '/' &&
281+
token[i + 2] == '/')
282+
return true;
283+
}
284+
285+
if (N (token) >= 2 && token[0] == '.' && token[1] == '/') return true;
286+
if (N (token) >= 3 && token[0] == '.' && token[1] == '.' && token[2] == '/')
287+
return true;
288+
if (N (token) >= 2 && token[0] == '~' && token[1] == '/') return true;
289+
if (has_at && has_colon) return true;
290+
if (has_dot && has_alpha) return true;
291+
if (token[0] != '-' && has_dash && has_alpha && has_digit) return true;
292+
return false;
293+
}
294+
295+
static bool
296+
parse_path_token (string s, int& pos) {
297+
if (pos >= N (s)) return false;
298+
if (is_path_token_delim (s[pos])) return false;
299+
300+
int start= pos;
301+
int end = pos;
302+
while (end < N (s) && !is_path_token_delim (s[end]))
303+
end++;
304+
string token= s (start, end);
305+
if (!looks_like_path_token (token)) return false;
306+
pos= end;
307+
return true;
308+
}
309+
230310
text_property
231311
prog_language_rep::advance (tree t, int& pos) {
232312
string s= t->label;
@@ -255,6 +335,10 @@ prog_language_rep::advance (tree t, int& pos) {
255335
current_parser= string_parser.get_parser_name ();
256336
return &tp_normal_rep;
257337
}
338+
if (path_parser_enabled && parse_path_token (s, pos)) {
339+
current_parser= "path_parser";
340+
return &tp_normal_rep;
341+
}
258342
if (keyword_parser.parse (s, pos)) {
259343
current_parser= keyword_parser.get_parser_name ();
260344
return &tp_normal_rep;
@@ -313,7 +397,8 @@ prog_language_rep::get_color (tree t, int start, int end) {
313397
int pos= 0;
314398
while (pos <= start) {
315399
if (inline_comment_parser.can_parse (s, pos)) {
316-
return decode_color (lan_name, encode_color ("comment"));
400+
if (!inline_comment_requires_space || (pos == 0 || is_space (s[pos - 1])))
401+
return decode_color (lan_name, encode_color ("comment"));
317402
}
318403
pos++;
319404
}

0 commit comments

Comments
 (0)