Emacs Lisp Functions
≡ 목차 (Table of Contents)
이 글은 Emacs에서 사용하는 Emacs Lisp의 함수를 정리하는 노트다. 당연히 모든 것을 정리한 것은 아니고, 기회가 될 때 마다 추가하고 있다.
변수
setq
전역 변수를 생성한다.
(setq variable-name 100) (setq v1 1 v2 2 v3 3)
let
지역 변수를 생성한다.
(let (a b) ...)
초기값도 사용 가능하다.
(let ((a 1) (b 2) (c (generate-some-value))) ... body ...)
let*
지역 변수를 생성하는데 앞서 생성한 값을 생성하는데 참고할 수 있는 특수한 형태다.
(let* ((a 1) (b (+ a 2)) (c (/ b 3))) ... body ...)
리스트 관련
리스트 생성하기
(list 1 2 3 4) ;; (1 2 3 4) '(1 2 3 4) ;; (1 2 3 4)
순차적인 리스트는 number-sequence
를 이용해 생성할 수 있다.
(number-sequence 3) ;; (3) (number-sequence 2 5) ;; (2 3 4 5) (number-sequence 0 9 2) ;; (0 2 4 6 8)
아이템 꺼내오기
(car '("a" "b" "c")) ;; "a" (first '("a" "b" "c")) ;; "a" (nth 3 '("a" "b" "c" "d" "e")) ;; "d" (last '("a" "b" "c")) ;; ("c") (car (last '("a" "b" "c"))) ;; "c"
리스트 여분 구하기
(cdr '(1 2 3 4)) ;; (2 3 4) (rest '(1 2 3 4)) ;; (2 3 4) (butlast '(1 2 3 4)) ;; (1 2 3) (nthcdr 2 '(1 2 3 4)) ;; (3 4)
리스트 연장하기
(cons "a" '("b" "c")) ;; ("a" "b" "c") (cons '("a" "b") '("c" "d")) ;; (("a" "b") "c" "d") (append '("a" "b") '("c" "d")) ;; ("a" "b" "c" "d")
이 외에 nconc
도 append
와 비슷하게 사용할 수 있다.
(let ((some-list '(1 2 3))) (nconc some-list '(4)) some-list) ;; => (1 2 3 4)
다만 nconc
는 원본 변수의 값을 바꿔버리기 때문에 append
와는 다른 용도를 가지고 있다고 생각하자.
리스트 요소 다루기
(let ((lst '("b" "c"))) (push "a" lst) ;; lst -> ("a" "b" "c") (pop lst) ;; -> "a" ;; lst -> ("b" "c") )
문자열 관련
length: 길이
(length "abcd")
근데 length
는 다용도라 리스트 개수 세기 용으로도 사용된다.
concat: 이어 붙이기
문자열을 이어 붙일 때 사용한다.
(concat "hello" " " "world!") ;; -> "hello world!"
substring: 내부의 문자열 잘라서 얻기
(substring "abcde" 2 4) ;; -> "cd"
string-trim: 다듬기
문자열 좌우의 공백 문자(whitespaces)를 제거한다.
(string-trim " blah blah ") ;; -> "blah blah"
format: C 스타일 문자열 포맷
특정 포맷으로 문자열을 생성한다.
(format "I am %d age %s" 19 "old") ;; -> "I am 19 age old"
string-remove-prefix, string-remove-suffix
문자열 앞 혹은 뒤쪽의 특정 문자열을 잘라낸다.
(string-remove-prefix "aaa" "aaabbbccc") ;; -> "bbbccc" (string-remove-suffix "ccc" "aaabbbccc") ;; -> "aaabbb"
string-match and replace-match
문자열에서 일부분을 비교해서 위치를 반환한다. 정규표현식도 사용할 수 있다.
(string-match "bbb" "aaabbbccc") ;; -> 3
위 코드에 replace-match
를 이어서 사용할 수 있다.
(replace-match "BBB" nil nil "aaabbbccc") ;; -> aaaBBBccc
number-to-string: 숫자를 문자열로 변환하기
(number-to-string 3)
반대 용도로 string-to-number
도 있다.
split-string and string-join
split-string
은 문자열을 특정 문자열을 단위로 나눌 때 사용한다.
(split-string "my name is conrad" " ") ;; -> ("my" "name" "is" "conrad")
반대로 string-join
은 문자열 리스트를 하나의 문자열로 합친다.
(string-join '("my" "name" "is" "conrad") " ") ;; -> "my name is conrad"
조건문
if
(if (condition) (then-statement) (else-statement))
condition 값은 nil
혹은 ()
인 경우에만 False이고 나머지는 True이다.
then-statement 와 else-statement는 둘 다 함수 하나만 쓸 수 있게 되어있다. 만약 여러 프로시저를 넣고 싶다면 progn
으로 블록을 정의해서 써야한다.
(if (condition) (progn (statement 1) (statement 2)) (progn (statement 3) (statement 4)))
and, or, not 등은 함수로 쓸 수 있다.
(and cond1 cond2 ...) (or cond1 cond2 ...) (not (condition))
else 처리가 필요 없다면 좀 더 간단한 when
이나 unless
를 쓸 수도 있다.
(when (condition) (statement1) (statement2)) (unless (false-condition) (statement1) (statement2))
when
과 unless
는 progn
을 쓰지 않아도 여러 프로시저를 나열할 수 있다.
비교 함수들
(equal 10 10) ;; -> t (equal "str" "STR") ;; -> nil (equal '(1 2 3) '(1 2 3)) ;; -> t (equal 'symb 'symb) ;; -> t (> 10 1) ;; -> t (string= "abc" "ABC") ;; -> nil
타입 확인
(integerp 10) ;; -> t (floatp 3.14) ;; -> t
루프
while
(while (condition) (statement1) (statement2) ...)
함수형 언어 스타일 열거 함수
mapcar
리스트를 각 아이템을 특정 함수로 평가해서 리스트를 작성한다. 다른 언어에서 map 이라는 불리는 메서드와 거의 동일하다.
(defun make-double (x) (+ x x)) (mapcar #'make-double '(1 2 3 4 5)) ;; -> (2, 4, 6, 8, 10)
처리 함수가 공용이 아니라면 보통은 lambda 함수를 이용해 간단하게 구현하곤 한다.
(mapcar (lambda (x) (+ x x)) '(1 2 3 4 5)) ;; -> (2, 4, 6, 8, 10)
mapc
mapc
는 mapcar
와 비슷한데, 입력된 값을 그대로 반환하기 때문에 map 용도 보다는 그냥 for each에 가까운 용도로 사용한다.
(mapc (lambda (x) (+ x x)) '(1 2 3 4 5)) ;; => (1 2 3 4 5)
돌아오는 결과가 전혀 가공되지 않았음을 주의해서 보자.
mapconcat
리스트를 하나의 문자열로 합칠 때 사용한다.
(mapconcat #'identity '("hello" "world" "!") " ") ;; -> "hello world !"
위 예제에서 마지막 매개변수는 각 문자열이 합쳐 질 때 사이에 들어가는 문자열이다.
참고로 위 예제에서 identity
는 입력된 값을 그대로 돌려주는 함수다.
seq-filter
보통 다른 언어에서 filter라 부르는 메서드와 비슷한 용도의 함수다.
(require 'seq) (seq-filter (lambda (x) (= 0 (% x 2))) '(1 2 3 4 5 6)) ;; => (2 4 6)
내장 함수가 아니라 seq
라는 패키지에 들어있기 때문에 별도의 require가 필요하다는 것에 주의하자.
함수 형식
기본적인 함수 정의 방법
(defun function-name (param1 param2 ...) "documentation" ... body ...)
함수를 Emacs 커맨드로 쓰려면 interactive
를 선언해 주어야 한다.
(defun function-name (...) "documentation" (interactive) ;; <---- ... body ...)
옵셔널 매개 변수
(defun function-name (a b &optional c d) ;; ... )
위의 경우 a, b는 필수 매개 변수지만, c와 d는 넘기지 않아도 되며 이 경우 nil
이 값으로 들어온다.
버퍼 관련
char-after
(char-after 1)
goto-char
특정 위치로 커서를 옮긴다.
(goto-char (point-min)) ;; start of buffer (goto-char (point-max)) ;; end of buffer
insert
(insert "text")
generate-new-buffer
이름대로 버퍼를 생성한다.
(generate-new-buffer "buffer-name")
반환되는 값은 버퍼의 이름인데 꼭 지정된 이름과 일치하지는 않을 수도 있다.
switch-to-buffer
버퍼를 선택한다.
(switch-to-buffer (generate-new-buffer "some-buffer"))
with-current-buffer
현재 선택된 버퍼로 뭔가를 할 때 사용한다.
(with-current-buffer some-buffer (insert "sample text"))
with-temp-buffer
임시로 빈 버퍼를 만들어 뭔가 할 때 사용한다. 파일 내용을 읽어들일 때나 새로운 파일을 작성할 때 등등 의외로 자주 사용된다.
(with-temp-buffer (insert-file-contents "readme.txt") (insert "hello world!") (write-file "helloworld.txt"))
선택영역 관련
region-beginning and region-end
(goto-char (region-beginning)) (goto-char (regin-end))
커서 관련
파일/디렉토리 관련
expand-file-name: 완벽한 절대 경로 구하기
축약 경로를 절대 경로로 해석해 준다.
(expand-file-name "~/test.txt") ;; -> ex: /user/home/directory/test.txt
file-relative-name: 상대 경로 구하기
특정 경로를 기준으로 원하는 파일 경로의 상대 경로를 구한다.
(file-relative-name "/foo/bar/name" "./")
file-name-nondirectory: 경로에서 파일 이름 구하기
(file-name-nondirectory "/foo/bar/name.ext") ;; -> "name.ext"
file-name-directory: 경로에서 디렉터리만 구하기
(file-name-directory "/foo/bar/sample.txt") ;; -> "/foo/bar/"
file-name-sans-extension: 확장자 제거
파일 이름에서 확장자를 제거한다.
(file-name-sans-extension "sample.txt") ;; -> "sample"
file-name-as-directory: 디렉터리 경로 명확히 하기
(file-name-as-directory "/foo/bar") ;; -> "/foo/bar/"
끝에 /
가 붙었다는 것을 잘 보자.
file-expand-wildcards: 파일 목록 구하기
아래 커맨드는 ~/foo/bar
디렉터리 안의 모든 .org
파일 목록을 돌려준다.
(file-expand-wildcards "~/foo/bar/*.org")
file-exists-p: 파일 존재 여부 검사
파일이 존재하면 non-nil을 반환한다.
(when (file-exists-p "/foo/bar/file/name") (message "file exists!"))
체크섬(Checksum)
md5
(md5 "some-string")
이렇게 하면 MD5 해시를 문자열로 구할 수 있다.