Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion TeXmacs/plugins/bash/progs/code/bash-lang.scm
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@
"##" "#" "%%" "%" ;; ${var##pat} ${var%pat} ...
)))

;; Paths / urls
(tm-define (parser-feature lan key)
(:require (and (== lan "bash") (== key "path")))
`(,(string->symbol key)
(enable)))

;; Numbers
(tm-define (parser-feature lan key)
(:require (and (== lan "bash") (== key "number")))
Expand All @@ -163,7 +169,8 @@
(tm-define (parser-feature lan key)
(:require (and (== lan "bash") (== key "comment")))
`(,(string->symbol key)
(inline "#")))
(inline "#")
(inline_require_space)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Preferences for syntax highlighting
Expand Down
34 changes: 33 additions & 1 deletion TeXmacs/tests/tmu/209_7.tmu
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<TMU|<tuple|1.1.0|2026.1.1>>
<TMU|<tuple|1.1.0|2026.1.2>>

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

Expand All @@ -24,6 +24,38 @@

IFS=$'\\n\\t'

# ---------- path -------------

\;

tar xzvf nvim-linux-x86_64.tar.gz

sudo mv nvim-linux-x86_64 /opt/nvim

git clone [email protected]:XmacsLabs/mogan.git

cat chapter-3.1.tmu

3.2 4.5

\;

# ----------- commment ---------

echo $# # 行尾注释

\;

echo ${#PATH}#not_comment

echo "${#PATH}#still_not_comment"

\;

echo ${#PATH} # 这里才是注释

\;

\;

# ---------- globals ----------
Expand Down
10 changes: 10 additions & 0 deletions devel/209_7.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@

关联 issue #2607

## 2026/01/29
### What
- 修复 Bash 代码模式下 `#``$#``${#...}` 中被误识别为注释的问题
- 增加路径/URL 识别规则,避免路径/文件名中的关键字与数字误高亮(如 `abc.git`

### How
-`prog_language.cpp` 增加可配置的 `path` 解析步骤,位于 `string_parser` 之后、`keyword/number` 之前;匹配到路径/URL token 则整体消费
- `bash-lang.scm` 中启用 `path` 解析
- 注释规则增加 `inline_require_space`:仅当 `#` 位于行首或空白后才作为注释起始

4 changes: 4 additions & 0 deletions src/System/Language/impl_language.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ struct prog_language_rep : abstract_language_rep {
void customize_string (tree config);
void customize_preprocessor (tree config);
void customize_comment (tree config);
void customize_path (tree config);
tree get_parser_config (string lan, string key);

bool inline_comment_requires_space;
bool path_parser_enabled;
};

struct scheme_language_rep : language_rep {
Expand Down
87 changes: 86 additions & 1 deletion src/System/Language/prog_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ prog_language_rep::prog_language_rep (string name)
: abstract_language_rep (name) {
if (DEBUG_PARSER)
debug_packrat << "Building the " * name * " language parser" << LF;
inline_comment_requires_space= false;
path_parser_enabled = false;

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

tree preprocessor_config= get_parser_config (name, "preprocessor");
customize_preprocessor (preprocessor_config);

tree path_config= get_parser_config (name, "path");
customize_path (path_config);
}

tree
Expand Down Expand Up @@ -207,6 +212,9 @@ prog_language_rep::customize_comment (tree config) {
}
inline_comment_parser.set_starts (inline_comment_starts);
}
else if (label == "inline_require_space") {
inline_comment_requires_space= true;
}
}
}

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

void
prog_language_rep::customize_path (tree config) {
for (int i= 0; i < N (config); i++) {
tree feature= config[i];
string label = get_label (feature);
if (label == "enable") {
path_parser_enabled= true;
}
}
}

static bool
is_path_token_delim (char c) {
return is_space (c) || c == '(' || c == ')' || c == '{' || c == '}' ||
c == '[' || c == ']' || c == ';' || c == '|' || c == '&' || c == '<' ||
c == '>';
}

static bool
looks_like_path_token (string token) {
if (is_empty (token)) return false;
if (token == "." || token == "..") return false;

url parsed= url_path (token);
if (is_rooted (parsed) || is_rooted_web (parsed) || is_concat (parsed))
return true;

bool has_dot = false;
bool has_alpha= false;
bool has_digit= false;
bool has_at = false;
bool has_colon= false;
bool has_dash = false;
for (int i= 0; i < N (token); i++) {
char c= token[i];
if (c == '/' || c == '\\') return true;
if (c == '.') has_dot= true;
if (is_alpha (c)) has_alpha= true;
if (is_digit (c)) has_digit= true;
if (c == '-') has_dash= true;
if (c == '@') has_at= true;
if (c == ':') has_colon= true;
if (c == ':' && i + 2 < N (token) && token[i + 1] == '/' &&
token[i + 2] == '/')
return true;
}

if (N (token) >= 2 && token[0] == '.' && token[1] == '/') return true;
if (N (token) >= 3 && token[0] == '.' && token[1] == '.' && token[2] == '/')
return true;
if (N (token) >= 2 && token[0] == '~' && token[1] == '/') return true;
if (has_at && has_colon) return true;
if (has_dot && has_alpha) return true;
if (token[0] != '-' && has_dash && has_alpha && has_digit) return true;
return false;
}

static bool
parse_path_token (string s, int& pos) {
if (pos >= N (s)) return false;
if (is_path_token_delim (s[pos])) return false;

int start= pos;
int end = pos;
while (end < N (s) && !is_path_token_delim (s[end]))
end++;
string token= s (start, end);
if (!looks_like_path_token (token)) return false;
pos= end;
return true;
}

text_property
prog_language_rep::advance (tree t, int& pos) {
string s= t->label;
Expand Down Expand Up @@ -255,6 +335,10 @@ prog_language_rep::advance (tree t, int& pos) {
current_parser= string_parser.get_parser_name ();
return &tp_normal_rep;
}
if (path_parser_enabled && parse_path_token (s, pos)) {
current_parser= "path_parser";
return &tp_normal_rep;
}
if (keyword_parser.parse (s, pos)) {
current_parser= keyword_parser.get_parser_name ();
return &tp_normal_rep;
Expand Down Expand Up @@ -313,7 +397,8 @@ prog_language_rep::get_color (tree t, int start, int end) {
int pos= 0;
while (pos <= start) {
if (inline_comment_parser.can_parse (s, pos)) {
return decode_color (lan_name, encode_color ("comment"));
if (!inline_comment_requires_space || (pos == 0 || is_space (s[pos - 1])))
return decode_color (lan_name, encode_color ("comment"));
}
pos++;
}
Expand Down