레이블이 build인 게시물을 표시합니다. 모든 게시물 표시
레이블이 build인 게시물을 표시합니다. 모든 게시물 표시

2009년 5월 11일 월요일

emacs 특정 path 아래파일을 열경우 flymake 적용하기

이전글에 썼던 코드들에 내용 추가

flymake 가 있으면 킹왕짱 좋지만 설정은 좀 귀찮은 놈이라 몇몇 프로젝트에만 설정해놓고 쓰는데(cmakeflymake 붙이기가 쉽지 않아서 자주 안쓰게 되더라 이거 빨리 적절한 방법을 찾아봐야 하는데...) 이러다 보니 수작업이 좀 들어가야 해서 잠시 남는시간에 관련 코드를 좀 추가했다.

결론적으로 추가된 함수는 요거 하나가 핵심이고
(defmacro yoonkn-enable-flymake-mode (pattern hook)
"hook 에 pattern 을 검사해서 통과한 경우에만 flymake-mode 를 켜는 함수를 추가한다.

사용예:
(yoonkn-enable-flymake-mode \"\\`/home/yoonkn/scratch/hehehehe/mao\" 'c-mode-common-hook)"

`(add-hook ,hook '(lambda ()
(let ((path (buffer-file-name)))
(when (and path (string-match ,pattern path))
(flymake-mode-on))))))

내가 평소에 쓰던 defproject/yoonkn 에서 한방에 적용이 가능하도록 적용하고싶은 모드들은 인자로 추가했다.
(defmacro defproject/yoonkn (name root builddir buildcmd &optional flymake-enable-modes)
"per-directory 로컬변수 세팅이 반복되는 작업이라 매크로를 만들었다.

사용예:
(defproject/yoonkn 'mao \"~/scratch/hehehehe/mao\" \"~/tmp/mao\" \"make \" '(c-mode-common-hook))
(defproject/yoonkn 'boost \"~/scratch/boost\" \"~/tmp/boost\" \"make \")
"

`(progn
(define-project-bindings ,name
'((nil . ((yoonkn-build-option . ((build-directory . ,builddir)
(build-command . ,buildcmd)))))))
(set-directory-project ,root ,name)
;; flymake-enable-modes 가 지정된경우 각각의 모드마다 후킹함수 추가
(loop for mode in ,flymake-enable-modes
collect (yoonkn-enable-flymake-mode (expand-file-name ,root) mode))))

이제 기존에 줄줄이 잡아놓고 쓰던 defproject/yoonkn 들에 원하는 모드를 추가하만 하면 해당 디렉토리의 파일들을 열때 flymake 켜고 뜨게된다. 물론 flymake 세팅은 따로 잡아줘야 하지만.. 뭐 Makefile 하나 정도 추가하는 작업이라 큰작업은 아니지. 다만 귀찮을따름.


추가.
어이쿠.. defproject/yoonkn 에서 root 를 expand 한후에 앞쪽에 \\` 패턴을 붙이는걸 깜빡했네. (concat "\\`" ...) 을 추가하면 된다.

2009년 3월 18일 수요일

emacs 에서 per-directory local variables 와 anything 으로 프로젝트들 빌드하기

현재 ede 사용을 검토중인데 지금 내가 쓰는 방법을 먼저 적어둔다. 꽤 오래전부터 써오던 코드라 위키 등에도 적어둔건데 정리할겸.

내가 원하는것
1. 여러개의 프로젝트들을 목록으로 관리
2. 목록중 하나를 선택하면 해당 프로젝트 루트디렉토리를 dired 모드로
3. 해당 프로젝트 아래의 소스를 편집중에 f7 을 누르면 적당한 방법으로 빌드

이게 전부.
1,2 는 anything 으로 해결했고 3 은 직접만든 함수에 추가로 예전에는 dirvars.el 을 쓰다가 emacs 자체기능으로 전환.
비슷한 일을 하는 코드들이 많지만 써보지는 않았다. 그냥 내손에 맞게 만들다 보니 이런 모양이 됐더라. 자동완성(별 필요성을 못느끼지만) 때문에 ede 를 보고 있는 중인데 ede 를 적용하면 anything 을 ede 로부터 뽑아내야 하는등 다소 변화가 있어야 해서 일단 내걸 정리해둔다.

