Gauche:scm2cmd
- yokota: MS Windows の cmd.exe 上で Gauche のスクリプトをバッチファイルのように見せかける方法を見つけました。
具体的には任意のGaucheスクリプトの先頭に以下を、
;@rem -*- mode: scheme -*- ;@echo off ;gosh "%~f0" %* ;goto :__gauche_script_end
最後に
; ;:__gauche_script_end ;
を挿入し、ファイルの拡張子を .cmd にします。
これによりWindows上で任意のスクリプトをそのまま実行ファイルにできます。
末尾部分はの3行それぞれ「次の行を確実に行頭にする」、「バッチファイルの終了時にgotoで移動する場所」、「cmd.exeがコマンド終了時に挿入する改行を抑制」という意味があります。その性質上1行目と3行目は単なる空行でも構いませんが、何か見えた方が分かりやすいのでこうしました。
もちろん、 windows 上では ftype コマンドと assoc コマンドを用いればこのような事をせずに実行ファイルにできるのですが、リダイレクトができなくなる等問題があり、バッチファイルにする事はある程度の意義があります。
- Microsoftサポート技術情報: STDIN/STDOUT Redirection May Not Work If Started from a File Association
たぶんこれで直ります。 -- 通りすがり
- yokota: なるほど。もう直っていたんですね。情報ありがとうございます。 そうすると、この手法を用いなくても良いわけですが、上の方法を用いるとUnixの #! 記法のように、スクリプトを動かすインタプリタをスクリプト毎に直接指定できるので、Gauche以外の複数のSchemeインタプリタを混ぜて使いたい時などにはまだ有用ではないかと思います。ともあれ、ありがとうございました。
以上の操作を行なわせるスクリプトを以下に示します。 このスクリプトを用いたスクリプトを使用する時はあらかじめ gosh にPATHを通しておくかスクリプト上の gosh をフルパス指定して下さい。
バッチファイルはコマンド入力時に拡張子を省略して実行できるのでUnix上のGaucheスクリプトと同じようにプログラムを実行できます。ただし、この記法はUnixの #! 記法とは互換性が無いので注意して下さい。
filename: scm2cmd.scm
#!/usr/bin/gosh
;; scm2cmd by YOKOTA Hiroshi
#|
=head1 NAME
scm2cmd - wrap Gauche code into a MS Windows batch file
=head1 SYNOPSIS
B<scm2cmd> B<-h>
B<scm2cmd> S<[B<-o> I<output_file>]> I<input_file>
=head1 DESCRIPTION
This utility converts a Gauche script into a batch file that can be
executed on DOS-like operating systems. This is intended to allow
you to use a Gauche script like regular programs and batch files where
you just enter the name of the script [probably minus the extension]
plus any command-line arguments and the script is found in your B<PATH>
and run.
=head1 OPTIONS
=over 8
=item B<-h>
Show usage.
=item B<-o> I<output_file>
Specify output file name. If this option is not specified, make output
file name from input file name.
=head1 SEE ALSO
gosh
=cut
|#
(use gauche.parseopt)
(define (usage)
(print "Usage: scm2cmd [-o outfile] <script>")
(exit 0))
(define (main args)
(let-args (cdr args) ((outfile "o=s")
(help "h|help" => (cut usage))
. args)
(when (null? args) (usage))
(let* ((ifile (car args))
(ofile (or outfile
(if (#/\.scm$/ ifile)
(regexp-replace #/\.scm$/ ifile ".cmd")
#`",|ifile|.cmd"))))
(with-output-to-file ofile
(lambda ()
(for-each print '(";@rem -*- mode: scheme -*-"
";@echo off"
";gosh \"%~f0\" %*"
";goto :__gauche_script_end"))
(with-input-from-file ifile
(lambda () (copy-port (current-input-port)
(current-output-port))))
(for-each print '(";"
";:__gauche_script_end"
";"))
)))))
; end