TortoiseSVN의 설치 디렉토리\bin에 포함된 TortoiseProc.exe를 사용하면, 커맨드 프롬프트 혹은 타 스크립트 언어에서 TortoiseSVN의 특정 기능을 실행하는 것이 가능하다.


1. 로그 보기

TortoiseProc /command:log /path:"작업 디렉토리 경로"


2. Commit


TortoiseProc /command:commit /path:"작업 디렉토리 경로" /logmsg:"기본 commit 메세지"


3. Update

TortoiseProc /command:update /path:"작업 디렉토리 경로" /closeonend:1


(/closeonend:1 옵션은 에러가 없을 경우, 해당 다이얼로그창을 자동으로 닫는다.)




이 외에도 더 많은 기능들이 실행 가능하지만, 자세한 내용은 Help 파일의 Automating TortoiseSVN 파트를 참고하도록 하자.

테스트 버전 : TortoiseSVN 1.8.11

,

Common Lisp에서 List, Array, Vector, String, Sequence 차이점

List
 - 순차적 접근 가능.

Array
 - 임의의 접근 가능.
 - 여러 차원도 가능.
 - 기본적으로 고정 사이즈이지만, 제한된 범위 내에서 사이즈를 변경하거나(:fill-pointer), 제한 없이 사이즈를 변경할 수 있는(:adjustable) 옵션을 줄 수 있다.

Vector
 - Array 중 1차원 Array.

String
 - Vector 중 character를 구성 요소로 하는 Vector

Sequence
 - List, Vector의 상위 개념


List의 생성

(list a b c)
-> (a b c)

'(a b c)
-> (a b c)

