0

---+ 简介

这个问题是关于在 emacs 的 cperl 模式下缩进多行字符串,例如对于 Perl,这样它们就不会破坏代码流。

我知道如何获得我想要的缩进,使用=~ s/^[^\S\n]*\|//mhr字符串上的转换,并提供 emacs :about 建议cperl-calculate-indentsyntax-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' andcperl-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 模式下编辑它,我可能会继承我不想意外破坏的遗留代码。
  • 此外,我可以对这些多行字符串进行不同类型的缩进/转换:

    1. 无 - 多行字符串的标准 cperl 模式缩进
    2. 修剪行首的前缀,例如 s/^[\S\n]*
    3. 有时我想要 cperl-mode 提供给 qw{} 的相同类型的缩进 - 基本上,我创建自己的 qw 允许使用逗号等没有警告的内容,s/\s+/ /g
    4. 有时我实际上可能希望字符串像 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中提到的问题。

4

0 回答 0