eval, eval, eval

init file을 쓰담쓰담 하다 보면 변경 사항을 반영해야 한다. 이왕이면 바로 반영됐으면 좋겠다. 수정하고 emacs 다시 실행해서 반영했는지 확인하고 다시 수정하고. 이렇게 수정하기는 싫다. 괴로워.

M-x load-file <RET> ~/.emacs.d/init.el
M-x eval-buffer

load-file(<RET>는 엔터를 치라는 뜻), eval-buffer전체를 평가(evaluation)할 수 있다. 지금은 간단히 실행한다는 의미로만 이해하고 넘어가도록 한다. 이후 평가라는 단어 대신 eval을 사용할 것이다. 그냥 평가라고 하면 다른 뜻으로도 혼동할 수 있어서 영어 병기를 해야 하는데, 귀찮아서.

M-x eval-last-sexp

기본 키바인딩은 C-x C-e이다. sexpeval한다. 일부분만 변경됐는데, 전체를 eval할 필요가 있겠나. 변경된 부분만 eval해서 결과를 확인할 수 있다. minibuffer에 리턴값을 출력한다.

M-x eval-print-last-sexp

기본 키바인딩은 C-j이다. 리턴값을 다음 행에 출력하는 것 빼고는 eval-last-sexp와 같다.

C-h f *eval

eval 명령을 내리는 다른 함수도 있을까? 찾아보면 엄청 많다.

eval-last-sexp

sexp는 뭐지? sex가 들어간 단어 같지만 실은 symbolic expression 약자다. 다음에 더 자세히 보도록 하고 지금은 간단히 emacs에서 eval할 수 있는 elisp 코드 유닛이라고 생각하자. 괄호로 감싼 표현식이거나 괄호가 없는 atom이다. 지금 더 자세히 알고 싶다면 Lisp 이해하기1 - taesoo emacsbook을 참고.

(menu-bar-mode -1)

init.el을 열고 타이핑 한다.

커서를 ) 오른쪽으로 움직여 C-x C-e를 누르면 메뉴바가 사라진다. -1t로 바꾸고 C-x C-e를 누르면 메뉴바가 나온다.

만약 커서를 )에 두고 C-x C-e를 누르면? minibuffer에 -1이 나온다. 즉, eval-last-sexp는 커서 위치를 기준으로 sexp를 찾아서 eval하는 함수다.

커서 위치를 기준으로 어떻게?

C-h f eval-last-sexp

Evaluate sexp before point; print value in minibuffer.

도움말을 보면 point라는 용어가 나온다. 텍스트 삽입 위치를 point라고 부른다.

cursor 대신 point를 사용했을까? 난 emacs가 기본으로 뚱뚱한 커서(block cursor)를 사용했기 때문이라고 생각한다. 만약 날씬한 vertical bar를 사용했다면 cursor라는 용어를 그대로 사용해도 헷갈리지 않았을 것이다.

위에 (menu-bar-mode -1)에서 커서를 )에 두고 입력하면 ) 앞에 문자가 들어간다. 그래서 point 이전 sexp이므로 -1eval된다.

어떻게 사용?

수정하고 저장. M-x load-file 또는 M-x eval-buffer로 다시 로드해 제대로 반영됐는지 확인. 이렇게 하지 말자.

수정한다. C-x C-eeval. 제대로 반영되는지 확인. 아니면 다시 수정해서 eval. 이런 빠른 이터이션을 마음껏 즐기자. 원래 lisp가 이렇다.

왜 init file이라고 할까?

설정을 담아 놓는다면 init file 보다는 configuration file이라고 부르는 게 적절하다. 왜 이런 용어를 선택했을까? 설정을 위한 데이터 포맷이 있고 그걸 읽어 설정하는 게 아니다. emacs에서는 함수 호출이 설정이다.

이렇게 생각하면 명확해진다. 초기화 파일이다. emacs를 실행하면 제일 먼저 읽어서 eval하는 파일이다. 그래서 init file이다.

C-x C-s C-x C-c


Feedback plz <3 @ohyecloudy, ohyecloudy@gmail.com