横着プログラミング 第3回: 履歴マニア

最終更新日: 2002-05-18 (公開日: 2002-05-18)

Unix Magazine 誌に 2002年1月号から 2003年2月号にかけて連載し ていた記事の元の原稿です。


コンピュータの方がうまくできることに人間を使うな。
-- Tom Duff

*1 

1

使


Unix使 使 Unix

 csh  tcsh   zsh*2 使  zsh zsh 

 zsh Emacs   EDITOR vi  ~/.zshrc *3
bindkey -e   # Emacsと同じキー操作を行う

 Emacs  *4

1 C-p (up-line-or-history)  cpxp*5
% xp foo.txt /tmp
zsh: command not found: xp
% 

C-p 
% xp foo.txt /tmp

xpcp 1


C-p 10  C-p 10  C-r (history-incremental-search-backward) 使  diff   ``diff''   C-r dif4 C-p 10

zsh1
zsh2
zsh3
zsh4

 diff unimag.rd~ unimag.rd   C-r   ``dif'' 


 zsh   zsh    ~/.zshrc ~/.zsh-history  zsh 
HISTFILE=$HOME/.zsh-history           # 履歴をファイルに保存する
HISTSIZE=100000                       # メモリ内の履歴の数
SAVEHIST=100000                       # 保存される履歴の数
setopt extended_history               # 履歴ファイルに時刻を記録
function history-all { history -E 1 } # 全履歴の一覧を出力する

108 58,0001 240  1.9MB 

10 便*6C-r   grep  使  "find"  "tr" 
% history-all | grep find | grep tr


5603 13.6.2001 07:11 16:54 find . -depth -print | while read i; do mv $i `dirname $i`/`basename $i | tr A-Z a-z`; done

使 便  downcase-rename   ~/bin 

 CD-ROM  Unix   HTML   HTML


Unix  kterm   Tera Term*7   ()  1 便



zsh  ~/.zshrc   zsh 
setopt share_history

 ~/.zsh-history  ls1Enter  A B C-p 1 B Enter A


zsh  C-/  ()   M-d (kill-word)  *8 C-/ C-/

使


zsh zsh


 <tab> 

zsh1
zsh2



zsh
zstyle ':completion:*:default' menu select=1

 ~/.zshrc   C-n C-p C-f C-b   <tab> 1 zstylezsh zsh

zsh


Unix使 ls, cp, mv   downcase-rename 15 使 down <tab> 5  <tab> 

zsh1
zsh2


zsh gcc  cvs  zsh  ~/.zshrc 
autoload -U compinit
compinit

 gcc -funroll-loops  使g cc<space> - fun<tab> <tab> l <tab> 

zshgcc1
zshgcc2
zshgcc3
zshgcc4
zshgcc5


zsh  rm **/*(x.)  M-q  zsh   ``zsh for the working researcher'' *9 

Emacs


 Emacs 


Emacs  C-<space>   C-w (kill-region)   M-w (kill-ring-save)   kill-ring  kill-ring 

kill-ring C-y (yank) 




C-y  M-y (yank-pop) 1 M-y  kill-ring  zsh C-p   M-y 

  kill-summary.el *10  使 M-x kill-summary  kill-ring  便 *11kill-summary 使 kill-summary.el  *12  ~/.emacs 
(autoload 'kill-summary "kill-summary" nil t)

kill-summary.el

1  kill-ring   C-s 


C-x C-f (find-file)   file-name-history  *13  M-p 1

M-p    minibuf-isearch *14  使C-r   zsh  C-r 

minibuf-isearch
minibuf-isearch
minibuf-isearch

minibuf-isearch 使 minibuf-isearch.el   ~/.emacs 
(require 'minibuf-isearch)

 M-% (query-replace) 使 minibuf-isearch 


Christoph Wedler session.el *15 使 Emacskill-ring  file-name-history   Emacs  session.el  ~/.emacs 
(require 'session)
(add-hook 'after-init-hook 'session-initialize)


Emacs  zsh  C-/  ( ) C-/   C-g   C-/ 

使


Windows 使 使

Windows使

Emacs  David Ponce recentf.el*16  使File  Open Recent 使

Open Recent

recentf.el  Emacs 21 ~/.emacs  使
(recentf-mode)

 M-x recentf-open-files 


Emacs  dabbrev  C  ``real_pathname'' r e alM-/ (dabbrev-expand)   ``real''  ``real_pathname'' 

: 
: M-x 

 dabbrev   Migemo  *17

Ruby


Ruby*18  irb (interactive ruby) irb使 Ruby 使調 便 1.7   Enumerable#inject 使  irb  Enumerable#inject 使
% irb
irb(main):002:0> (1..10).inject(0) {|x,y| x + y}
55

 irb  Ruby便 irb  irb irb-history.rb *19  使irb irb-history.rb   *20  ~/.irbrc  ~/.irb-history 
require "irb-history"


require "irb/completion"

Ruby沿 便 [1,2,3].rev  <tab>   [1,2,3].reverse irb   readline  C-p 1 C-r  C-/ 

: Unix使


Unix 使  open   recentf.c   Red Hat Linux 7.2 (glibc 2.2.4 + gcc 2.96)  OS
  /*
   * システムコール open(2) を横取りして「最近使ったファイル」
   * の履歴を取る実験 (Red Hat Linux 7.2 で動作確認)
   */
  #include <time.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include <limits.h>
  #include <sys/stat.h>
  #include <sys/syscall.h>
  
  static char *
  date (void)
  {
      static char datestr[BUFSIZ];
      time_t t;
      struct tm *tm;
  
      time(&t);
      tm = localtime(&t);
      strftime(datestr, BUFSIZ, "%Y-%m-%d %H:%M:%S", tm);
      return datestr;
  }
  
  static void
  do_logging (const char *pathname)
  {
      FILE *fp;
      char log_filename[PATH_MAX];
      char *user;
  
      user = getenv("USER");
      if (user) {
          sprintf(log_filename, "/tmp/%s-recentf", user);
          fp = fopen(log_filename, "a");
          if (fp) {
              fprintf(fp, "%s: %s\n", date(), pathname);
              fclose(fp);
              chmod(log_filename, 0600);
          }
      }
  }
  
  static int
  under_home_p (const char *pathname)
  {
      char *home, real_home[PATH_MAX];
      int homelen, pathlen;
  
      home = getenv("HOME");
      if (home) {
          realpath(home, real_home);
          homelen= strlen(real_home);
          pathlen = strlen(pathname);
          if (pathlen > homelen && strncmp(real_home, pathname, homelen) == 0) {
              return 1;
          } else {
              return 0;
          }
      } else {
          return 0;
      }
  }
  
  int 
  open (const char *pathname, int flags, mode_t mode)
  {
      char real_pathname[PATH_MAX];
  
      realpath(pathname, real_pathname);
      if (under_home_p(real_pathname)) {
          do_logging(real_pathname);
      }
      return syscall(SYS_open, pathname, flags, mode);
  }
  
  int __open(const char *, int, mode_t) 
      __attribute__((weak, alias("open")));
  int __libc_open(const char *, int, mode_t) 
      __attribute__((weak, alias("open")));
  int open64(const char *, int, mode_t) 
      __attribute__((weak, alias("open")));
  int __libc_open64(const char *, int, mode_t) 
      __attribute__((weak, alias("open")));

recentf.c 
% gcc -shared -o recentf.so recentf.c

 zsh 使 LD_PRELOAD open recentf.so 
% export LD_PRELOAD=$PWD/recentf.so

 /tmp/$USER-recentf*21  使  tail 使10
2002-01-17 17:20:17: /home/satoru/tmp/recentf.c
2002-01-17 17:20:50: /home/satoru/tmp/Makefile


recentf.c  ~/  open  使

 emacs lisp   ~/share/emacs/site-lisp emacs   ~/share/emacs/site-lisp  使使


Unix

*22 


稿zsh 

: 




使 調 !!  Emacs 

*23 
専門知識はあるとないでは大変な違いである。専門知識がないばか
りにとんでもない損をしている人々はたくさんいる。だからといっ
て、そういう人たちのところへ行って、ストレートにそれじゃだめ
です、こうやるべきなんですよ、といってみたところで何にもなら
ない。これはコンピュータのような技術の進歩の速い分野の知識・
技能を身につけた若者が陥りやすい落とし穴である。訳者自身過去
には、そこのところを完全に誤解していて、いろいろ失敗をした。


参考文献


Satoru Takabayashi


*1Jon Bentley
*2<http://www.zsh.org/>
*3~/.zshrc   .zshrc  /home/satoru/.zshrc
*4bindkey -e  compinit  compinit bindkey -e 
*5 C-p  Ctrl p
*61
*7http://hp.vector.co.jp/authors/VA002416/teraterm.html
*8M-d  Alt d
*9<http://cl.aist-nara.ac.jp/student/daiti-m/text/zsh-intro.html>
*10<http://mibai.tec.u-ryukyu.ac.jp/~oshiro/Programs/elisp/kill-summary.el>
*11M-x kill-summary  Alt x  kill-summary  Enter
*12M-x describe-variable load-path   site-lisp   /usr/local/share/emacs/site-lisp
*13Emacs
*14<http://sodan.org/~knagano/emacs/minibuf-isearch/>
*15<http://www.fmi.uni-passau.de/~wedler/session/>
*16<http://perso.wanadoo.fr/david.ponce/more-elisp.html>
*17
*18<http://www.ruby-lang.org/>
*19<http://arika.org/memo.cgi?cmd=view;name=irb-history.rb>
*20ruby -rrbconfig -e 'puts Config::CONFIG["sitelibdir"]' 
*21$USER   USER echo $USER 
*22<http://0xcc.net/unimag/>
*23