먼저 f7 을 누르면 컴파일 되도록 하는것부터.
간단히 f7 눌리는 순간 로컬변수로부터 컴파일 커맨드 가져와서 그걸 돌리는걸로 끝. 그런데 내가 cmake 를 쓰고 아웃오브소스 빌드를 좋아하니 빌드디렉토리가 현재 버퍼의 디렉토리와 달라서 이 정보까지 구겨박아야 했다.
이때 이 로컬변수 이름을 yoonkn-build-option 이라고 하고( yoonkn 붙인건 elisp 이 네임스페이스가 없기 때문 헐. 달리 붙인 단어가 없더라) 여러 정보가 들어가야 하니 alist 로 구성했다.(구버전에서는 plist 형태였는데.. 왜바꿨는지는 기억안나네)

즉 yoonkn-build-option 의 모양은 이런 형태
(setq yoonkn-build-option '((build-directory . "/tmp/foo")
(build-command . "make "))
이정보를 가지고 f7 눌리면 /tmp/foo 에 가서 make  돌리도록 해보자.
(defun yoonkn-build ()
(interactive)
(if (and (boundp 'yoonkn-build-option)
(not (null yoonkn-build-option)))
(let ((pwd (substring (pwd) (length "Directory ")))
(wc (cdr (assq 'build-directory yoonkn-build-option)))
(compile-command (cdr (assq 'build-command yoonkn-build-option))))
(unwind-protect
(progn
(cd wc)
(call-interactively 'compile))
(cd pwd)))
(call-interactively 'compile)))
(global-set-key [f7] 'yoonkn-build
좀 드럽지만 어쨌건 돌아간다..
cmake 알기 전에 msvc 쓸때는 devenv 에 커맨드 라인주고 빌드하기도 했는데 지금은 그렇게 쓸 필요가 없지. 그리고 익스프레스버전은(지금은 모르겠고 2005때는) 커맨드라인 빌드가 잘 안됐던것으로 기억하고. 뭐 어쨌건 상용 msvc 를 쓰고있다면 cmake 없이 바로 커맨드라인으로 빌드가 가능하니 위 함수로 ms 쪽빌드도 가능하다.

음.. 그런데 생각해보니 걍 cd .. ; make 해도 될것 같기도?? 헐

yoonkn-build-option 을 디렉토리마다 다르게 주기
위처럼 때려박으면 여러 프로젝트를 동시에 쓰기가 어려우니 per-dir local var 를 써먹자. 이건 전에 적었으니 대강 넘어가고, 그냥 요런식으로 쓰면 된다.
(define-project-bindings 'foo
'((nil . ((yoonkn-build-option . ((build-directory . "/tmp/foo")
(build-command . "make ")))))))
(set-directory-project "~/scratch/foo" 'foo
나는 위 코드를 office-projects.el 또는 home-projects.el 등에 나눠 넣고 머신마다 다른 el 을 부르도록 해서 쓰고있다.

음. 추가.
per-dir 로컬변수 세팅이 아주 반복적이니 매크로를 만들었다.
(defmacro defproject/yoonkn (name root builddir buildcmd)
`(progn
(define-project-bindings ,name
'((nil . ((yoonkn-build-option . ((build-directory . ,builddir)
(build-command . ,buildcmd)))))))
(set-directory-project ,root ,name)))
매크로를 쓰면 위 너저분한 코드가 아래 한줄로
(defmacro/yoonkn 'foo "~/scratch/foo" "/tmp/foo" "make ")

anything 에 등록하기
프로젝트간에 이동을 쉽게 하기 위해서 anything 을 활용했다. 적당히 anything-source 로 등록하면 그만
;;;; Per-Directory Local Variables 하고 anything 을 이용해서 프로젝트 관리
;;; define-project-bindings, set-directory-project 로 적절히 프로젝트를
;;; 세팅해 두면 그걸 anything 이 읽어서 dired 를 띄울수 있도록 해줬다.
(defun yoonkn-projects-candidates ()
(reverse ; reverse 안해주면 set-directory-project 역순으로 나온다
(mapcar #'(lambda (x)
(symbol-name (cdr x)))
project-directory-alist)))

(defun yoonkn-projects-get-dir (name)
(let* ((name-symbol (intern name))
(dir (car (find name-symbol project-directory-alist :key 'cdr))))
dir))

(defun yoonkn-projects-dired (name)
(dired (yoonkn-projects-get-dir name)))

(defun yoonkn-projects-psvn (name)
(psvn-status (yoonkn-projects-get-dir name)))

(setq anything-sources-my-projects
'((name . "내 프로젝트들")
(candidates . yoonkn-projects-candidates)
(action . (("dired 실행하기" . yoonkn-projects-dired)
("psvn 실행하기" . yoonkn-projects-psvn))))

우왕ㅋ굳ㅋ
이제 프로젝트 굵직한게 추가되면 적당히 등록하고 anything 켜서 이동후 코딩하다가 f7 누르면 장땡. 로컬변수 잘 활용라면 ifdef 모드등도 제어가능하고..