(cons a '(b c))
-> (a b c)



Vector의 생성

(vector 1 2 3)
-> #(1 2 3)

#(1 2 3)
-> #(1 2 3)

(make-array 3 :initial-element 1)
-> #(1 1 1)



,

Vector 정의 방법

(defparameter some-array (make-array 4 :initial-element 1)) ; 길이가 4이고 1로 초기화



IF NOT 구문


(unless A B C D)


; (if (not A) (progn B C D)) 와 동일



NOT vs. NULL


: 동작 상으로 동일 (nil 값인지 여부를 체크)


(not T)

-> NIL


(not nil)

-> T


(not '())
-> T

(not 10) ; 10은 nil 값이 아니므로

-> NIL



DO 구문 사용


;; 사용법 :

(do ((변수명 초기값 다음값_계산식)) (종료조건1 종료조건2 ..)) ; 모든 종료 조건을 만족해야 종료 (AND 연산)
    실행구문1
    실행구문2
    ..
)

(do ((i 0 (+ i 1))) ((>= i 100)) ; => for (i = 0; i < 100; i++) 과 동일

)



DOLIST 구문 사용하여 리스트 순회하기


(dolist (x '(1 2 3 4))
    (print x)
)
-> 1
2
3
4
NIL


(dolist (x '(1 2 3 4))
    (print x)
    (if (= x 2) (return)) ; return 문을 사용하여 루프를 빠져나올 수 있음
)
-> 1

2

NIL



키보드 입력 받기


(read-line)



,

Common Lisp 문자열 관련 함수 사용법을 정리해보았습니다



문자열 자르기 & 치환

; 문자열 자르기
(subseq "abcdef" 2)
-> "cdef"

(subseq "abcdef" 0 2)
-> "ab"

; 문자열 치환
(defparameter str (string "abcdef"))
(setf (subseq str 0 2) "AB")
str
-> "ABcdef"

; 치환시 변경 전의 길이보다 변경 후의 부분이 더 길 경우, 변경 전의 길이만큼만 바뀐다. (늘어나지 않음)
(defparameter str (string "abcdef"))
(setf (subseq str 0 2) "ABC")
str
-> "ABcdef"

(setf (subseq "abcdef" 0 2) "AB") ; (X) 변수에 대해서만 사용가능하다

(setq (subseq str 0 2) "ABC") ; (X) setq가 아닌 setf만 가능함에 유의



문자열 결함

; 문자열 결합
(concatenate 'string "abc" "def") ; 문자열로 결합
-> "abcdef"

(concatenate 'list "abc" "def") ; 문자의 리스트로 결합
-> (#\a #\b #\c #\d #\e #\f)

; 문자열 포매팅
(format nil "this is ~A" '(a b c))
-> "this is (A B C)"


(format nil "this is ~{ ~A~}" '("abc" "def" "ghi"))
-> "this is  abc def ghi"



개별 문자 처리

; 개별 문자 얻기
(char "abcdef" 2)
-> #\c

; 개별 문자 치환
(defparameter str (string "abcdef"))
(setf (char str 5) #\g)
str
-> "abcdeg"

; 문자 -> 코드 변환
(char-code #\a)
-> 97

; 코드 -> 문자 변환
(code-char 97)
-> #\a



개별 문자 나열

; 한번에 한 문자씩 처리 : 익명 함수를 통해 직접 처리하는 방법
(map 'string #'(lambda (c) (print c)) "abcde")
-> #\a
#\b
#\c
#\d
#\e
"abcde"
 
; 한번에 한 문자씩 처리 : loop를 사용하여 문자 리스트를 얻어 처리하는 방법
(loop for char across "abcde" collect char)
-> (#\a #\b #\c #\d #\e)



문자 제거

; 특정 문자 제거
(remove #\b "abcdef")
-> "acdef"


(remove #\b "bbbbbb1" :start 2) ; 인덱스 2 이후 문자를 대상으로
-> "bb1"



; 특정 조건을 만족하는 문자 제거
(remove-if #'upper-case-p "AbCdEf") ; 대문자 제거
-> "bdf"

; 특정 문자 대체 (뒤엣것으로 앞엣것을 대체)
(substitute #\z #\a "abcdefga")
-> "zbcdefgz"

; 특정 조건을 만족하는 문자 대체
(substitute #\Z #'upper-case-p "AbCdEf")
-> "ZbZdZf"

; 특정 구간만큼 대체
(replace "abcdef" "12345" :end1 3) ; 인덱스 3 앞의 문자를 대상으로
-> "123def"



문자열, 문자 사이의 변환

; 길이가 1인 문자열 -> 문자
(coerce "a" 'character)
-> #\a

(coerce "ab" 'character) ; 길이가 1이 아닐 때 쓰면 에러 발생!

; 길이가 1이 넘는 문자열 -> 문자 리스트
(coerce "abc" 'list)
-> (#\a #\b #\c)

; 길이가 1인 문자열 <- 문자
(string #\a)
-> "a"

; 길이가 1이 넘는 문자열 <- 문자
(coerce '(#\a #\b #\c) 'string) ; 리스트로부터 생성
-> "abc"


(coerce #(#\a #\b #\c) 'string) ; array로부터 생성 (1)
-> "abc"


(defparameter some-array (make-array 4 :initial-element #\a)) ; array로부터 생성 (2)
(coerce some-array 'string)
-> "aaaa"



; [참고] array 정의 방법
(defparameter some-array (make-array 4 :initial-element #\a)) ; 길이가 4이고 a로 초기화



기타 처리

; 문자열 뒤집기
(reverse (string "abcde"))
-> "edcba"

; 대소문자 변환
(string-upcase "abcde")
-> "ABCDE"
(string-downcase "ABCDE")
-> "abcde"
(string-capitalize "abcde")
-> "Abcde"

; 문자열 트림 : 첫번째 파라미터의 문자들을 두번째 파라미터 끝에서부터 제거한다
(string-trim " " " abc def ")
-> "abc def"
(string-trim " ac" " abc abc ")
-> "bc ab"
(string-left-trim " ac" " abc abc ") ; 왼쪽에서부터 제거
-> "bc abc "
(string-right-trim " ac" " abc abc ") ; 오른쪽에서부터 제거
-> " abc ab
(string-right-trim '(#\Space #\a #\c) " abc abc ") ; 첫번째 파라미터로 문자열 대신 리스트 사용
-> " abc ab"



심볼 관련

; 문자열 -> 심볼(변수명 등) 변환
; - 단지 변환하는 것이 아닌 해당 심볼이 패키지에 존재하지 않을 경우 추가된다.
(intern "SOME-SYMBOL")

; 심볼 -> 문자열 변환
; - 심볼 존재 유무에 상관없이 동작
(symbol-name 'SOME-SYMBOL)
-> "SOME-SYMBOL"



문자 검색

; 문자 검색 후 발견한 문자 반환

(find #\t "The quick onyx goblin jumps over the lazy dwarf." :test #'equal) ; 대소문자 구별하여 검색
-> #\t


(find #\Z "The quick onyx goblin jumps over the lazy dwarf." :test #'equal) ; 미발견시
-> NIL

(find #\Z "The quick onyx goblin jumps over the lazy dwarf." :test #'equalp) ; 대소문자 구별 없이 검색
-> #\z


; 특정 함수를 만족시키는 문자 검색하여 문자 반환
; (digit-char-p : 문자가 숫자를 나타내는 문자인지 체크하는 함수)

(find-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890") ;
-> #\1

(find-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890" :from-end t) ; 뒤에서부터 검색
-> #\0


; 문자 검색 후 발견한 위치 반환

(position #\t "The quick onyx goblin jumps over the lazy dwarf." :test #'equal) ; 대소문자 구별하여 검색
-> 33

(position #\t "The quick onyx goblin jumps over the lazy dwarf." :test #'equalp) ; 대소문자 구별 없이 검색
-> 0



; 특정 함수를 만족시키는 문자 검색하여 위치를 반환

(position-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890")
-> 49

(position-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890" :from-end t) ; 뒤에서부터 검색
-> 58


; 문자 검색 후 발견한 갯수 반환

(count #\t "The quick onyx goblin jumps over the lazy dwarf." :test #'equal) ; 대소문자 구별하여 검색
-> 1


(count #\t "The quick onyx goblin jumps over the lazy dwarf." :test #'equalp) ; 대소문자 구별 없이 검색
-> 2



; 특정 함수를 만족시키는 문자 검색하여 갯수를 반환

(count-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890")
-> 10

(count-if #'digit-char-p "The quick onyx goblin jumps over the lazy dwarf. 1234567890" :start 51) ; 특정 위치에서부터 검색
-> 5



문자열 검색

; 기본 검색
(search "the" "the quick onyx goblin jumps over the lazy dwarf.")
-> 0

; 뒤에서부터 검색
(search "the" "the quick onyx goblin jumps over the lazy dwarf." :from-end t)
-> 33

; 시작 위치를 지정하여 검색
(search "the" "the quick onyx goblin jumps over the lazy dwarf." :start2 4)
-> 33

; 뒤에서부터 시작 위치를 지정하여 검색
(search "the" "the quick onyx goblin jumps over the lazy dwarf." :end2 10 :from-end t)
-> 0

; 미발견시
(search "JUMPS" "the quick onyx goblin jumps over the lazy dwarf.")
-> NIL

; 특정 함수를 만족시키는 문자열 검색
(search "JUMPS" "the quick onyx goblin jumps over the lazy dwarf." :test #'char-equal) ; 대소문자 구별없이 문자 비교
-> 22



문자열, 숫자  사이의 변환


문자열 -> 숫자 변환 (PARSE-INTEGER 사용)
 - 두번째 리턴값은 parsing이 멈춘 위치

 - "#X23"과 같은 기수 표기법은 사용 불가

(parse-integer "37")
-> 37
2

(parse-integer "37" :start 1) ; 시작 위치를 지정
-> 7
2

(parse-integer "37" :end 1) ; 종료 위치를 지정
-> 3
1

(parse-integer "37" :radix 8) ; 진수를 지정
-> 31
2

(parse-integer " 37 ") ; space가 포함되도 괜찮다
-> 37
4

(parse-integer " 37 is thirty-seven" :junk-allowed t) ; space 외 다른 문자가 포함되는 것을 허용할 경우
-> 37
3


(parse-integer " 37 is thirty-seven") ; space 외 다른 문자를 허용하지 않을 경우
-> junk in string " 37 is thirty-seven" (에러 발생!)


문자열 -> 숫자 변화 (READ-FROM-STRING 사용)

 - 역시 두번째 리턴값은 parsing이 멈춘 위치
 - 기수 표기법은 물론 커맨드 라인에서 가능한 모든 표현이 가능
 - 심지어 문자열 안에서 함수를 실행 후 그 결과값을 사용할 수도 있다.

(read-from-string "#X23") ; 8진수 표현
-> 35
4

(read-from-string "4.5") ; 소수점
-> 4.5
3

(read-from-string "6/8") ; 분수
-> 3/4
3

(read-from-string "#C(6/8 1)") ; 복소수 (실수부 + 허수부)
-> #C(3/4 1)
9

(read-from-string "1.2e2") ; 지수 표기법
-> 120.00001
5

(defparameter a-symbol 34)
(read-from-string "a-symbol")
-> A-SYMBOL
8

(defparameter a-symbol 34)
(read-from-string "#.a-symbol") ; 변수의 실제값을 사용
-> 34
10

(read-from-string "#.(+ 1 2)") ; 함수 호출 결과값을 사용
-> 3
9


숫자 -> 문자열 변환

(write-to-string 250)
-> "250"

(write-to-string 250.02)
-> "250.02"

(write-to-string 250 :base 16) ; 16진수로
-> "FA"

(write-to-string (/ 1 3)) ; 유리수
-> "1/3"



문자열 비교

(string= "Abcd" "Abcd") ; 대소문자 구별하여 비교
-> T


(string= "Abcd" "abcd")
-> NIL


(string-equal "Abcd" "abcd") ; 대소문자 구별하지 않고 비교
-> T

(string< "aaaa" "aaab") ; "aaaa"가 "aaab"보다 작을 경우 달라지는 인덱스를 반환. 그렇지 않을 경우, NIL을 반환
-> 3

(string< "aaab" "aaaa")
-> NIL

(string-lessp "AAAA" "aaab") ; string<와 대소문자 구별을 하지 않는다는 점만 빼고 같음
-> 3

(mismatch "abcde" "bbcde" :test #'char=) ; char= 함수를 만족하지 않는 인덱스를 반환
-> 0

(mismatch "abcde" "abdde" :from-end t :test #'char=) ; 뒤에서부터 비교하여 char= 함수를 만족하지 않는 인덱스를 반환 (주의 : 0번째 문자에서 달라질 경우 1을 반환)
-> 3



참고 : http://cl-cookbook.sourceforge.net/strings.html의 내용을 바탕으로 작성했습니다.


,

유용한 .emacs 설정

폰트 변경 방법

  1. M-x를 누른 후, set-default-font를 입력한다.
  2. tab을 두번 누르면, 폰트 리스트가 뜬다. (여기서 선택을 할 경우, 해당 폰트가 적용되면서 어떻게 표시되는지 확인할 수는 있지만 설정이 저장되지는 않는다)
  3. 원하는 폰트에 대한 스트링을 기억해둔다.
  4. .emacs 파일에 아래와 같은 형식으로 따옴표 안에 기억했던 폰트에 대한 스트링을 넣어 추가한다.
    (set-default-font
    "-outline-Ubuntu Mono-normal-normal-normal-mono-*-*-*-*-c-*-iso10646-1")
    

아스키 코드로 입력 방법 / 개행 문자 입력 방법

  1. 아스키 코드로 입력하기 : C-q <8진수 숫자>
  2. (검색 등에서) 개행 문자 입력하기 : C-j 혹은 C-q C-j
    • replace-string 명령 파라미터 입력시 C-j를 사용하면 바로 입력이 종료되기 때문에 중간에 개행문자가 끼어있는 파라미터 입력시는 C-q C-j를 사용해야 한다.
<테스트 환경>
- OS : Windows 7
- Emacs 버전 : Emacs 24.3 윈도우
,

SBCL 소스를 커맨드 프롬프트에서 스크립트처럼 실행 시에, 특수 변수 *posix-argv*를 사용하여 실행 파라미터(인자)를 리스트의 형태로 가져올 수 있다.


아래와 같이 example.lisp을 작성한다.

(print *posix-argv*)


실행 파라미터를 주어 실행해보면, 

sbcl --script example.lisp enter your argument


("sbcl" "enter" "your" "argument")


첫번째 요소로 SBCL 실행 파일명을 가지며, 나머지에 실행 파라미터가 포함된 리스트가 출력되는 것을 볼 수 있다.




<테스트 환경>

OS : Windows 7

SBCL 버전 : 1.2.7


,

1. UTF-8 한글 표시 설정


  1. .emacs 파일에 다음의 내용을 추가한다.
    (set-language-environment "Korean")
    (prefer-coding-system 'utf-8)
    
  1. 하지만 이렇게만 할 경우, 버퍼의 내용은 제대로 표시되지만, 한글로 된 파일명을 가진 파일을 읽을 때, 파일명이 같은 형식으로 표시되거나, 새로 한글로 된 파일명을 입력하여 저장할 때, 제대로 저장이 되지 않는 등의 문제가 있다. 파일명을 위한 인코딩 설정을 위해 .emacs 파일에 아래의 내용을 추가한다.
    (set-file-name-coding-system 'cp949-dos)
    


2. Shift-Space 키에 의한 한영 변환 기능을 제거


윈도우 환경 Emacs에서는 Shift-Space, 한영키 둘 다에 의해 한영 변환을 지원하지만, 가끔씩 상태가 꼬여서 불편한 사태가 발생하게 된다.


.emacs 파일에 다음 내용을 추가하면 Shift-Space 키에 의한 한영 변환 기능을 제거할 수 있다.


  • [추가] 하지만 이렇게 하더라도 C-s를 눌러서 들어가는 Search buffer로 들어가면 Shift-Space에 의한 변환이 동작한다. 그러므로 상태바에 한2 이런 표시가 보이면 Search buffer로 냉큼 들어가서 Shift-Space를 누르면 원래대로 돌아온다
(global-unset-key (kbd "S-SPC"))


혹은 Shift-Space 키를 다른 기능으로 설정할 수도 있다.

(global-set-key (kbd "S-SPC") 'other-window) ; 다른 창으로 이동 기능으로 설정


키에 설정된 기능을 확인하려면, M-x를 누르고 describe-key를 입력 후 해당 키를 누르거나, M-x를 누르고 describe-bindings를 눌러 전체 설정 내역을 확인할 수 있다.



참고 사이트

<테스트 환경>
- OS : Windows 10
- Emacs 버전 : Emacs 24.5.1 윈도우용
,

SBCL에서 디렉토리 내의 파일/디렉토리 리스트를 가져오는 방법입니다. (sb-posix, sb-grovel을 사용한 방법)


1. 디렉토리 리스트 가져오기


(require :sb-posix)
(require :sb-grovel)

(defun is-directory (pathname) ; 주어진 경로가 디렉토리인지 체크한다
  (ignore-errors
    (sb-posix:s-isdir (sb-posix:stat-mode (sb-posix:lstat pathname)))
    )
  )

(defun get-directory-contents (pathname) ; 주어진 경로 내의 모든 디렉토리/파일 리스트를 얻는다
  (let ((dir (sb-posix:opendir pathname)))
    (prog1
      (loop for dirent = (sb-posix:readdir dir)
           until (sb-grovel::foreign-nullp dirent)
           unless (or (equal (sb-posix:dirent-name dirent) ".")
                      (equal (sb-posix:dirent-name dirent) ".."))
           collect (concatenate 'string pathname "/"
                                (sb-posix:dirent-name dirent)))
      (sb-posix:closedir dir))
    )
  )

(defun get-dirs (dir) ; 주어진 경로 내의 모든 디렉토리 리스트를 얻는다 (get-directory-contents의 결과 중 디렉토리가 아닌 항목을 제거한다)
  (remove-if-not #'is-directory (get-directory-contents dir))
  )


(defparameter dir-list nil)

(setq dir-list (get-dirs ".")) ; 현재 디렉토리 내의 디렉토리를 가져와 DIR-LIST에 저장한다


(dolist (dir dir-list) ; DIR-LIST의 내용을 출력한다
  (print dir)
  )




2. 파일 리스트 가져오기


(require :sb-posix)
(require :sb-grovel)

(defun is-directory (pathname) ; 주어진 경로가 디렉토리인지 체크한다
  (ignore-errors
    (sb-posix:s-isdir (sb-posix:stat-mode (sb-posix:lstat pathname)))
    )
  )

(defun get-directory-contents (pathname) ; 주어진 경로 내의 모든 디렉토리/파일 리스트를 얻는다
  (let ((dir (sb-posix:opendir pathname)))
    (prog1
      (loop for dirent = (sb-posix:readdir dir)
           until (sb-grovel::foreign-nullp dirent)
           unless (or (equal (sb-posix:dirent-name dirent) ".")
                      (equal (sb-posix:dirent-name dirent) ".."))
           collect (concatenate 'string pathname "/"
                                (sb-posix:dirent-name dirent)))
      (sb-posix:closedir dir))
    )
  )

(defun get-dirs (dir) ; 주어진 경로 내의 모든 디렉토리 리스트를 얻는다 (get-directory-contents의 결과 중 디렉토리가 아닌 항목을 제거한다)
  (remove-if-not #'is-directory (get-directory-contents dir))
  )

(defun get-files (dir) ; 주어진 경로 내의 모든 파일 리스트를 얻는다 (get-directory-contents의 결과 중 디렉토리인 항목을 제거한다)
  (remove-if #'is-directory (get-directory-contents dir))
  )

(defparameter file-list nil)

(setq file-list (get-files ".")) ; 현재 디렉토리 내의 파일 리스트를 가져와 FILE-LIST에 저장한다


(dolist (file-item file-list) ; FILE-LIST의 내용을 출력한다
  (print file-item)
  )




<테스트 환경>

OS : Windows 7

Emacs 버전 : Emacs 24.3 윈도우용

SBCL 버전 : 1.2.7

Slime 버전 : 2.21


,