OrangeX4 / OrangeX4-HyperSnips

OrangeX4's HyperSnips
52 stars 26 forks source link

关于行间公式snippet的建议 #6

Closed pilgrimlyieu closed 3 years ago

pilgrimlyieu commented 3 years ago

在markdown.hsnips的403-413行中的im为

snippet im "inline Math" wA
$${1}$``
let str = t[0];
let test = str.charAt(str.length - 1);
if (test != ',' &&  test != '.' &&  test != '-' && test !='?' && test !=' '){
    rv = ' ';
}
else{
    rv = '';
}``$2
endsnippet

这个snippet只有在$a-$xxx等时$和xxx之间才会没有空格,但是我认为$a$-xxx在$和-之间没有空格的观感更好,而且那位神级小哥似乎也是这么做的:smile:

我自己改了一下不知道对不对。我把t[0]改成了t[1]str.length - 1改成了0

snippet im "inline Math" wA
$${1}$``
let str = t[1];
let test = str.charAt(0);
if (test != ',' &&  test != '.' &&  test != '-' && test !='?' && test !=' '){
    rv = ' ';
}
else{
    rv = '';
}``$2
endsnippet

还有一个,在559-561行中的是

snippet prod "product" wAm
\prod_{${1:n=${2:1}}}^{${3:\infty}} ${4:${VISUAL}} $0
endsnippet

请问一下这个VISUAL怎么使用,是先框选然后直接输入snippet吗?我试了一下似乎不奏效。

非常感谢!

pilgrimlyieu commented 3 years ago

嗯还有一个,以im开头的单词还是挺多的,所以建议可以换成lm之类的。

pilgrimlyieu commented 3 years ago

再请教一下,我想让下面这些函数可以在后面为字母时自动添加空格,在非字母时不添加空格,于是我参考了一下im snippet的写法写了下面的snippet,但是只能用一次,嵌套了就无法使用;而且有BUG,会把后面的一个字符拉到前面来。

snippet `(?<!\\[a-zA-Z]*)(sin|cos|tan|cot|arcsin|arccos|arctan|arccot|csc|sec|log|ln|lg|exp|arg|max|min)` "函数名" wAm
\``rv = m[1]````
if (/^[a-zA-Z]/.test(t[0]) == true){
    rv = ' ';
}
else{
    rv = '';
}``$1
endsnippet

3

我还写了一个别的,但是也有一样的问题

snippet `(?<!\\[a-zA-Z]*)(sin|cos|tan|cot|arcsin|arccos|arctan|arccot|csc|sec|log|ln|lg|exp|arg|max|min)` "函数名" wAm
\``rv = m[1]````
let str = t[0];
let test = str.charAt(0);
if ((test >= "a" && test <= "z") || (test >= "A" && test <= "Z")){
    rv = ' ';
}
else{
    rv = '';
}``$1
endsnippet
pilgrimlyieu commented 3 years ago

再请教一下,我想让下面这些函数可以在后面为字母时自动添加空格,在非字母时不添加空格,于是我参考了一下im snippet的写法写了下面的snippet,但是只能用一次,嵌套了就无法使用;而且有BUG,会把后面的一个字符拉到前面来。

测试了一下,输入依次输入sin``a``cos就正常,看来是因为第二个符号snippet触发变成\开头,然后中间的空格就消失了造成的。但是不能排除\,因为空格会阻拦分式snippet的运行(加括号有点麻烦,而且之前好像出过一点bug就没怎么用过)。

还有,依次输入sin``a``cos也不会把后一个字符拉到前面了。

不知道有没有一个功能能输完一个字符就自动退出placeholder或者已经有了rv后就不再改变之类的功能。

pilgrimlyieu commented 3 years ago

有个小问题,正则排除了一部分,改成下面就可以连续输入命令了。但是没有实质改变,两个问题仍然存在。

snippet `(?<!\\)(sin|cos|tan|cot|arcsin|arccos|arctan|arccot|csc|sec|log|ln|lg|exp|arg|max|min)` "函数名" wAm
\``rv = m[1]````
if (/^[a-zA-Z]/.test(t[0]) == true){
    rv = ' ';
}
else{
    rv = '';
}``$1
endsnippet

另外,先输入sin变成\sin后输入c按一下Tab再输入os就能正常工作,但是效率太低了。

OrangeX4 commented 3 years ago

插件已更新,可以用 ${VISUAL} 语法了。

