---+ 简介
这个问题是关于在 emacs 的 cperl 模式下缩进多行字符串,例如对于 Perl,这样它们就不会破坏代码流。
我知道如何获得我想要的缩进,使用=~ s/^[^\S\n]*\|//mhr
字符串上的转换,并提供 emacs :about 建议cperl-calculate-indent
,syntax-ppss
用于识别我何时在字符串中。
麻烦的是,有时我想做这样的缩进,有时又不想。
我寻求有关约定的建议,BKM,以暗示所需的缩进是什么。
my $legacy = qw{
This string
should
not be indented};
my $needs_trimming = (q{
|BEGIN
| SUB
|END
} =~ s/^[^\S\n]*\|//mgr);
my $needs_different_triming = (q{ + -
, ? :
| & ^
|| &&
| =~ s/\s+/ /gr);
我希望其他人在我之前解决了这个问题。
---+ 详细信息:
我将此作为 emacs/cperl 模式问题提出,但该问题对于允许多行字符串的语言是通用的。不仅是 Perl,还有 Javascript、C/C++、Javascript(不破坏缩进的多行字符串)、LISP 和 elisp 等。
我经常编写使用多行字符串的 Perl 代码。
我不喜欢多行字符串如何打破缩进:
if(cond) {
my $var = q{
START Line crossing string needs
to be indented
differently than rest of code
FINISH
};
my $var2 = ...
}
我更喜欢保持相同的缩进,所以我经常做类似的事情
if(cond) {
my $var = (q{
|START Line crossing string needs
| to be indented
| differently than rest of code
|FINISH
} =~ s/^[^\S\n]*\|//mgr);
my $var2 = ...
}
if(cond) {
my $var = fix_string( {unindent=>'|',trim=>1,},
q{
|START Line crossing string needs
| to be indented
| differently than rest of code
|FINISH
} =~ s/^[^\S\n]*\|//mgr);
my $var2 = ...
}
好的,所以这很好用,我已经做了很多年,可能几十年了。
过去效果不佳的是缩进,使用像perl-mode' and
cperl-mode' 这样的包。
好的,所以我解决了这个问题,使用
(defun cperl-calculate-indent--hack--/ag (orig-fun &rest args)
"hack / experimenting with cperl-calculate-indent"
(interactive)
(let ((state (syntax-ppss)))
(cond
((and (nth 3 state) ;in string
(nth 8 state) ; beginning of string
(< (nth 8 state) (point-at-bol)) ; on different line
)
(save-excursion
(goto-start-of-string--ag)
(+ 4 (current-column)))
)
(t (apply orig-fun args))
)
)
)
(advice-add 'cperl-calculate-indent :around #'cperl-calculate-indent--hack--/ag)
;;(advice-remove 'cperl-calculate-indent #'cperl-calculate-indent--hack--/ag)
所以现在我可以缩进多行字符串。如果那是我想做的。
不幸的是,有时我确实想缩进多行字符串。有时我不会。
- 例如,如果我在 cperl 模式下编辑它,我可能会继承我不想意外破坏的遗留代码。
此外,我可以对这些多行字符串进行不同类型的缩进/转换:
- 无 - 多行字符串的标准 cperl 模式缩进
- 修剪行首的前缀,例如 s/^[\S\n]*
- 有时我想要 cperl-mode 提供给 qw{} 的相同类型的缩进 - 基本上,我创建自己的 qw 允许使用逗号等没有警告的内容,s/\s+/ /g
- 有时我实际上可能希望字符串像 HTML、C 或 ...
我知道如何做这些。我可以为任何约定使用识别器。
但是...我正在寻找关于如何区分的建议,理想情况下是标准做法或 BKM。别人会觉得可读的东西。
例如,我考虑使用PerlX::QuoteOperator my_q
. 但这是不标准的,可能会混淆其他人,并且将来可能会中断。此外,我真正想做的只是提供缩进提示,而不是更改语言。
例如,如上所述,我已经使用了 fixup functions
fixup_string( q{ ... } )
。我可以在这些上进行模式匹配。但是当用户添加新的修复功能等时,这会中断。
例如,我考虑过查看字符串的第一行,例如
fixup_string( q{:
:not indented
: indented
} )
这适用于我的前缀 s/^[^\S\n]*://mgr,但不适用于其他情况。
(我目前正在做(looking-at ".[~!@#$%^&*_+=|:;'?/]$"))
,这很容易,但是有明显的问题(比如,如果我想从一个字符串开始"|\n..."
怎么办。即它没有通过测试“不要破坏合理可能的现有代码”。)
如果 Perl 有一个不是行尾的注释,比如 C 的 `/ ... /'我可能会 dp
fixup_string( q/*indent-here*/{|
|
|
} )
但是 Perl 确实有这样的非行尾注释。(是吗?是否有任何等效的句法技巧?)
因此我的问题。
我相信其他人之前已经解决了这个问题。我很想知道他们做了什么。
在许多方面,这只是同一缓冲区内多种模式的特例,https://emacswiki.org/emacs/MultipleModes。我想避免https://www.emacswiki.org/emacs/HtmlModeDeluxe中提到的问题。