yamasushi(2013/04/11 06:38:36 UTC)interactive/info.scmをもとに、マニュアルを検索するライブラリをつくってみました。述語を指定して、マッチするキーをひいて、取得したマニュアルデータの見出し部分をさらにフィルタします。
($マクロを多用したので、schemeのコードのように見えないかもしれません。(汗)
;;; gaucheのinfoにアクセスする。
;;; interactive/info.scmを改造した。
;;; もとになったblog
;;; Gaucheのinfo関数の表示を日本語にするには - 再帰の反復
;;; http://d.hatena.ne.jp/lemniscus/20100326/1269613137
;;; interactive/info.scm - online helper
;;;
;;; Copyright (c) 2000-2012 Shiro Kawai <shiro@acm.org>
;;;
;;; Redistribution and use in source and binary forms, with or without
;;; modification, are permitted provided that the following conditions
;;; are met:
;;;
;;; 1. Redistributions of source code must retain the above copyright
;;; notice, this list of conditions and the following disclaimer.
;;;
;;; 2. Redistributions in binary form must reproduce the above copyright
;;; notice, this list of conditions and the following disclaimer in the
;;; documentation and/or other materials provided with the distribution.
;;;
;;; 3. Neither the name of the authors nor the names of its contributors
;;; may be used to endorse or promote products derived from this
;;; software without specific prior written permission.
;;;
;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
;;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
;;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;;
; TODO コード構成の整理。
; TODO シンプルなヘルプ
; TODO key ---> 見出し map
; TODO caddrの展開
; TODO <dictionary> <ordered-dictionary>などの重要だがdocumentに索引のないものに対応
; TODO 実際のクラス・モジュール情報を見て処理する
(define-module textj.gauche-info (extend textj.info-lib textj.info-root)
(use gauche.config)
(use srfi-1)
(use srfi-13)
(use gauche.mop.singleton)
(use text.tree)
(use gauche.generator)
(use gauche.dictionary)
(use gauche.sequence)
(use gauche.lazy)
(use util.match)
(use text.info)
(use gauche-modules)
(use pretty-print) ; debug
(use komono-dict)
(use komono-combinator)
(use komono-regexp)
(export
gauche-info-root <gauche-info-root> <info-index-node>
gauche-source <gauche-source>
gauche-module-finder <gauche-module-finder>
<%node>
;;
info-string-generator info-string-lseq
info-deftp&body-generator info-deftp&body-lseq
info-deftp-generator info-deftp-lseq
info-node-function-jp info-node-function-en
info-node-variable-jp info-node-variable-en
info-node-class-jp info-node-class-en
info-node-module-jp info-node-module-en
process-deftp-string-list
)
)
(select-module textj.gauche-info)
(define *source* "*source*") ; ソースファイルを見る。
(define *index-node-source-module-jp* "*module*")
(define *index-node-source-function-jp* "*function*")
(define *index-node-source-variable-jp* "*variable*")
(define *index-node-source-class-jp* "*class*")
(define *index-node-source-macro-jp* "*macro*")
(define *info-file-jp* "gauche-refj.info") ; 日本語infoを見る
(define *info-file-en* "gauche-refe.info") ; 英語infoを見る
(define *info-file-dev-en* "gauche-deve.info") ; 開発者manual
(define *info-file-gl-en* "gauche-gl-refe") ; Gauche gl
(define *index-node-function-jp* "Index - 手続きと構文索引")
(define *index-node-variable-jp* "Index - 変数索引")
(define *index-node-class-jp* "Index - クラス索引")
(define *index-node-module-jp* "Index - モジュール索引")
(define *index-node-function-en* "Function and Syntax Index")
(define *index-node-variable-en* "Variable Index")
(define *index-node-class-en* "Class Index")
(define *index-node-module-en* "Module Index")
(define *index-node-dev-function-en* "Function and Macro Index")
(define *index-node-dev-type-en* "Type Index")
(define *index-node-dev-variable-en* "Variable Index")
(define *index-node-gl-function-en* "Function and Syntax Index")
(define *index-node-gl-variable-en* "Variable Index")
(define *index-node-gl-class-en* "Class Index")
(define *index-node-gl-module-en* "Module Index")
(define *toc-lib-gauche-jp* "ライブラリモジュール - Gauche拡張モジュール")
(define *toc-lib-srfi-jp* "ライブラリモジュール - SRFI")
(define *toc-lib-utilities-jp* "ライブラリモジュール - ユーティリティ")
(define *toc-lib-gauche-en* "Library modules - Gauche extensions")
(define *toc-lib-srfi-en* "Library modules - SRFIs")
(define *toc-lib-utilities-en* "Library modules - Utilities")
;--------------------------------------
; type --> node のテーブル
; menu keyword ---> key変換器(関数・文法用)
(define gauche-menu-key-converter-fn
(rxmatch-lambda
; (setter *)の処理 (重複している場合も含める)
[#/^\s*\(setter\s+(\S+)\s*\).*$/ (_ k) k ]
; refなどの重複するエントリの処理
[#/^\s*(\S+)\s*<[^>]+>.*$/ (_ k) k ]
; その他
[else => identity ] ))
; menu keyword ---> key変換器(class用)
;<>記号をつけないクラス
;もあるかもしれないが、そのときはそのときに適宜対応する。$
(define gauche-menu-key-converter-cls
(rxmatch-lambda
;
; 通常のエントリの処理
[#/^\s*(\S+)\s*$/ (_ k) (format #f "<~a>" k) ]
; refなどの重複するエントリの処理
[#/^\s*(\S+)\s*<[^>]+>.*$/ (_ k) (format #f "<~a>" k) ]
;
; その他
[else => identity ] ))
; menu keyword ---> key変換器(その他)
(define gauche-menu-key-converter
(rxmatch-lambda
; refなどの重複するエントリの処理
[#/^\s*(\S+)\s*<[^>]+>.*$/ (_ k) k ]
; その他
[else => identity ] ))
(define *info-node-names-source*
(alist->hash-table
`((function ,*index-node-source-function-jp* ,identity)
(variable ,*index-node-source-variable-jp* ,identity)
(class ,*index-node-source-class-jp* ,identity)
(module ,*index-node-source-module-jp* ,identity) ) ) )
(define *info-node-names-jp*
(alist->hash-table
`((function ,*index-node-function-jp* ,gauche-menu-key-converter-fn )
(variable ,*index-node-variable-jp* ,gauche-menu-key-converter )
(class ,*index-node-class-jp* ,gauche-menu-key-converter-cls )
(module ,*index-node-module-jp* ,gauche-menu-key-converter ) ) ) )
(define *info-node-names-en*
(alist->hash-table
`((function ,*index-node-function-en* ,gauche-menu-key-converter-fn )
(variable ,*index-node-variable-en* ,gauche-menu-key-converter )
(class ,*index-node-class-en* ,gauche-menu-key-converter-cls )
(module ,*index-node-module-en* ,gauche-menu-key-converter ) ) ) )
(define *info-node-names-dev-en*
(alist->hash-table
`((function ,*index-node-dev-function-en* ,gauche-menu-key-converter )
(type ,*index-node-dev-type-en* ,gauche-menu-key-converter )
(variable ,*index-node-dev-variable-en* ,gauche-menu-key-converter ) ) ) )
(define *info-node-names-gl-en*
(alist->hash-table
`((function ,*index-node-gl-function-en* ,gauche-menu-key-converter-fn )
(variable ,*index-node-gl-variable-en* ,gauche-menu-key-converter )
(class ,*index-node-gl-class-en* ,gauche-menu-key-converter-cls )
(module ,*index-node-gl-module-en* ,gauche-menu-key-converter ) ) ) )
;--------------------------------------
(define *info-src*
(alist->hash-table
`((default . refj) ; alias
(dev . deve) ; alias
(gl . gle) ; alias
;;
(ref refj refe)
(src ,*source* ,*info-node-names-source* )
(refj ,*info-file-jp* ,*info-node-names-jp* )
(refe ,*info-file-en* ,*info-node-names-en* )
(deve ,*info-file-dev-en* ,*info-node-names-dev-en*)
;;
(gle ,*info-file-gl-en* ,*info-node-names-gl-en*)
) ) )
;--------------------------------------------------------
; <info-node>のように見せるもの
(define-class <%node> []
[(name :init-keyword :name :init-value "")
(content :init-keyword :content :init-value "")
;;
(file :allocation :virtual :slot-ref (^[self] gauche-source ) )
;;
(next :init-keyword :next :init-value #f)
(prev :init-keyword :prev :init-value #f)
(up :init-keyowrd :up :init-value #f)
] )
;--------------------------------------------------------
; info-index-node的な挙動をするmoduleファインダ
(define-class <gauche-module-finder> (<dictionary> <singleton-mixin>)
[ (node :init-value (make <%node> :name "*module*" ) )
(*index* :init-value
(lazy-dict
(make-hash-table 'string=?)
(^t
(dict-for-each (force *lazy-modules-table*)
(^[k v]
(dict-put! t k `(,v) ) ) ) ) ) )
(index :allocation :virtual :slot-ref (^[self] ($ force $ ~ self '*index*) ) )
] )
(define-method initialize ((self <gauche-module-finder>) initargs)
(next-method)
)
(define gauche-module-finder (instance-of <gauche-module-finder> ) ) ; initializeの定義後に書くこと
; dictionary protocol
(define-method dict-get ((d <gauche-module-finder>) key :optional default)
(dict-get (~ d 'index) key default ) )
(define-method dict-put! ((d <gauche-module-finder>) key value)
(dict-put! (~ d 'index) key value) )
(define-method dict-exists? ((d <gauche-module-finder>) key)
(dict-exists? (~ d 'index) key ) )
(define-method dict-delete! ((d <gauche-module-finder>) key)
(dict-delete! (~ d 'index) key ) )
(define-method dict-fold ((d <gauche-module-finder>) proc seed)
(dict-fold (~ d 'index) proc seed))
(define-method call-with-iterator ((d <gauche-module-finder>) proc . keys)
(apply call-with-iterator (~ d 'index) proc keys) )
; key ---> node-name
(define-method ref ((obj <gauche-module-finder>) (key <string>))
(~ obj 'index key) )
;--------------------------------------------------------
; <cached-info-file>的な挙動をするソースブラウザ
(define-class <gauche-source> (<singleton-mixin>)
[ (name :init-value *source* )
(file :init-value #f )
(key-converter-table :init-value #f )
;;
(module :init-value gauche-module-finder )
(function :init-value #f )
(class :init-value #f )
(macro :init-value #f )
(variable :init-value #f )
] )
(define-method initialize ((self <gauche-source>) initargs)
;#?= "initialize ((self <gauche-source>)"
(next-method)
)
(define gauche-source (instance-of <gauche-source> ) ) ; initializeの定義後に書くこと
; refを定義する
; ソースの冒頭を取得する
(define (head-of-source path)
(call-with-input-file path
($ (cut string-join <> "\n" 'suffix )
$ generator->list $ gtake-while #/^\S/
$ port->line-generator $) ) )
; node-name ---> node or #f
(define-method ref ((obj <gauche-source>) (key <string>))
(rxmatch-case key
; 各種ファインダ
[ #/\*(\S+)\*/ (_ slot-name) ($ ~ obj $ string->symbol slot-name) ]
; ファインダで求めた。ここにはpath名がくる
[ else =>
(^ (path)
(make <%node> :name path
:content
(string-append
path "\n"
(head-of-source path) ) ) ) ]
) )
;--------------------------------------------------------
; <gauche-info-root>
; gaucheのinfoアクセスの元締め
(define-class <gauche-info-root> (<info-root> <singleton-mixin> ) () )
(define-method initialize ((root <gauche-info-root>) initargs)
(next-method) )
(define gauche-info-root (instance-of <gauche-info-root> *info-src* ) )
(define-method get-info-paths ((root <gauche-info-root>))
;#?=root
(let* ((syspath (next-method))
(instpath (list (gauche-config "--infodir")))
(in-place (list "../doc")))
;#?=syspath
;#?=instpath
;#?=in-place
(append syspath instpath in-place)))
; info-file-name ----> info
; ※ 一般の場合、key-converterテーブル参照は失敗するかもしれない
(define-method ref ((root <gauche-info-root>) (key <string>))
;#?= "ref ((root <gauche-info-root>) "
(rxmatch-case key
[ #/^\*source\*$/ ( _ ) gauche-source ]
[ else (next-method) ] ) )
;--------------------------------------------------------
; deftp文字列の処理。適切なデータがないなら#f
; [ カテゴリ 名前 記述 元の文字列]を返す。
; predで名前判定する
; (<string> -> x) <string> ---> [<string> <string> <string> <string>]
(define (process-deftp-string pred s)
(rxmatch-case s
; ( setter * )の処理
[#/^\s+--\s([^:]+):\s*\(setter\s*(\S+)\s*\)\s*(.*)$/ ( org cat name disc)
(if (pred name)
`( ,cat ,name
,(rxmatch-case disc
[#/^\s*$/ (_) #f ]
[else => (cut string-append "!setter! " <> ) ] ) ,org )
#f ) ]
; 通常の項目
[#/^\s+--\s([^:]+):\s*(\S+)\s*(.*)$/ ( org cat name disc)
(if (pred name)
`( ,cat ,name
,(rxmatch-case disc
[#/^\s*$/ (_) #f]
[else => identity] ) ,org )
#f) ]
[else #f]
) )
; deftp文字列リストの処理。適切なデータがないなら#fを返す
; [ [ カテゴリ 名前 記述 元の文字列] ... ]を返す。
; predで名前判定する
; (<string> -> x) [<string>] ---> [[<string> <string> <string>] ... ]
(define (process-deftp-string-list pred sl)
($ (if-listfn$
(pa$ filter-map (pa$ process-deftp-string pred) ) )
;$ tee print
$ append-map
(rxmatch-lambda
; ^cを展開する
[#/^(\s+--\sMacro:\s+\^)c(\s+.*)$/ (_ h t)
($ map (cut string-append h <> t)
$ cons "_" ; "^_" も追加する
$ map ($ string $ integer->char $ + (char->integer #\a) $) $ iota 26)]
; TAGvetorを展開する
[#/^(.*)TAG(vector.*)$/ (_ h t)
(map (cut string-append h <> t)
'("s8" "u8" "s16" "u16" "s32" "u32" "s64" "u64" "f16" "f32" "f64")) ]
[else => list ] )
sl) )
; deftpと説明部を列挙する
; deftp = [ カテゴリ 名前 記述 元の文字列]
; [ 冒頭部(string list) [ [deftp(string-list) 説明(string list)] ... ] , node-name type info-index ]
(define-method info-deftp&body-generator ( (root <gauche-info-root>) pred . rest )
($ gfilter-map
(match-lambda
[(node-name content . rest )
($ (pack$ (^(h b) (if b (cons* h b node-name rest) #f ))
($ car $)
($ filter-map
(^x (if-let1 v (process-deftp-string-list pred (car x) )
(cons v (cdr x))
#f ) )
$ (cut slices <> 2) $ cdr $) )
$ (cut group-sequence <> :key ($ not $ #/^\s+--\s.*:/ $) )
$ map (cut string-append <> "\n") ; tree->string で変換する用途のために行末に改行をつけておく
$ (cut string-split <> #\nl) content )
])
(apply info-content-generator root pred rest) ) )
(define (info-deftp&body-lseq . arg)
($ generator->lseq $ apply info-deftp&body-generator arg) )
; deftpの列挙
; deftp = [ カテゴリ 名前 記述 元の文字列]
; [ deftp(string list) , 説明(string list) , 冒頭部(string list) , node-name , type , info-index ]
(define-method info-deftp-generator ( (root <gauche-info-root>) pred . rest )
($ gconcatenate $ gmap (match-lambda
[(head deftp&body . rest )
($ x->generator $ append-map
(match-lambda
[(deftp body)
(map (cut cons* <> body head rest) deftp)])
deftp&body) ])
(apply info-deftp&body-generator root pred rest) ) )
(define-method info-deftp-lseq ( (root <gauche-info-root>) . arg)
($ generator->lseq $ apply info-deftp-generator root arg) )
; viewerでみるための文字列generatorを生成する
; 木構造になった、deftp見出しを巡回して、フィルタしながら変換
; predで名前判定する
(define (filter-map-nested-deftp$ pred)
(if-listfn$ ($ filter-map
(match-lambda
; 冒頭の文字列はそのまま残す
[(? string? s) s]
; Node
[( ( deftp-list . body ) . child-nodes)
(let [[deftp-all ($ (andfn$ (map$ (match-lambda [(_ _ _ org) org])) )
$ process-deftp-string-list (^_ #t) deftp-list)]
[deftp-filtered ($ (andfn$ (map$ (match-lambda [(_ _ _ org) org])) )
$ process-deftp-string-list pred deftp-list)]
[child-deftp ((filter-map-nested-deftp$ pred) child-nodes)]]
;#?=deftp-all
;#?=deftp-filtered
;#?=child-deftp
(cond
[ (and (not deftp-filtered) (not child-deftp)) #f]
[ (not child-deftp) (append deftp-filtered body ) ]
[ (not deftp-filtered) (append deftp-all body child-deftp ) ]
[ else (append deftp-filtered body child-deftp) ] ) )
] )
$ ) ) )
; p = 見出し前の空白でグループ化した列で
; ( (n deftp ... ) body (m deftp ) .... )
; これを、レベルを見て木構造にする。
(define (process-nested-deftp p)
(cond
[(null? p) p]
[(string? p) p]
[(pair? p)
(cond
[(string? (car p)) (cons (car p) (process-nested-deftp (cdr p)) ) ]
[(pair? (car p))
(receive (body d) (span string? (cdr p))
(let [[n (caar p)]
[node (cons (cdar p) body ) ] ]
(receive (h t) (span (any-pred string? ($ < n $ car $) ) d)
(cons
(cons node (process-nested-deftp h))
(process-nested-deftp t) ) ) ) ) ]
[else (errorf "??? ~a" (car p)) ] ) ]
[else (errorf "??? ~a" p) ] ) )
(define (info-content-string pred content)
($ tree->string
$ (filter-map-nested-deftp$ pred)
$ process-nested-deftp
;$ tee-exit
;$ pretty-print
$ map
(match-lambda
[ ( ( nn . s ) ... )
(let1 n (car nn)
(if n
(cons n s)
(string-concatenate s) ) ) ])
$ (cut group-sequence <> :key car )
$ map (pack$ cons
(rxmatch-lambda [#/^(\s+)--\s.*:/ (_ h) (string-length h)] [else #f])
(cut string-append <> "\n"))
$ (cut string-split <> #\nl) content ) )
(define-method info-string-generator ( (root <gauche-info-root>) pred . rest)
(gappend
; 関数・文法、変数 (funciton,variable)
($ gmap (match-lambda [( _ x . _ ) (info-content-string pred x ) ])
$ apply info-content-generator root pred
:type-filter (any-pred (pa$ eq? 'function) (pa$ eq? 'variable) )
rest )
; class,module
($ gmap (match-lambda [( _ x . _ ) x] )
$ apply info-content-generator root pred
:type-filter (any-pred (pa$ eq? 'class) (pa$ eq? 'module) )
rest )
; module ( source )
($ gmap (match-lambda [( _ x . _ ) x] )
$ info-content-generator root pred
:type-filter (any-pred (pa$ eq? 'module) )
:tag 'src)
) )
(define-method info-string-lseq ( (root <gauche-info-root>) pred . rest)
($ generator->lseq $ apply info-string-generator root pred rest) )
(define (info-node-function-jp ) (~ gauche-info-root *info-file-jp* *index-node-function-jp*))
(define (info-node-variable-jp ) (~ gauche-info-root *info-file-jp* *index-node-variable-jp*))
(define (info-node-class-jp ) (~ gauche-info-root *info-file-jp* *index-node-class-jp* ))
(define (info-node-module-jp ) (~ gauche-info-root *info-file-jp* *index-node-module-jp* ))
(define (info-node-function-en ) (~ gauche-info-root *info-file-en* *index-node-function-en*))
(define (info-node-variable-en ) (~ gauche-info-root *info-file-en* *index-node-variable-en*))
(define (info-node-class-en ) (~ gauche-info-root *info-file-en* *index-node-class-en* ))
(define (info-node-module-en ) (~ gauche-info-root *info-file-en* *index-node-module-en* ))
;;; info閲覧、日本語対応
;;; gaucheのinfo.scmを日本語対応にする
;;; Gaucheのinfo関数の表示を日本語にするには - 再帰の反復
;;; http://d.hatena.ne.jp/lemniscus/20100326/1269613137
;;; > lib/gauche/interactive/info.scmを変更する。ひとつは、
;;; > (define *info-file* "gauche-refe.info")
;;; > を
;;; > (define *info-file* "gauche-refj.info")
;;; > に変える。
;;; > もうひとつは、info関数の定義に出てくる文字列リテラル
;;; > 「"Function and Syntax Index"」を「"Index - 手続きと構文索引"」に変えて、
;;; > さらに適切にエンコードを指定する。
;;;
;;; interactive/info.scm - online helper
;;;
;;; Copyright (c) 2000-2012 Shiro Kawai <shiro@acm.org>
;;;
;;; Redistribution and use in source and binary forms, with or without
;;; modification, are permitted provided that the following conditions
;;; are met:
;;;
;;; 1. Redistributions of source code must retain the above copyright
;;; notice, this list of conditions and the following disclaimer.
;;;
;;; 2. Redistributions in binary form must reproduce the above copyright
;;; notice, this list of conditions and the following disclaimer in the
;;; documentation and/or other materials provided with the distribution.
;;;
;;; 3. Neither the name of the authors nor the names of its contributors
;;; may be used to endorse or promote products derived from this
;;; software without specific prior written permission.
;;;
;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
;;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
;;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;;
(define-module textj.view-infoj
(use gauche.dictionary)
;
(use textj.gauche-info)
(use komono-combinator)
(export
ofni
infoj infoe
modulegrep
infogrep infogrepe
)
)
(select-module textj.view-infoj)
;(format (standard-error-port) "view-infoj loaded\n")
(define viewer (viewer gauche-info-root))
(define-method infogrep ( (rx <regexp>) :optional (info-file-tag 'default) )
;#?=rx
($ (andfn$ viewer)
$ (^x
(if (pair? x)
(string-join x "\n")
#f ) )
(info-string-lseq
gauche-info-root
rx :tag info-file-tag ) ) )
(define-method infogrep ( (fn <string>) :optional (info-file-tag 'default))
;#?=fn
(let* [[fn (regexp-quote fn)]
[rx (string->regexp fn :case-fold #t )]
]
(infogrep rx info-file-tag) ))
(define-method infoj ( (fn <string>) :optional (info-file-tag 'default) )
;#?=fn
(rxmatch-case fn
;[ #/<(\S+)>/ (_ class-name ) (infoj class-name info-file-name ) ]
[ #/^(\S+)->$/ (_ from-what)
($ (cut infogrep <> info-file-name)
$ string->regexp $ format #f "^~a->\\S+$" $ regexp-quote from-what) ]
[ #/^->(\S+)$/ (_ to-what)
($ (cut infogrep <> info-file-name)
$ string->regexp $ format #f "^\\S+->~a$" $ regexp-quote to-what) ]
[ #/^-if$/ (_) (infogrep #/^\S+-if$/ info-file-name) ]
[ #/^if-$/ (_) (infogrep #/^if-\S+$/ info-file-name) ]
[ #/^-let1$/ (_) (infogrep #/^\S+let1$/ info-file-name) ]
[ #/^-let$/ (_) (infogrep #/^\S+-let\S+$/ info-file-name) ]
[ #/^do-$/ (_) (infogrep #/^do\S+$/ info-file-name) ]
[ #/^-filter$/ (_) (infogrep #/^\S+-filter[!]?$/ info-file-name) ]
[ #/^-map$/ (_) (infogrep #/^\S+-map[!]?$/ info-file-name) ]
[ #/^-map-accum$/ (_) (infogrep #/^\S*map-accum$/ info-file-name) ]
[ #/^-fold$/ (_) (infogrep #/^\S+-fold$/ info-file-name) ]
[ #/^-fold-right$/ (_) (infogrep #/^\S+-fold-right$/ info-file-name) ]
[ #/^-unfold$/ (_) (infogrep #/^\S+[-]?unfold.?$/ info-file-name) ]
[ #/^string-$/ (_) (infogrep #/^string-\S+$/ info-file-name) ]
[ #/^generator-$/ (_) (infogrep #/^generator-\S+$/ info-file-name) ]
[ else
(let* [[fn ($ format #f "^~a[0$*!]?$" $ regexp-quote fn)]
[rx (string->regexp fn :case-fold #t )]
]
(infogrep rx info-file-tag) ) ] ) )
(define-method infoj ( (fn <symbol>) . rest) (apply infoj (symbol->string fn) rest))
(define (infoe fn) (infoj fn 'refe))
(define (infogrepe p) (infogrep p 'refe))
;逆引きする
(define *lazy-ofni-hash* (make-lazy-ofni-hash gauche-info-root 'ref) )
(define-method ofni ( (rx <regexp>) )
($ (andfn$ viewer)
$ (if-stringfn$
(cut dict-fold <>
(^(k v s)
(if (rx k)
(string-append "\n" k "\n" (string-join v " , ") "\n" s )
s ) )
"" ))
$ force *lazy-ofni-hash*)
;;
(values))
(define-method ofni ( (str <string>) )
($ ofni $ (cut string->regexp <> :case-fold #t ) $ regexp-quote str) )
Filesystem utilities file.util Filtering file content file.filter , file-filter-map , file-filter-for-each , file-filter Loading Scheme file load-from-port , load , current-load-port , current-load-path , current-load-next , current-load-history , add-load-path , *load-path* Lock files with-lock-file , lock-file-name Profiler API profiler-stop , profiler-start , profiler-show , profiler-reset Other file operations sys-ttyname , sys-truncate , sys-pipe , sys-mkfifo , sys-isatty , sys-ftruncate , sys-chdir ....
6.15 ハッシュテーブル
=============================
-- Method: ref (ht <hash-table>) key :optional default
-- Method: (setter ref) (ht <hash-table>) key value
`hash-table-get'と`hash-table-put!'のメソッド版です。
6.18.2 万能アクセサ
-------------------------
-- Generic function: ref object key :optional args ...
-- Generic function: (setter ref) object key value
多くの集合型はこのジェネリックファンクションを特殊化し、
統一されたアクセス方法と変更方法を提供しています。
`ref'のオプショナル引数ARGSの意味はメソッド毎に異なりますが、
最初のオプショナル引数は、OBJECTのKEYに対する値が無い場合の
フォールバック値として使われるのが普通です。
正確な動作の定義は、`ref'メソッドを提供しているクラスごとに説明されています。
`~'の動作は次のコードで理解できるでしょう。
(define ~
(getter-with-setter
(case-lambda
[(obj selector) (ref obj selector)]
[(obj selector . more) (apply ~ (ref obj selector) more)])
(case-lambda
[(obj selector val) ((setter ref) obj selector val)]
[(obj selector selector2 . rest)
(apply (setter ~) (ref obj selector) selector2 rest)])))
(Gaucheは最適化のためにいくつかの型で短絡経路を使うこともあるので、
実際の実装とは異なります)
.....
9.31.1 ユニフォームベクタの基本操作
-------------------------------------------------
-- Function: make-u8vector LEN :OPTIONAL FILL
[SRFI-4]
長さLENのTAGvectorを作成して返します。各要素はFILLで
初期化されます。正確な整数のベクタに対しては、FILLは正確な整数でなければならず、
また有効な範囲内の値でなければなりません。
FILLが省略された場合、各要素の初期値は不定です。
(make-u8vector 4 0) => #u8(0 0 0 0)
9.13 `gauche.logger' - ユーザレベルのロギング
========================================================
-- Class: <log-drain>
ログメッセージの行き先を表現するオブジェクトです。
デフォルトのログの行き先として、グローバルな`<log-drain>'のインスタンスが
ひとつ作られます。
ログをいくつかにわけて出力する場合などは`make'メソッドを使って
いくつでも`<log-drain>'のインスタンスを作ることができます。
-- Instance Variable of <log-drain>: path
ログファイルのパス名か、`#t'、`#f'、あるいはシンボル`syslog'
の値を取ります。このスロットが`#t'の場合、ログメッセージは現在のエラーポートに
書き出されます。`#f'の場合は`log-format'は
ログを書き出すかわりにフォーマットされたログメッセージを文字列として返します。
シンボル`syslog'の場合はメッセージがシステムログへと送られます。
このスロットの初期値は`#f'です。
...
#!/usr/bin/env gosh
; /* -%- lang:scheme indent-width: 2; use-tabs: no; strip: yes -%-
(use gauche.parseopt)
(use textj.view-infoj)
(define (main args)
(let-args (cdr args)
[[ofni-mode "ofni"]
[ofni-mode-rx "ofnix"]
[module-mode "m"]
[module-mode-rx "mx"]
[grep-mode "g"]
[grep-mode-rx "gx"]
[else [opt . _ ] (print "不明なオプション : " opt) (exit) ]
. args]
(cond
[(null? args) (error "キーワードを指定すること")]
[ ofni-mode (ofni (car args))]
[ ofni-mode-rx (ofni ($ string->regexp $ car args))]
[ module-mode (modulegrep (car args))]
[ module-mode-rx (modulegrep ($ string->regexp $ car args))]
[ grep-mode (infogrep (car args))]
[ grep-mode-rx (infogrep ($ string->regexp $ car args))]
[ else (infoj (car args))] )
) 0 )
(※ gauche-classes、gauche-modulesのコードはGauche:モジュールの列挙にあります。)