テキストブラウザ #6

前回(id:smeghead:20070825:ncurses2)の続き

ファイヤープロジェクト

http://www.fireproject.jp/

ここのサイトのの情報って幅広さと濃さが凄いですね。かなり前から色々な言語でお世話になっています。

matsuさんという方が個人で作成しているらしいです。頭が下がりますm(_ _)m

パッド

パッドを使用すると論理画面にまとめて表示データを格納しておいて,必要な分だけ物理画面で表示することが可能になる.しかも簡単に.

http://www.fireproject.jp/feature/c-language/curses/pad.html#2

以前、仮想画面と勘違いしていたのはパッドでした。ということでパッドを試してみました。

今回は、上のサイトで紹介されている「なんちゃってless」をcommon lispで書いてみました。

  • オリジナルのなんちゃってlessから変更した点
    • w3mのようにカーソルがある点
    • キーバインドをw3m風に(といってもhjklqしか作ってません)
curses-wrapper.lisp

継ぎ接ぎだらけですがここに置いてみました。

追加したマクロ

(defmacro with-pad (pad-name initial-proc &body body)
`(progn
(setq ,pad-name ,initial-proc)
,@body
(delwin ,pad-name)))
less.lisp
(load "/usr/lib/clisp/asdf.lisp")
(setf asdf:*central-registry*
'(*default-pathname-defaults*
#p"/usr/lib/clisp/system/"))
(asdf:oos 'asdf:load-op :cffi :verbose nil)
(load "curses-wrapper.lisp")
(use-package :curses-wrapper)
(defun get-contents (file-name)
(with-open-file (stream file-name :direction :input)
(loop for line = (read-line stream nil 'eof)
until (equal line 'eof)
collect line)))
(defun setup-pad (contents)
(let ((pad-y 0)
(pad-x 0))
(loop for line in contents
for i from 0
do (mvwprintw *stdpad* i 0 line))
(defun pad-down ()
(if (and (eql (getcury *stdscr*) (1- *LINES*))
(< (+ pad-y *LINES*) (getmaxy *stdpad*)))
(prefresh *stdpad* (incf pad-y) pad-x 0 0 (1- *LINES*) (1- *COLS*))
(wmove *stdscr* (1+ (getcury *stdscr*)) (getcurx *stdscr*))))
(defun pad-up ()
(if (and (eql (getcury *stdscr*) 0)
(> pad-y 0))
(prefresh *stdpad* (decf pad-y) pad-x 0 0 (1- *LINES*) (1- *COLS*))
(wmove *stdscr* (1- (getcury *stdscr*)) (getcurx *stdscr*))))
(defun pad-left ()
(if (and (eql (getcurx *stdscr*) 0)
(> pad-x 0))
(prefresh *stdpad* pad-y (decf pad-x) 0 0 (1- *LINES*) (1- *COLS*))
(wmove *stdscr* (getcury *stdscr*) (1- (getcurx *stdscr*)))))
(defun pad-right ()
(if (and (eql (getcurx *stdscr*) (1- *COLS*))
(< (+ pad-x *COLS*) (getmaxx *stdpad*)))
(prefresh *stdpad* pad-y (incf pad-x) 0 0 (1- *LINES*) (1- *COLS*))
(wmove *stdscr* (getcury *stdscr*) (1+ (getcurx *stdscr*)))))))
(defun main (args)
(if (not args)
(format *error-output* "Usage: clisp less.lisp filename~%")
(progn
(let ((contents (get-contents (car args))))
(with-curses
(cbreak)
(noecho)
(scrollok *stdscr* FALSE)
(with-pad *stdpad* (newpad (length contents)
(loop for line in contents
maximize (length line)))
(setup-pad contents)
(refresh)
(prefresh *stdpad* 0 0 0 0 (1- *LINES*) (1- *COLS*))
(input-loop key
(((char-code #\q) (char-code #\Q)) (return))
((char-code #\h) (pad-left))
((char-code #\j) (pad-down))
((char-code #\k) (pad-up))
((char-code #\l) (pad-right)))))))))
(main *args*)

いろいろ試すいい機会なので、マクロとかクロージャも積極的に使う方向でやってみています。

でも大域変数使いすぎで汚ないです;;ncursesプログラミングはこんなもんなのかな?

実行方法

$ clisp less.lisp <text file name>

感想

パッドは便利。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


The reCAPTCHA verification period has expired. Please reload the page.

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください