getselectedtext()から改行を取り除くにはNo.10379
かんの さん 24/05/27 19:48
 
こんにちは、選択した文字を<b>太字</b>にするマクロを組んだのですが
改行を含めて選択した時にうまく動作しないようです。
getselectedtext()から改行を取り除く方法を教えていただけませんか。

$buff に 改行コードの"\x0A"が含まれていたら1文字減らしてみたもののうまくいき
ませんでした。

 // 選択ワードの前後にタグを追加
 $buff = getselectedtext();
 // 選択されてなかったらselectword2で選択する
 if ($buff == "")
 {
  selectword2;
  $buff = getselectedtext();
 }
 // 改行は末尾へ
 if (strstr( $buff, "\x0A") != -1)
 {
  $buff = leftstr( $buff, strlen( $buff) - 1);
  $Str = "改行あり<b>" + $buff + "</b>" + "\n";
 }
 else
 {
  $Str = "改行なし<b>" + $buff + "</b>";
 }
 insert $Str;

[ ]
RE:10379 getselectedtext()から改行を取No.10380
でるもんたいいじま さん 24/05/27 22:36
 
でるもんた・いいじまです。

> 選択した文字を<b>太字</b>にするマクロを組んだのですが
> 改行を含めて選択した時にうまく動作しないようです。
> getselectedtext()から改行を取り除く方法を教えていただけませんか。
>
> $buff に 改行コードの"\x0A"が含まれていたら
> 1文字減らしてみたもののうまくいきませんでした。

調べてみたところ、$buff の中の改行データは \x0A の1文字ではなく、\x0D \x0A
になっていました。これをしっかり考慮してあげる必要があります。

☆ ☆ ☆

以下、順番に。
 
>  // 選択ワードの前後にタグを追加
>  $buff = getselectedtext();
>  // 選択されてなかったらselectword2で選択する
>  if ($buff == "")
>  {
>   selectword2;
>   $buff = getselectedtext();
>  }

ここまでは特に問題ないと思います。

☆ ☆ ☆

で、その直後にこういうチェックを入れてみます。
  message "Debug: $buff='" + $buff + "', length=" + str(strlen($buff)) + ".";

$buffに改行が入った状態でこの message 文を実行すると、「$buff=='...'」の中に
改行が入るのは想定通りのはずですが、length= で表示される値が、そちらの期待し
ている値より1つ大きくなっているはずです。

☆ ☆ ☆

さらにチェックしてみます。こちらのコードを追加します:
  #posLF = strstr( $buff, "\x0A");
  #posCR = strstr( $buff, "\x0D");
  message "LFの位置=" + str(#posLF) + ", CRの位置=" + str(#posCR) + ".";

この結果を見れば、LF(\x0A)の直前に実はCR(\x0D)が潜んでいる、ということが
分かるはずです。

☆ ☆ ☆

原因究明はここまでですが、たとえばこのプログラム自体を「選択範囲の末尾に改行
が複数あるケースでも上手く動くものにしたい」といったことも考えると、全体とし
て次のようにするのがシンプルで読みやすいと思います。

if ( !selecting ) selectword2;
$buff = getselectedtext();

loaddll "hmJre.dll";
$str = dllfuncstr( "ReplaceRegular", "^(.*?)([\\x0D\\x0A]+)$",
    $buff, 0, "改行あり<b>\\1</b>\\2", 1);

if ( $str == "" ) // ReplaceRegularが失敗した場合
  $str = "改行なし<b>" + $buff + "</b>";

insert $str;
freedll;
endmacro;

正規表現を使うと、かなり込み入った処理でも数行でシンプルに記述できることが
多々あります。もしお時間がありましたら、ぜひ正規表現の勉強をしてみてください。
マクロから呼び出す以外にも、普段の検索・置換作業にも重宝します。

ただし、もしも「全くのゼロから勉強を始める」という状況の場合は、秀丸用の正規
表現に特化した資料はほぼ皆無ですので、まずは他のポピュラーな言語で正規表現の
基礎を一通り固めてから、そのあと秀丸特有の方言を適宜覚えていく、という順序が
いいと思います。

そういう「ポピュラーな言語」としては、たとえばJavaScriptが大本命の一つですし、
Perl/Ruby/Pythonなどのスクリプト言語でも大丈夫です。

☆ ☆ ☆

最後に1つだけ、オマケです。

今回は「もしかして \x0D が入っているのかな?」という予想がたまたまビンゴだっ
たのですが、逆にどうしても状況が分からない場合には、次のような「秘密兵器」を
使うといいです。

dump:
  $$dump = "";
  $$target = $$1;
  while ( $$target != "" )
  {
    ##c = ascii($$target);
    $$dump = $$dump + sprintf("%02X ",##c); //##cを「2桁以上の16進数」に
変換

    if ( ##c<0x100 ) // 1バイト文字
      $$target = midstr($$target, 1, 99999999);
    else // 2バイト文字
      $$target = midstr($$target, 2, 99999999);
  }
  message "文字列 '" + $$1 + "' の16進ダンプは次の通り:\n" + $$dump;
return;

メインのプログラムからは、
call dump $buff;
のように呼び出します。

☆ ☆ ☆

ではでは。長くなりましたがこんなところで。

[ ]
RE:10379 getselectedtext()から改行を取No.10381
igus さん 24/05/27 22:55
 
改行コードで分割してつなぎ直してみたらどうだろうって思って作ってみてうまくい
ったっぽいです。最後の改行のみの部分を消すのがスマートじゃないけど。

//タグ追加するよ.mac
begingroupundo;
if(!selecting)selectword2;
$s1=getselectedtext();
#n=split($b,$s1,"\r\n");
$s2=join($b,#n,"</b>\r\n<b>");
insert "<b>"+$s2+"</b>";
replaceallfast "<b></b>","";
endgroupundo;
endmacro;

[ ]
RE:10381 getselectedtext()から改行を取No.10382
かんの さん 24/05/28 07:03
 
かんのです。

でるもんた・いいじまさん、igusさん。

デバッグしてみましたらCRLFになっていましたので、その点を踏まえたらうまく動作
するようになりました。
改行コードで繋ぎなおすのも良さそうですね。
ありがとうございました。

[ ]