다음 이전 차례

5. Delete와 Backspace

Delete와 Backspace 키가 제대로 동작하도록 하는 것이 그리 간단한 문제는 아니다. 특히 콘솔, X, bash, emacs, 원격 로그인 등 여러가지가 혼합된 환경에서는 더더욱 그러하다. 아마도 사용자가 원하는 바를 정확히 수행하도록 관계된 프로그램 모두에게 전달하려면 여러개의 환경설정화일을 편집해야 될지도 모른다. 한편으로는 키가 발생시키는 코드가 무엇인지도 (그리고 kermit이나 emacs등에서 이러한 코드가 어떤 규칙으로 다시 매핑되는지도) 문제가 되고, 다른 한편으로는 각 코드에 연결된 기능이 무엇인지도 문제가 된다.

사람들이 종종 `백스페이스 키가 작동하지 않는다.'고 불평하는데, 이것은 마치 이 키에 `이전의 문자를 지우는' 내장된 기능이 있는 것처럼 말하는 것이다. 하지만 불행히도 이 키가 하는 일이라곤 코드 하나를 발생하는 것뿐이며, 커널 tty 드라이버와 모든 어플리케이션 프로그램이 백스페이스 키가 실제로 `이전 문자를 지우는' 동작을 하도록 설정되어 있기를 고대하는 것이 전부이다.

모든 유닉스 프로그램은 `요리된' 모드에서 커널 tty 드라이버를 통해 tty 입력을 받고, 단순한 stty 명령이 삭제 문자를 결정한다. 하지만 bashemacs, X 같은 프로그램은 독자적으로 입력을 다루며 하나씩 올바로 동작하는지 확인해야 한다.

5.1 유닉스에서 직전 문자를 지우는데 사용할 문자를 지정하는 방법

        % stty erase ^?
글자가 지워지긴 하지만 이상한 방법으로 지워진다면 사용자의 tty 설정에 뭔가 잘못된 것이 있는 것이다. echoprt가 설정되어 있다면 지워진 문자는 \/로 둘러싸여진다. echoe가 설정되어 있지 않으면 삭제 문자가 화면에 찍힐 것이다. (#과 같이 화면에 표시되는 문자인 경우라면 당연하다고 생각할 것이다.) 보통의 경우는 stty echoe -echoprt 상태를 원한다. stty sane이라고 하면 이런 상태가 되며, 그 이외에도 몇가지를 더 설정한다. stty -a라고 명령을 내리면 현재 설정 상태를 화면에 보여준다. 사용자가 올바른 getty를 사용하면 디폴트로 적절한 상태로 되어 있다.

bashemacs 등등 많은 프로그램이 독자적인 키바인딩을 가지고 있음에 유의하라. (~/.inputrc, ~/.emacs 등에 정의되어 있다.) 이런 프로그램들은 삭제 문자 설정등에는 영향을 받지 않는다.

표준 유닉스 tty 드라이버는 (화살표 같은) 키를 커서의 현재 위치를 이동하는 뜻으로 인식하지 않는다. 따라서 `현재 문자 삭제' 명령도 없다. 하지만 콘솔상의 bash에서 아래와 같이

        set editing-mode emacs
        "\e[3~":delete-char
~/.inputrc에 넣어주면 Delete 키를 인식하도록 할 수 있다.

`DEL과 BS가 잘 작동하던 Getty가 지금은 깨져있는 것인가?'

옛날에는 콘솔 드라이버가 DEL (\177)를 받으면 BS Space BS (\010\040\010)를 수행하도록 해두었다. 하지만 지금은 DEL은 무시된다. (이것이 당연한 것이 드라이버는 vt100을 흉내내기 때문이다.) DEL을 출력하지 않는 최신의 getty를 구해서 사용하라.

`첫번째 로그인 시도와 두번째 로그인 시도가 좀 다른것 같다. 이것이 정상인가?'

첫번째 로그인 시도는 getty와 이야기하는 것이지만, 두번째 시도는 login과 이야기하는 것이다. 서로 다른 프로그램이다.

5.2 리눅스에서 키를 누를 때 발생하는 코드를 지정하는 방법

콘솔에서, 정확히 말하자면 raw 모드가 아닌 경우에는

        % loadkeys mykeys.map
이라고 하면 된다. X 환경에서는
        % xmodmap mykeys.xmap
를 사용하면 된다. (XFree86-2.1 이래로) X는 처음 시작시에 X keymap을 초기화할 때, 리눅스 keymap 설정을 읽는다는 사실에 유의하라. 비록 두 시스템이 100% 호환되지는 않지만 이러한 사실은 많은 경우에 xmodmap이 보다 영향력이 있다는 것을 의미하기 때문이다.

예를 들어, 사용자가 백스페이스 키에 BackSpace (^H, 8진수 010)을 보내도록 하려 하고, 회색 Delete 키로는 DEL (8진수로 0177)을 보내려 한다면, /etc/rc.local (또는 사용자만의 부팅 설정화일에)

        /usr/bin/loadkeys << EOF
        keycode 14 = BackSpace
        keycode 111 = Delete
        EOF
라고 첨가하면 된다. 이 설정은 다른 설정을 바꾸지 않았다면 두개의 키 설정만 바꾼다는 사실에 유의할 필요가 있다. (다른 키맵에서도 키 설정을 바꾸고 싶다면, 어느 키맵을 바꿀지 키맵 라인을 지정해 주어야 한다.) 리눅스 커널은 디폴트로 Ctrl-Backspace 키가 BackSpace를 발생하도록 되어 있다. 이것은 때때로 DEL 코드만 생기는 위급 상황에서 빠져나가는데 유용하다.

왼쪽 Alt 키는 종종 메타키라고 부른다. 디폴트로 왼쪽 Alt-X 키조합은 MetaX로 설정되어 있다. 그렇다면 MetaX는 어떤 키 시퀀스인가? 그것은 (각각의 tty에서) 메타 플래그에 의해서 결정된다. 이것은 setmetamode 명령으로 설정할 수 있다. ESC X를 치는 것과 0200과 OR연산을 한 X를 치는 두가지 방법이 존재한다.

