For Development HEAD DRAFTSearch (procedure/syntax/module):

3.2 インタラクティブな開発

スクリプトファイルが与えられなかった場合、 goshはインタラクティブなread-eval-printループ(REPL)に入ります。

インタプリタを終了するには、EOF文字(Unix端末では通常Control-D)をタイプするか、 (exit)を評価します。

インタラクティブセッションでは、goshgauche.interactiveモジュールをロードしてuserモジュールにインポートします (gauche.interactive - インタラクティブセッション参照)。 また、ユーザーのホームディレクトリに.gauchercという ファイルがあればそれもロードされます。 インタラクティブデバッグに便利な設定をそこに書いておくことができます。 (Gauche release 0.7.3から、.gauchercはgoshがスクリプトモードで 起動された時は読まれなくなりました。)

.gauchercは常にuserモジュールへとロードされます (gosh-r7オプションつきで起動されていてもそうです)。 .gauchercを自動で読み込む、という機能自体がGauche特有の機能ですから、 そこでポータビリティを考慮する必要はないわけです。

goshをEmacs内部で走らせることをお勧めします。 EmacsはSchemeサブプロセスを操作するための豊富な機能を持っています。 次の行を.emacsに加えておくと、M-x run-scheme で Emacsのバッファ内でgoshが走ります。

(setq scheme-program-name "gosh -i")

カーソル制御可能な端末でgoshを走らせた場合、 REPLセッションで簡単な行編集が使えます。 詳しくは入力の編集を参照してください。

対話環境でマルチバイト文字を使う場合は、端末の文字エンコーディングをgoshの 内部エンコーディングと合わせるようにして下さい。


3.2.1 REPLでの開発

REPLに入ると、Gaucheはプロンプトを出してScheme式の入力を待ちます。

gosh>

(入力編集機能をオンにしている場合は、プロンプトがgosh>ではなく gosh$になります。詳しくは入力の編集を参照してください。)

完全なScheme式を入力してENTERをタイプすると、そのS式の評価結果が表示されます。

gosh> (+ 1 2)
3
gosh>

REPLセッションは、過去3回分の評価結果をグローバル変数 *1*2*3 に束縛します。これらのヒストリ変数を 使って、以前の結果を後続の式の中で使えます。

gosh> *1
3
gosh> (+ *2 3)
6

Scheme式が複数の値を返した場合 (多値参照)は、各値が順に表示されます。

gosh> (min&max 1 -1 8 3)
-1
8
gosh>

式が多値を返しても、変数*1*2*3 に束縛されるのは最初の値のみです。しかし別のグローバル変数 *1+*2+*3+に、全ての値をリストにしたものが 束縛されています。

gosh> *1
-1
gosh> *2+
(-1 8)

(上の例で、*1を評価した時点でヒストリがひとつずれてしまっていることに 注意してください。(min&max 1 -1 8 3)の結果を見るためには *2+を参照する必要があります。)

手続き*historyはヒストリ変数の値を表示します。

gosh> (*history)
*1: (-1 8)
*2: -1
*3: -1
gosh>

特別な場合として、式の評価がゼロ個の値を返した場合は、ヒストリ変数は更新されません。 *history手続きはゼロ個の値を返すので、ヒストリを見るだけでヒストリが 進んでしまうということはありません。

gosh> (*history)
*1: (-1 8)
*2: -1
*3: -1
gosh> (values)
gosh> (*history)
*1: (-1 8)
*2: -1
*3: -1

最後に、評価途中で捕捉されないエラーが発生した場合は、エラーコンディションオブジェクトが グローバル変数*eに束縛されます。