WetABQ commented 3 years ago
\``rv = m[1]````
if (/^[a-zA-Z]/.test(t[0]) == true){
  rv = ' ';
}
else{
  rv = '';
}``$1

问题大概是因为 Flag A 的自动展开,当 Tab Stop 没有消失,便会在 Tab Stop 内部连续 update Snippets

目前来看,应该在 Snippet 书写规范中加入 禁止同时使用 Regex 和 Dynamics Update,因为写的正则完全处于一个新的不可控的环境下,而且一直不结束,很容易造成 Snippet 触发崩坏,甚至是严重的性能问题。

如 Inline Math 的 im 展开为 ${TAB_1}${TAB_2} 或许可以允许在 TAB_1中使用带有前后匹配的 Regex Dynamics Update,如 $ ^ 但应该不允许在 TAB_1 中做普遍 Regex 检测,并且尽管 $ ^TAB_1 匹配看上去是安全的,也仅限于目前来而言只是看上去安全,并不推荐这样的使用方法。

TAB_2 只有 ^ 匹配看上去似乎是安全的,但仍然强烈不建议这样使用 Snippet

WetABQ commented 3 years ago

尝试修复了一下,但是这似乎是 HSnips 的 bug

snippet `(?<=\b|\d+)(?<!\\)(sin|cos|arccot|cot|csc|ln|log|exp|star|perp)` "function" wAm
\``
if (/^[a-zA-Z]/.test(t[0]) == true && t[0] != 'undefined'){
    rv = m[1] + ' ';
}
else{
    rv = m[1] + '';
}``${1}``if (/^[a-zA-Z]/.test(t[0]) == true && t[0] != 'undefined'){
    rv = ' ';
}
else{
    rv = '';
}``
endsnippet

这样写的时候 后面的空格会自动填充并选中,但期望是不选中,只填充,如果把填充的空格改为 abc 则不会发生这个问题

WetABQ commented 3 years ago

再研究了一下发现,似乎 HSnips 的动态更新问题很多,甚至 box 都有问题,不建议使用 HSnips 的动态更新。建议改为命令式 Snippet,但是这里用命令式 Snippet 书写性价比比较低,建议还是手打空格,或者修复一下 HSnips 动态更新的问题。

WetABQ commented 3 years ago

命令式 Snippet 大抵可以参考这样的写法,

priority 200
snippet `c(o|n)?(l|n)?(b|c)?int` "s     egral" wAm
``
let final = "\\"; // init
let isO = m[1] == "o";
(isO) ? final += "o" : "" // o option
let b = 1;
let isL = m[2] == "l";
(m[3] == 'b') ? b = 2 : (m[3] == 'c') ? b = 3 : 1;
for (let i = 0; i < b - 1; i++) {
final += "i";
}
final += "int";
final += ((b >= 2) || (b != 1 && !isO && isL)) ? "\\limits" : "";
let r = (b == 3) ? "E" : (b == 1 && (isL || isO)) ? "C" : "R";
final += ((b >= 2) || isO || (b == 1 && isL)) ? "_{${1:" + r + "}}" : "_{${1:-\\infty}}^{${2:\\infty}}";
let x = (b == 2) ? "A" : (b == 3) ? "V" : (b == 1 && isL) ? "s" : "x";
final += " ${3} ~\\mathrm{d}${4:" + x + "} $0";
rv = final;
``
endsnippet

c(o)(l)(b/c)int, 如 coint 就是一阶曲线积分,cbint 就是二重积分,ccint 就是三重积分,clint 是一阶曲线积分的简写版等等组合方式

pilgrimlyieu commented 3 years ago

请教一下,我想将类似"$xxx$"替换成"(xxx)",但是"xxx"里包含"$",然后返回rv时会被当做tab stop,怎样避免这种情况?

代码如下

snippet `\$(.+)\$` "test" A
rv = "\\(" + m[1] + "\\)";
endsnippet

我也试过将"$"替换成"\$"和"\$"但没什么用,只要将"$"替换成别的字符就能正常使用,但就是不能正确返回$字符。

非常感谢!!!

OrangeX4 commented 3 years ago

这是正则表达式的问题, 既然 xxx 包含 "$", 那正则表达式怎么可能那么智能的知道到底要在哪个 "$" 截断呢?

例如 "$abcd$efg$" 这样的字符串, 正则表达式怎么区分得了你要的 xxx 到底是 "abcd" 还是 "abcd$efg" 呢, 两者的区别是非贪婪或贪婪策略.