2022年10月29日土曜日

CatMemoNoteにfill region的なコマンド追加 : AutoHotkey

CatMemoNoteにfill region的なコマンド追加 : AutoHotkey

CatMemoNoteにfill region的なコマンド追加 : AutoHotkey

便利に使っているメモソフトCatMemoNoteだが、メール用のテキスト編集に使う時、一定の文字数で改行を入れたい。emacsのfill regionのような機能が使えたらと思ったのでAutoHotkeyで作ってみた。

  • 選択範囲がある状態で alt+g を押すと、70文字で改行する。
  • 行頭に '>' または "\" が付いている場合は適当に字下げも行う。

#IfWinActive ahk_class CatMemoNoteMainFrame

; まずは単純な選択範囲の折返し
!g:: folding( cFillColumn := 70 )

;選択範囲なしで発動すると、カーソルが行頭にあった場合その行をコピー、
;なかった場合、カーソル位置以降をコピーとなる(catmemonote)

;処理された文字列がカーソル位置にペーストされ、行末に改行があるので
;元あった文字列の後半が次の行になる。

;○○○_○○○○
;   ↓
;○○○_●●●●●●●\r\n
;○○○○


;範囲選択がない場合
+!g::
  Send, {Home}+{Down}
  folding( cFillColumn := 70 )

;=========================

folding( cFillColumn )
{
  Send, ^c
  ClipWait
  vString := Clipboard
  Clipboard := ""
  If ( !ErrorLevel )
  {
    ;改行、行頭行末スペースtab、削除
    ;このファイルの文字コードがUTF-8 with BOMじゃないと" "にマッチしない
    vString := RegExReplace( vString,  "m)^[ ,\s]+" )
    vString := RegExReplace( vString,  "m)[ ,\s]+$" )
    StringReplace, vString, vString, `r`n, , All

    if( RegExMatch(vString,  "^>" ) )
    {
      vHead := " "
    }
    else if( RegExMatch(vString,  "^`\`\" ) )
    {
      vHead := "  "
    }
    else
    {
      vHead := ""
    }

    Loop, Parse, vString
    {
      vCurrentStr := vCurrentStr . A_LoopField
      wchar := A_LoopField
      ;全角か半角か
      ;次の範囲をUnicodeの半角文字とみなします。
      ;U+0000~U+007F,U+FF61~U+FFDC,U+FFE8~U+FFEE
;      if(wchar <= U+007F || (wchar >= U+FF61 && wchar <= U+FFDC) || (wchar >= U+FFE8 && wchar <= U+FFEE) )
      if( RegExMatch(wchar,  "[\x{0000}-\x{007F}]" ) || RegExMatch(wchar,  "[\x{FF61}-\x{FFDC}]" ) || RegExMatch(wchar,  "[\x{FFE8}-\x{FFEE}]" ))
      {
        cLen += 1  ;hankaku
;        MsgBox, %wchar% . "半角"
      }
      else
      {
        cLen += 2  ;zenkaku
;        MsgBox, %wchar% . "全角"
      }


      if( cLen >= cFillColumn - 1 )
      {
        ;行末に改行
        vCurrentStr := vCurrentStr . "`r`n"
        ;行頭にスペース 0 | 1 | 2 個
        vCurrentStr := vHead . vCurrentStr
        Clipboard := Clipboard . vCurrentStr
        vCurrentStr := ""
        cLen := 0
      }
    }
        ;最後の行 ここ空なら飛ばす?
        vCurrentStr := vCurrentStr . "`r`n"
        ;行頭にスペース 0 | 1 | 2 個
        vCurrentStr := vHead . vCurrentStr
        Clipboard := Clipboard . vCurrentStr
        vCurrentStr := ""
        cLen := 0
        ;余計な1行目行頭スペース除去
        StringTrimLeft, Clipboard, Clipboard, StrLen(vHead)

    Send, ^v
;MsgBox, cLen=%cLen% cFillColumn=%cFillColumn%

  }
  Return
}


/* ; 範囲選択を自動でやる版を作ろうとしたけど、遅くて不安定なのでボツとした
selectParagraph(wchar){
  Send, {Home}
  Loop  ;段落頭探し
  {
    if( RegExMatch(wchar, "\r\n" ))
    {
      ;行頭改行
      Send, {Up}
    }
    else
    {
      Send, {Up}
      wchar := CurrentChar()
      if( RegExMatch(wchar, "\r\n" ))
      {
        break
      }
    }
    wchar := CurrentChar()
  }

  Send, {Down}
  Loop  ;段落尻探し、選択
{
  wchar := CurrentChar()
  if( RegExMatch(wchar, "\r\n" ))
  {
    break
  }
  else
  {
    i++
    Send, {Down}
  }
}
Loop , %i%
{
    Send, +{Up}
}
  Return
}

 CurrentChar()
{
  Send, {Home}+{Right}
  Send, ^c
  ClipWait
  Send, {Left}
  Return  Clipboard
}
*/