1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Qiitaでバッチファイルの謎なシンタクスハイライトを直したい

Posted at

はじめに

筆者は Windows でバッチファイルを愛用しているが,そのバッチファイルを Qiita の記事内で取り上げるときにシンタクスハイライトが気持ち悪いので下記の記事で取り上げたことがある。

Qiitaでバッチファイルのシンタクスハイライトが謎な件 - Qiita

具体的には下記のような感じである。なおシンタクスハイライト自体はバージョンアップによって変更される可能性があるため,この記事を書き始めた時点(2024年11月現在)における色付けを保存したものを以下に示す。

違和感を感じる部分を以下列挙する。

  • 実行ファイル名 csc.exeevalbar.exe.exe 部分がエラー判定となること。
  • FOR 変数 %%~$PATH:I もエラー判定となること。
  • キーワード属性 #ebd247 の対象が謎。echopause が外されて ifgotoexitfordoin などの制御構文が入るのは分かるが,それ以外にも echo 文の単なる出力文字列や goto 文のラベルにまでマッチングしているのがおかしい。
  • 環境変数の設定 set 文がキーワード属性 #ebd247 になっているのは分かるが,環境変数まで対象になっているのは止めたい。
  • オプションスイッチがアトリビュート属性 #8bdf4c になっているのは分かる。-w:4 の部分は分かるが,-win32icon:shogi.ico の色付けは無理やり感がある。

開発環境の立ち上げ

この記事を書いている現在,Qiita のシンタクスハイライトは Ruby の rouge によって実現されているので,まず ruby のインストールから始める。

次に gem を使って rouge をインストールする。

デバッグ用コード

改造のベースとするために batchfile.rb を開発用フォルダにコピーする。筆者の環境の場合,もともとのファイルは下記のパスにあった。

C:\Ruby32-x64\lib\ruby\gems\3.2.0\gems\rouge-4.5.0\lib\rouge\lexers\batchfile.rb

コピーする際にファイル名を MyBatchfile.rb に変え,クラス名も MyBatchfile に変える。

MyBatchfile.rb
module Rouge
  module Lexers
    class MyBatchfile < RegexLexer
    # 以下略

デバッグモード用のスクリプトを以下に示す。先ほどコピーした MyBatchfile.rb と同じフォルダに置く。なお,入力するファイル(バッチファイル)の文字コードを UTF-8 にする必要がある。

debug.rb
require "rouge"
require_relative "MyBatchfile"
if ARGV.size == 0 then
  puts "usage: debug(.rb) [filename(.cmd/bat)]"
  exit
end
filename = ARGV[0]
if !File.exist?(filename) then
  puts "#{filename} is not found."
  exit
end
input = File.open(filename, "rt:BOM|utf-8")
source = input.read
Rouge::Lexer.enable_debug!
lexer = Rouge::Lexers::MyBatchfile.new({'debug'=>'1'})
null = Rouge::Formatters::Null.new
null.format(lexer.lex(source))
exit

デバッグモードの実行例を以下に示すが,なんといきなり echo コマンドがビルトインコマンドとして判定されておらず,単なるテキストとして誤判定されているではないか!ちなみにビルトインコマンドとして判定されていない理由は先頭に @ の文字が付いているせいである。
@ を外せばビルトインコマンド判定になる。

デバッグモードの実行
c:\qiita\rouge>debug build.cmd
lexer: batchfile
stack: [:root]
stream: "@echo off\nsetlocal\nr"
  entering: mixin :basic
  trying: #<Rule /@?\brem\b.*$/i>
  trying: #<Rule /^::.*$/>
  trying: #<Rule /:[a-z]+/i>
  trying: #<Rule /([a-z]\w*)(\.exe|com|bat|cmd|msi)?/i>
  trying: #<Rule /((?:[\/\+]|--?)[a-z]+)\s*/i>
  entering: mixin :expansions
  trying: #<Rule /[%!]+([a-z_$@#]+)[%!]+/i>
  trying: #<Rule /(\%+~?[a-z]+\d?)/i>
  exiting: mixin :expansions
  trying: #<Rule /[<>&|(){}\[\]\-+=;,~?*]/>
  exiting: mixin :basic
  entering: mixin :data
  trying: #<Rule /\s+/>
  trying: #<Rule /0x[0-9a-f]+/i>
  trying: #<Rule /[0-9]/>
  trying: #<Rule /["]/>
  trying: #<Rule /[']/>
  trying: #<Rule /[`]/>
  trying: #<Rule /[^\s&|()\[\]{}\^=;!%+\-,"'`~?*]+/>
    got: "@echo"
    yielding: Text, "@echo"

~以下略~

長くなったので次回に続く。

次回,Qiitaでバッチファイルの謎なシンタクスハイライトを直したい2(予定)

参考文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?