gosh> (filter odd? '(1 2 x 4 5))
*** ERROR: integer required, but got x
Stack Trace:
_______________________________________
  0  (eval expr env)
        At line 173 of "/usr/share/gauche-0.9/0.9.3.3/lib/gauche/interactive.scm"
gosh> *e
#<error "integer required, but got x">

(エラースタックトレースの表示はインストールの状況によって異なる場合があります。)

REPLプロンプトではまた、よくある仕事のために、特別なトップレベルコマンドを 入力することもできます。トップレベルコマンドはScheme式ではありませんし、S式でさえ ありません。むしろ、伝統的な行指向のシェルコマンドのように動作します。

トップレベルコマンドは通常のScheme式と区別するために、コンマで始まります。 どういったコマンドが使えるかを見るには、,helpとタイプしてリターンを 入力してみてください。

gosh> ,help
You're in REPL (read-eval-print-loop) of Gauche shell.
Type a Scheme expression to evaluate.
A word preceded with comma has special meaning.  Type ,help <cmd>
to see the detailed help for <cmd>.
Commands can be abbreviated as far as it is not ambiguous.

 ,apropos|a  Show the names of global bindings that match the regexp.
 ,cd         Change the current directory.
 ,describe|d Describe the object.
 ,help|h     Show the help message of the command.
 ,history    Show REPL history.
 ,info|doc   Show info document for an entry of NAME, or search entries by REGEXP.
 ,load|l     Load the specified file.
 ,print-all|pa
             Print previous result (*1) without abbreviation.
 ,print-mode|pm
             View/set print-mode of REPL.
 ,pwd        Print working directory.
 ,reload|r   Reload the specified module, using gauche.reload.
 ,sh         Run command via shell.
 ,source     Show source code of the procedure if it's available.
 ,use|u      Use the specified module.  Same as (use module option ...).

それぞれのコマンド特有のヘルプを見るには、コンマを含まないコマンド名を helpコマンドに与えてください。

gosh> ,help d
Usage: d|describe [object]
Describe the object.
Without arguments, describe the last REPL result.

,d (あるいは,describe)トップレベルコマンドは与えられたSchemeオブジェクト、 または何もオブジェクトが与えられなければ直前の結果のオブジェクトについて、 その説明を表示します。ちょっと試してみましょう。

gosh> (sys-stat "/home")
#<<sys-stat> 0x2d6adc0>
gosh> ,d
#<<sys-stat> 0x2d6adc0> is an instance of class <sys-stat>
slots:
  type      : directory
  perm      : 493
  mode      : 16877
  ino       : 2
  dev       : 2081
  rdev      : 0
  nlink     : 9
  uid       : 0
  gid       : 0
  size      : 208
  atime     : 1459468837
  mtime     : 1401239524
  ctime     : 1401239524

上の例では、まず(sys-stat "/home")を評価して、結果として <sys-stat>オブジェクトが返ってきました。続く,dコマンドによって その<sys-stat>オブジェクトの詳細が表示されています。

表示される情報はオブジェクトの型に依存します。型によっては、追加の情報が 表示される場合もあります。例えば正確な整数をdescribeすると、 いくつかの異なる解釈が示されます。

gosh> ,d 1401239524
1401239524 is an instance of class <integer>
  (#x538537e4, ~ 1.3Gi, 2014-05-28T01:12:04Z as unix-time)
gosh> ,d 48
48 is an instance of class <integer>
  (#x30, #\0 as char, 1970-01-01T00:00:48Z as unix-time)

シンボルをdescribeすると、分かっている束縛が示されます。

gosh> ,d 'filter
filter is an instance of class <symbol>
Known bindings for variable filter:
  In module `gauche':
    #<closure (filter pred lis)>
  In module `gauche.collection':
    #<generic filter (2)>

手続きをdescribeした場合、もし分かっていればそのソースコード上の 場所も表示されます(Defined at ...の行):

gosh> ,d string-interpolate
#<closure (string-interpolate str :optional (legacy? #f))> is an
instance of class <procedure>
Defined at "../lib/gauche/interpolate.scm":64
slots:
  required  : 1
  optional  : #t
  optcount  : 1
  locked    : #f
  currying  : #f
  constant  : #f
  info      : (string-interpolate str :optional (legacy? #f))
  setter    : #f

他のトップレベルコマンドも見てみましょう。,infoコマンドは 手続き、変数、構文、モジュールもしくはクラス名が与えられると、そのドキュメントを 表示します。(テキストはシステムにインストールされたGaucheのinfoドキュメントから 検索されます。もしエラーが出た場合は、infoドキュメントが正しくインストール されているかどうか確認してください。)

gosh> ,info append
 -- Function: append list ...
     [R7RS base] Returns a list consisting of the elements of the first
     LIST followed by the elements of the other lists.  The resulting
     list is always newly allocated, except that it shares structure
     with the last list argument.  The last argument may actually be any
     object; an improper list results if the last argument is not a
     proper list.

gosh> ,info srfi.19
 -- Module: srfi.19
     This SRFI defines various representations of time and date, and
     conversion methods among them.

     On Gauche, time object is supported natively by '<time>' class
     (*note Time::).  Date object is supported by '<date>' class
     described below.

gosh> ,info <list>
 -- Builtin Class: <list>
     An abstract class represents lists.  A parent class of '<null>' and
     '<pair>'.  Inherits '<sequence>'.

     Note that a circular list is also an instance of the '<list>'
     class, while 'list?' returns false on the circular lists and dotted
     lists.
          (use srfi.1)
          (list? (circular-list 1 2)) => #f
          (is-a? (circular-list 1 2) <list>) => #t

また、,infoコマンドに正規表現のパターンを与えることもできます (正規表現参照)。 その場合、パターンにマッチするドキュメントの項目の一覧が表示されます。

gosh> ,info #/^string-.*\?/
string-ci<=?             Full string case conversion:44
                         String comparison:19
string-ci<?              Full string case conversion:43
                         String comparison:18
string-ci=?              Full string case conversion:42
                         String comparison:17
string-ci>=?             Full string case conversion:46
                         String comparison:21
string-ci>?              Full string case conversion:45
                         String comparison:20
string-immutable?        String Predicates:9
string-incomplete?       String Predicates:12
string-null?             SRFI-13 String predicates:6
string-prefix-ci?        SRFI-13 String prefixes & suffixes:28
string-prefix?           SRFI-13 String prefixes & suffixes:26
string-suffix-ci?        SRFI-13 String prefixes & suffixes:29
string-suffix?           SRFI-13 String prefixes & suffixes:27

,a (または,apropos) は、与えられた名前や正規表現に マッチするグローバルな識別子を表示します。

gosh> ,a filter
filter                         (gauche)
filter!                        (gauche)
filter$                        (gauche)
filter-map                     (gauche)

註: aproposコマンドは現在のプロセス中から名前を探します。 つまり、既にロードされインポートされた名前しか表示しません。 それは同時に、ロードされてさえいれば、ドキュメントのある公式なAPIか 内部的な非公式なエントリかにかかわらず表示されるということでもあります。

一方、infoコマンドは現在のプロセスにロードされているかどうか とは関係なく、infoドキュメントから検索します。ドキュメントされていない APIにはヒットしません。

aproposはイントロスペクションのツール、 infoはドキュメント参照のツールと考えると良いでしょう。

評価結果が巨大な構造になる場合、それを表示するのに時間がかかりすぎる問題があります。 Gaucheはデフォルトで、表示する構造の長さと深さに制限を設けているので、 非常に長い、あるいは深い構造を表示しようとした場合に、…によって後の方が 省略されたり、#によって深い構造が省略されたりします (REPLで(make-list 100)を評価してみてください。)

直前の結果を省略無しで再表示するには ,pa (もしくは,print-all) トップレベルREPLコマンドをタイプしてください。

デフォルトでは、REPLはネストした構造をプリティプリントします:

gosh> ,u sxml.ssax
gosh> (call-with-input-file "src/Info.plist" (cut ssax:xml->sxml <> '()))
(*TOP*
 (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"")
 (plist
  (|@| (version "1.0"))
  (dict (key "CFBundleDevelopmentRegion") (string "English")
   (key "CFBundleExecutable") (string "Gauche") (key "CFBundleIconFile")
   (string) (key "CFBundleIdentifier") (string "com.schemearts.gauche")
   (key "CFBundleInfoDictionaryVersion") (string "6.0")
   (key "CFBundlePackageType") (string "FMWK") (key "CFBundleSignature")
   (string "????") (key "CFBundleVersion") (string "1.0")
   (key "NSPrincipalClass") (string))))

何らかの理由でプリティプリントをoffにしたい場合は、 トップレベルプロンプトで,pm pretty #f (あるいは,print-mode pretty #f)と打つか、 環境変数GAUCHE_REPL_NO_PPRINTをセットしてgoshを起動してください。

プリントモードをデフォルトに戻すには,pm defaultとタイプします。 より詳しくは,help pmを見てください。

註: gosh-qオプション (初期化ファイルをロードしない) で 起動した場合もREPLに入りますが、そこではヒストリ変数などは使えません。 REPLの便利機能はgauche.interactiveモジュールで実装されていますが、 -qオプションをつけるとgauche.interactiveがロードされないからです。


3.2.2 入力の編集

goshがカーソル制御可能な端末で起動された場合、入力編集が可能です。 入力編集モードが有効であれば、REPLのプロンプトが$で終わります。 例えばデフォルトではgosh>のかわりにgosh$になります。

(註: 今のところ、Gaucheはvt100系のエスケープシーケンスを認識する端末か、 Windows consoleのみをサポートします。端末タイプがそれらでなかった場合は、 入力編集の無いモードになります。プロンプトでどちらのモードにいるかわかります。)

入力編集機能はまだ開発途上です。もし重大なバグに当たって編集機能をオフにしたければ、 環境変数GAUCHE_NO_READ_EDITを設定するか、 gosh-fno-read-edit オプションつきで起動するか、 REPLで ,edit off とタイプしてください。

キーバインディングはEmacsと似ています。いずれカスタマイズする機能も提供する予定です。 詳細に立ち入る前に、知っておくと良いヒントをいくつか。

カーソル移動

C-f (forward) と C-b (backward) はカーソルを一文字前あるいは 一文字後に移動します。C-p (previous) と C-n (next) は カーソルを一行前あるいは一行後に移動します。移動方向に行が無ければ、 入力バッファが一つ前または一つ後のヒストリに置き換わります。

M-fM-bは単語単位でカーソルを前後に移動します。

C-aC-eは行の先頭または末尾に、 M-<M->は入力バッファの最初または最後にカーソルを移動します。

Undo

直前の変更をundoするにはC-_を使います。C-_を続けてタイプすれば どんどん編集をundoできます。undoのモデルはEmacsと同じで、つまり [undo自体をundoする]こともできます。 詳しいアルゴリズムは、ソースのlib/text/line-edit.scm末尾の コメントを見てください。

killとyank

C-kはカーソルから行末までの文字を取り除きます。もしカーソルが既に 行末にあったら、改行文字そのものを取り除きます(つまり、次の行が現在の行の後に 接続されます)。

M-dはカーソルが単語の中にあればその単語を、そうでなければ直後の単語を 取り除きます。

C-@はカーソル位置をマークします。その後、C-wで その時点のカーソルとマークの間の文字を取り除けます。

これらのコマンドで取り除かれた文字は、“kill-ring” と呼ばれるバッファに セーブされていて、C-yをタイプするとカーソル位置に復元することができます。 C-yの後に続けてM-yをタイプしてゆくと、“kill-ring”にセーブされた さらに古い内容へと遡って復元することができます。

補完

部分的にタイプされた単語の中、もしくは直後にTABを打つと単語が補完されます。 複数の候補がある場合、共通するプレフィクスが補完され、そこで続けてTABを打つと候補がリストされます。

何が補完されるかは文脈によります。トップレベルコマンド (プロンプトにおいてコンマの後に続く単語)の場合はトップレベルコマンドが、 ,loadトップレベルコマンドの引数であればパス名が、 ,use,reloadトップレベルコマンドの引数であればモジュール名が、 そしてその他の文脈では現在のモジュールから見えるグローバル束縛があるシンボルです。

シンボルとモジュール名については、区切られた単語による補完が可能です。 例えばc-w-c-ccall-with-current-continuationに補完されます。

今のところ、補完メカニズムはハードコードされています。いずれカスタマイズできるように するかもしれません。

入力の終了

入力のS式がまだ完結していなければ、RET (C-m) は入力に改行文字を 挿入します。もしS式が完結していれば、カーソルがどこにあってもRET (C-m)は 入力を評価機に送ります。もし完結したS式の途中に改行を追加したい場合は C-jをタイプしてください。

S式が完結しているかどうかにかかわらず入力を評価したい場合は、 M-C-xをタイプしてください。

ヒストリ

入力のヒストリは保存されていて、M-p (prev-history)と M-n (next-history)で呼び出すことができます。 カーソル上下移動のC-pC-nも、現在の入力バッファを越えて移動しようとすると 前または後のヒストリを呼び出します。

C-cで中断された入力はヒストリに保存されません。

デフォルトでは、入力ヒストリはREPLが正常終了する際に~/.gosh_historyされ、 次にREPLが起動する際に読み込まれます。 ヒストリを保存するファイル名は環境変数GAUCHE_HISTORY_FILEで変更できます。 また、この環境変数が空文字列にセットされていれば、ヒストリは保存されません。

その他

C-gは複数キーシーケンスをキャンセルします。

C-cは現在の入力をキャンセルします。

C-tはカーソルとその前の文字を入れ替えます。

C-qは次のキーストロークを読み取ってそれを入力にそのまま挿入します。

M-(は対になった括弧を挿入し、カーソルを括弧の間に置きます。

C-lは画面をクリアし、入力バッファを再表示します。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT