Home > Archives > 2007年01月

2007年01月

リージョンを シェルコマンドの実行結果で置換3

整理してこんな形になった.まだ微妙にあやしいけどそのうちちゃんと elisp を勉強しよう.

(defun filter-command-region (start end command)
  "Filter region by a command. 
The region is passed to the command as input.
The region is overwritten by the result."
  (interactive (perfom-command-region-interactive-func
		"Shell command on region (filtering): "))
  (perform-command-region-general start end command nil nil t))
 
(defun perform-command-region (start end command) 
  "Perform a command on region.
The region is passed to the command as input.
The region remains on top of the result."
  (interactive (perfom-command-region-interactive-func
		"Shell command on region: "))
  (perform-command-region-general start end command nil nil nil))
 
(defun perform-command-region-comment (start end command)
  "Perform a command on comment-region.
The region is uncommented and then passed to the command as input.
The comment-region remains on top of the result."
  (interactive (perfom-command-region-interactive-func
		"Shell command on commented region: "))
  (perform-command-region-general start end command t nil nil))
 
(defun perfom-command-region-interactive-func (msg)
"A general interaction function for perform-command-region-general..."
  (let (string)
    (unless (mark)
      (error "The mark is not set now, so there is no region"))
    ;; Do this before calling region-beginning
    ;; and region-end, in case subprocess output
    ;; relocates them while we are in the minibuffer.
    (setq string (read-from-minibuffer msg
				       nil nil nil
				       'shell-command-history))
    ;; call-interactively recognizes region-beginning and
    ;; region-end specially, leaving them in the history.
    (list (region-beginning) (region-end)  string)))
;;
;; perform a command on region.
;;
(defun perform-command-region-general (start end command uncomment comment overwrite)
  "A general function to perform a command on region.
uncomment: Set t to uncomment the region before passing it to the command. 
comment  : Set t to comment-out the region after the command. 
overwrite: Set t to overwrite the region with the result of the command. 
           Otherwise the original region remains on top of the result.
"
  (let ((swap (< start end)) (exit-status))
    (if (not overwrite)
	(let ()
	  (kill-region start end)
	  (setq sp (point-marker))
	  (yank nil)
	  (setq ep (point-marker)))
      (let ()
	(goto-char start)
	(setq sp (point-marker))
	(goto-char end)	
	(setq ep (point-marker))))
    ;; uncomment the region
    (and uncomment (uncomment-region (marker-position sp) (marker-position ep))
    (goto-char (marker-position sp))	  
    (setq exit-status
	  ;; see describe-function
	  ;; error output is marged into standard output
	  (call-process-region (marker-position sp) (marker-position ep) shell-file-name t
			       (list t t)
			       nil shell-command-switch command))
    ;; swap the point and mark if necessary
    (and swap (goto-char (marker-position sp)))
    ;; yank the original contents
    (if (not overwrite)
	(let ()
	  (setq p1 (point-marker))
	  (yank nil) 	
	  (setq p2 (point-marker))
	  (and comment (comment-region (marker-position p1) (marker-position p2)))
	  (setq p1 nil)
	  (setq p2 nil)
	  )) 
    (setq sp nil)
    (setq ep nil)
    exit-status))
;;
;; Key bindings
;;
(defun filter-command-region-keybindings ()
  "Set up default key bindings for filter-command-region, ..."
  (interactive)
  (define-key global-map [(control ?!)] 'filter-command-region)
  (define-key global-map [(control meta ?#)] 'perform-command-region)
  (define-key global-map [(control meta ?!)] 'perform-command-region-comment))

リージョンを シェルコマンドの実行結果で置換

vi の ! コマンドに対応するコマンドを shell-command-on-region を簡略化して作ってみる.キモは call-process-region という組み込み関数.

;; replace specified region with output of 
;; a shell command against the content of the regon
(defun filter-command-region (start end command)
  (interactive 
   (let (string)
     (unless (mark)
       (error "The mark is not set now, so there is no region"))
     ;; Do this before calling region-beginning
     ;; and region-end, in case subprocess output
     ;; relocates them while we are in the minibuffer.
     (setq string (read-from-minibuffer "Shell command on region: "
					nil nil nil
					'shell-command-history))
     ;; call-interactively recognizes region-beginning and
     ;; region-end specially, leaving them in the history.
     (list (region-beginning) (region-end)  string)))
  (let (exit-status)
    ;; Replace specified region with output from command.
    (let ((swap (< start end)))
      (goto-char start)
      (push-mark (point) 'nomsg)
      (setq exit-status
	    ;; see describe-function
	    ;; error output is marged into standard output
	    (call-process-region start end shell-file-name t
				 (list t t)
				 nil shell-command-switch command))
      ;; swap the point and mark if necessary
      (and swap (exchange-point-and-mark)))
    exit-status))
(define-key global-map [(control ?!)] 'filter-command-region)

shell-command-on-region が M-! なので C-! で使えるようにしてみた.元のリージョンを上書きせずにコメントしてくれるほうが使いやすいかも…

リージョンを シェルコマンドの実行結果で置換2

ついでなので,元のリージョンの内容を出力の上部にコメントとして出力するものも作った.

(defun perform-command-region (start end command)
  (interactive 
   (let (string)
     (unless (mark)
       (error "The mark is not set now, so there is no region"))
     ;; Do this before calling region-beginning
     ;; and region-end, in case subprocess output
     ;; relocates them while we are in the minibuffer.
     (setq string (read-from-minibuffer "Shell command on region: "
					nil nil nil
					'shell-command-history))
     ;; call-interactively recognizes region-beginning and
     ;; region-end specially, leaving them in the history.
     (list (region-beginning) (region-end)  string)))
  (let (exit-status)
    ;; Replace specified region with output from command.
    (let ((swap (< start end)))
      (goto-char start)
      (kill-region start end)
      (yank)
      (push-mark (point) 'nomsg)
      (setq exit-status
	    ;; see describe-function
	    ;; error output is marged into standard output
	    (call-process-region start end shell-file-name t
				 (list t t)
				 nil shell-command-switch command))
      ;; swap the point and mark if necessary
      (and swap (exchange-point-and-mark))
      ;; mark current position
      (setq p1 (point-marker))
      (set-marker-insertion-type p1 nil)
      ;; yank the original contents
      (yank nil) 
      (setq p2 (point-marker)) 
      ;; comment the yanked contents
      (comment-region (marker-position p1) (marker-position p2))
      (setq p1 nil)
      (setq p1 nil))
    exit-status))
(define-key global-map [(control meta ?!)] 'perform-command-region)

そして C-M-! で発動すると.これって comment-region がない場合にどうなるんだろう?

Emacs Lisp の関数定義を探す

describe-function というコマンドで見つかるらしい.

ps2pdf でなく ps2pdf14 を使う

dvipsk と ps2pdf を使って dvi -> ps -> pdf と変換してたらいつの間にか”無効なフォント「MS-Mincho-H」が文書から削除されました”みたいなことを Acrobat が文句たれるようになっていた.この文句がでると文章全体がゴシック体になってしまうらしく困ってたのだが,ps2pdf14 を使って作成する PDF のバージョンを変えたら文句を吐かれないと分かった.何が違うんだろう?

Home > Archives > 2007年01月

Search
Feeds

Page Top