`왜 디폴트로 백스페이스 키가 BackSpace를 발생하도록 하지 않았나?'

(i) 왜냐하면 VT100에는 Delete 키가 Enter 키 위에 있었기 때문이다.

(ii) 또한 리누스가 그렇게 정했기 때문이다.

5.3 X에서 Delete와 백스페이스를 바꾸는 방법

        % xmodmap -e "keysym BackSpace = Delete" -e "keysym Delete = BackSpace"
백스페이스 키가 BackSpace를 발생하도록 하려면
        % xmodmap -e "keycode 22 = BackSpace"
Delete 키가 Delete를 발생하도록 하려면
        % xmodmap -e "keycode 107 = Delete"
(하지만 보통 이미 디폴트로 되어 있을 것이다.)

5.4 emacs에서 Delete나 Backspace에 대한 동작 지정하는 방법

사용자의 .emacs 화일에 다음 라인을 추가하면 된다.

        (global-set-key "\?" 'help-command)
        (global-set-key "\C-h" 'delete-backward-char)
물론 이런 방식으로 하면 다른 키에도 명령을 연결시킬 수 있다. 키 재정의 방식에는 여러가지 major 및 minor 방식이 있음을 유의할 필요가 있다. 예를 들어, incremental search 모드에서는 다음과 같은 코드가 있는 것을 발견할 수 있다.
        (define-key map "\177" 'isearch-delete-char)
        (define-key map "\C-h" 'isearch-mode-help)
이것을 보면 위의 두 명령을 global 키 설정으로 사용하는 것은 별로 좋은 방법이 아니라는 것을 알 수 있다. 많은 프로그램에서 ^H = help와 DEL = delete라는 가정하에 키를 사용한다. 물론 반드시 백스페이스 키가 DEL을 발생하도록 키를 설정해야만 하는 것은 아니다. 그러나 키 설정이 이렇게 되어 있지 않으면 emacs에서 사용할 수 있는 가장 낮은 레벨에서는 이 키들을 재설정하는 것이 가장 쉬운 방법이다.

5.5 emacs에서 Delete와 Backspace를 바꾸는 방법

사용자의 .emacs 화일에 다음 라인을 추가하면 된다.

        (setq keyboard-translate-table (make-string 128 0))
        (let ((i 0))
          (while (< i 128)
            (aset keyboard-translate-table i i)
            (setq i (1+ i))))
        (aset keyboard-translate-table ?\b ?\^?)
        (aset keyboard-translate-table ?\^? ?\b)
emacs의 최신 버전에서는 keyboard-translate 함수를 제공하기 때문에 간단하게 아래와 같이 해도 된다.
        (keyboard-translate ?\C-h ?\C-?)
        (keyboard-translate ?\C-? ?\C-h)
X 환경에서는 (콘솔에서 이 키가 어떤 코드를 만들던 간에) emacs가 Ctrl-h와 백스페이스 키를 구별할 수 있다. 그리고 emacs는 디폴트로 백스페이스 키를 DEL로 간주할 것이다. (물론 ^H에 연결된 도움말 기능이 아니라 문자를 지우는 일을 할 것이다.) 백스페이스와 Delete를 구분하여 사용하려면 다음과 같이 하면 된다.
        (global-unset-key [backspace] )
        (global-set-key [backspace] 'delete-backward-char)
        (global-unset-key [delete] )
        (global-set-key [delete] 'delete-char)

5.6 kermit에서 Delete와 Backspace를 바꾸는 방법

.kermrc 화일에 다음 라인을 추가하면 된다.

        set key \127 \8
        set key \8 \127

5.7 xterm에서 입맛에 맞는 tty 모드 설정하는 방법

보통 xterm은 이것을 호출한 프로그램의 tty 모드를 상속받는다. xdm 환경에서는 구형 유닉스 버전 6에서와 같이 디폴트로 설정된 지우기 및 죽이기 문자는 #@이다. 이 설정이 마음에 안들면 아래 내용을 /usr/lib/X11/app-defaults/XTerm$HOME/.Xresources에 넣으면 된다.

        XTerm*ttymodes: erase ^? kill ^U intr ^C quit ^\ eof ^D \ 
                        susp ^Z start ^Q stop ^S eol ^@
물론 $HOME/.xinitrc$HOME/.xsession
        xrdb $HOME/.Xresources
라는 구절이 있어야 작동한다.

5.8 xmosaic에서 Backspace 키가 DEL을 발생하도록 설정하는 방법

아래 내용을 $HOME/.Xresources에 넣으면 해결될 것이다.

        *XmText.translations: #override\n\
           <Key>osfDelete: delete-previous-character()
        *XmTextField.translations: #override\n\
           <Key>osfDelete: delete-previous-character()

하지만 넷스케이프 FAQ에는 다음과 같은 내용이 있다.

        왜 텍스트 필드에서 백스페이스 키가 말을 듣지 않는가?
        디폴트로 리눅스와 XFree86에는 백스페이스와 Delete 키가 잘못 설정되어
        있다. (넷스케이프 네비게이터를 포함한) 모든 모티프 프로그램에서
        똑같이 잘못 작동될 것이다.

        모티프 스펙에 보면 백스페이스는 이전 문자를 지우도록 되어 있고
        Delete는 다음 문자를 지우도록 되어 있다. 리눅스와 XFree86은
        백스페이스와 Delete 키가 모두 Delete를 발생하도록 설정되어 있다.

        사용자는 xmodmap, xkeycaps, loadkeys중 하나를 사용하여 문제의
        키가 Delete 대신에 BackSpace keysym을 발생하도록 할 수 있다.

        다른 방법으로는 .motifbind 화일을 만들어 해결할 수 있다. man 페이지
        VirtualBindings(3)을 참조하라.

        주의: 이 문제를 해결하기위해 *XmText.translations나
        *XmTextField.translations 리소스 화일을 사용하지 않는 것이 좋다.
        아마도 이것을 건드리면 넷스케이프 네비게이터의 다른 텍스트 필드의
        키 연결이 모두 망가질 것이다.

5.9 넷스케이프와 같이 모티프를 사용하는 프로그램의 더 좋은 해결책

Ted Kandell (ted@tcg.net)의 해결책은 다음과 같다.

사용자의 .profile 화일에 다음의 내용을 넣자.

stty erase ^H
bash 사용자라면 .inputrc에 다음 라인을 추가한다.
"\C-?": delete-char
"\C-h": backward-delete-char
.xinitrc 화일에는 아래의 내용을 추가한다.
xmodmap <<-EOF
keycode 22  =  BackSpace osfBackSpace
keycode 107 =  Delete
EOF

# 윈도우 관리자를 실행시킨다.
#(fvwm) 2>&1 | tee /dev/tty /dev/console

stty sane
stty erase ^H
loadmap <<-EOF
keycode 14  = BackSpace
keycode 111 = Delete
EOF

이렇게 하면 리눅스/XFree86 기반의 PC 101 또는 102 키보드에서는 반드시 잘 동작할 것이다.

넷스케이프와 같은 모티프 프로그램이 잘 동작하도록 하는데 중요한 부분은 osfBackSpace를 BackSpace와 함께 키코드 22에 넣는 점이다.

= 기호 양쪽에는 반드시 공백이 있어야 한다는 점도 유의할 것.

5.10 termcap와 terminfo는 뭐지?

사용자들이 백스페이스 문제에 부딪히면, 대개 터미널이 사용하는 termcap (또는 terminfo) 항목을 뒤적거린다. 물론 거기에 보면 kb (또는 kbs)라는 항목이 있고, 백스페이스 키가 만드는 코드에 대한 설명이 나온다. 하지만 그다지 많은 프로그램이 이것을 사용하는 것은 아니다. 따라서 만일 특정한 프로그램에서만 문제가 발생한다면 아마도 원인은 다른곳에 있을 가능성이 높다. 물론 termcap (terminfo) 항목을 고쳐서 문제를 해결하는 것도 좋은 생각이다. 뒤에 "TERM 변수" 부분을 참조하면 도움이 될 것이다.


다음 이전 차례