References
캐쥬얼 프로젝타일 - casual with projectile
[2024-12-22 Sun 22:22]
@최민수 #이맥스 #메뉴 #혁명 #사용자인터페이스 #구루 가 만든 패키지
#이맥스 #입문 #메뉴 #인터페이스 #마우스 casual context-menu
일단 구성해서 넣음
( progn
( defun casual-editkit--current-project-label ()
"Current project label using Projectile."
( let ((project-root (projectile-project-root)))
( if project-root
( format "Project: %s " ( file-name-nondirectory ( directory-file-name project-root)))
"Project" )))
(transient-define-prefix casual-editkit-project-tmenu ()
"Menu for ‘Project’ commands.
Commands pertaining to project operations can be accessed here."
[ "Project"
:description ( lambda () (casual-editkit--current-project-label))
[ "File"
( "." "browse-project" +default/browse-project) ;; for doom
( "f" "find-file" projectile-find-file)
( "r" "recentf" projectile-recentf)
( "b" "switch-to-buffer" projectile-switch-to-buffer)]
[ "Dired"
( "-" "dired" projectile-dired)
( "_" "find-dir" projectile-find-dir)
( "v" "vc-dir" projectile-vc)]
[ "Search/Replace"
( "s" "search-project" +default/search-project) ;; for doom
( "r" "replace-regexp…" projectile-replace-regexp)]
;; ("S" "Search regexp sequential…" project-search :transient t)
;; ("n" "Next sequential" fileloop-continue :transient t)]
[ "Tools"
:pad-keys t
( "i" "ibuffer" projectile-ibuffer)
( "c" "compile-project" projectile-compile-project)
;; ("e" "run-Eshell" projectile-run-eshell)
;; ("M-s" "run-shell" projectile-run-shell)
( "e" "edit-dir-locals" projectile-edit-dir-locals)
( "!" "run-shell-command-in-root" projectile-run-shell-command-in-root)
( "&" "run-async-shell-command-in-root" projectile-run-async-shell-command-in-root)]]
[ "Projectile"
:class transient-row
( "a" "add-known-project" projectile-add-known-project)
( "p" "switch-project" projectile-switch-project)
( "k" "kill-buffers" projectile-kill-buffers)
( "d" "remove-known-project" projectile-remove-known-project)
]
casual-editkit-navigation-group)
)
프로젝트 - 태그 검색, 주석에서만 검색,
프로젝트 관련 둠 함수
#둠이맥스 에서 프로젝트를 다루는 방법
( :fix-map ( "p" . "project" )
:desc "Browse project" "." #'+default/browse-project
:desc "Browse other project" ">" #'doom/browse-in-other-project
:desc "Run cmd in project root" "!" #'projectile-run-shell-command-in-root
:desc "Async cmd in project root" "&" #'projectile-run-async-shell-command-in-root
:desc "Add new project" "a" #'projectile-add-known-project
:desc "Switch to project buffer" "b" #'projectile-switch-to-buffer
:desc "Compile in project" "c" #'projectile-compile-project
:desc "Repeat last command" "C" #'projectile-repeat-last-command
:desc "Remove known project" "d" #'projectile-remove-known-project
:desc "Discover projects in folder" "D" #'+default/discover-projects
:desc "Edit project .dir-locals" "e" #'projectile-edit-dir-locals
:desc "Find file in project" "f" #'projectile-find-file
:desc "Find file in other project" "F" #'doom/find-file-in-other-project
:desc "Configure project" "g" #'projectile-configure-project
:desc "Invalidate project cache" "i" #'projectile-invalidate-cache
:desc "Kill project buffers" "k" #'projectile-kill-buffers
:desc "Find sibling file" "o" #'find-sibling-file
:desc "Switch project" "p" #'projectile-switch-project
:desc "Find recent project files" "r" #'projectile-recentf
:desc "Run project" "R" #'projectile-run-project
:desc "Save project files" "s" #'projectile-save-project-buffers
:desc "Test project" "T" #'projectile-test-project
:desc "Pop up scratch buffer" "x" #'doom/open-project-scratch-buffer
:desc "Switch to scratch buffer" "X" #'doom/switch-to-project-scratch-buffer
( :when ( and (modulep! :tools taskrunner)
( or (modulep! :completion ivy)
(modulep! :completion helm)))
:desc "List project tasks" "z" #'+taskrunner/project-tasks ))
@user project-current와 동일한 projectile 함수가 있는지 찾아봐줘
@assistant =project-current=와 동일한 기능을 하는 Projectile 함수는 =projectile-project-root=입니다. 이 함수는 현재 프로젝트의 루트 디렉토리를 반환합니다.
(projectile-project-root)
이 함수를 사용하면 현재 작업 중인 프로젝트의 루트 디렉토리를 얻을 수 있습니다.
@user casual 패키지의 일부 함수인데 projectile용으로 변경했으면 해.
( defun casual-editkit--current-project-label ()
"Current project label."
( let* ((project ( project-current )))
( if project
( format "Project: %s " ( nth 2 project))
"Project" )))
@assistant Projectile 패키지에 맞게 casual-editkit--current-project-label
함수를 변경하면 다음과 같이 작성할 수 있습니다:
( defun casual-editkit--current-project-label ()
"Current project label using Projectile."
( let ((project-root (projectile-project-root)))
( if project-root
( format "Project: %s " ( file-name-nondirectory ( directory-file-name project-root)))
"Project" )))
이 코드는 Projectile을 사용하여 현재 프로젝트의 루트 디렉토리를 가져오고, 그 디렉토리 이름을 프로젝트 라벨로 사용합니다. projectile-project-root
함수가 nil을 반환하면 "Project"라는 기본 라벨을 사용합니다.
@user casual 패키지의 project 관련 transient 메뉴인데, projectile 패키지를 이용하는 버전으로 변경하고 싶어.
(transient-define-prefix casual-editkit-project-tmenu ()
"Menu for ‘Project’ commands.
Commands pertaining to project operations can be accessed here."
[ "Project"
:description ( lambda () (casual-editkit--current-project-label))
[ "File"
( "f" "Open…" project-find-file)
( "B" "Switch buffer…" project-switch-to-buffer)]
[ "Dired"
( "d" "Dired…" project-dired)
( "D" "Dired in…" project-find-dir)
( "v" "VC Dired…" project-vc-dir)]
[ "Search/Replace"
( "r" "Search regexp…" project-find-regexp)
( "q" "Query replace regexp…" project-query-replace-regexp)
( "S" "Search regexp sequential…" project-search :transient t )
( "n" "Next sequential" fileloop-continue :transient t )]
[ "Tools"
:pad-keys t
( "c" "Compile…" project-compile)
( "e" "Eshell" project-eshell)
( "M-s" "Shell" project-shell)
( "!" "Shell command…" project-shell-command)
( "&" "Async command…" project-async-shell-command)]]
[ "Project"
:class transient-row
( "s" "Switch…" project-switch-project)
( "b" "List buffers" project-list-buffers)
( "k" "Kill buffers" project-kill-buffers)
( "F" "Forget" project-forget-project)]
casual-editkit-navigation-group)
@assistant Projectile 패키지를 사용하여 =casual-editkit-project-tmenu=를 변경하면 다음과 같이 작성할 수 있습니다:
(transient-define-prefix casual-editkit-project-tmenu ()
"Menu for ‘Project’ commands using Projectile.
Commands pertaining to project operations can be accessed here."
[ "Project"
:description ( lambda () (casual-editkit--current-project-label))
[ "File"
( "f" "Open…" projectile-find-file)
( "B" "Switch buffer…" projectile-switch-to-buffer)]
[ "Dired"
( "d" "Dired…" projectile-dired)
( "D" "Dired in…" projectile-find-dir)
( "v" "VC Dired…" projectile-vc-dir)]
[ "Search/Replace"
( "r" "Search regexp…" projectile-grep)
( "q" "Query replace regexp…" projectile-replace)
( "S" "Search regexp sequential…" projectile-ack :transient t )
( "n" "Next sequential" projectile-ack-next :transient t )]
[ "Tools"
:pad-keys t
( "c" "Compile…" projectile-compile-project)
( "e" "Eshell" projectile-run-eshell)
( "M-s" "Shell" projectile-run-shell)
( "!" "Shell command…" projectile-run-async-shell-command)
( "&" "Async command…" projectile-run-async-shell-command)]
[ "Project"
:class transient-row
( "s" "Switch…" projectile-switch-project)
( "b" "List buffers" projectile-display-buffer)
( "k" "Kill buffers" projectile-kill-buffers)
( "F" "Forget" projectile-remove-known-project)]
casual-editkit-navigation-group)
이 코드는 Projectile의 함수들을 사용하여 프로젝트 관련 명령을 정의합니다. 몇 가지 주의 사항:
=projectile-ack=과 =projectile-ack-next=는 =projectile-grep=와 =projectile-grep-next=로 대체될 수 있습니다. Projectile에서 =ack=를 사용하지 않는 경우입니다.
=projectile-compile-project=는 =projectile-compile=로 대체될 수 있습니다.
=projectile-run-async-shell-command=는 =projectile-run-shell-command=로 대체될 수 있습니다.
=projectile-remove-known-project=는 =projectile-forget-project=로 대체될 수 있습니다.
이 변경 사항은 Projectile의 기본 함수와 일치하도록 조정되었습니다. 필요에 따라 함수 이름을 조정하거나 추가적인 Projectile 기능을 사용할 수 있습니다.
@user 위에 transient 에서 다음 부분을 설명해줘. 여기서 "transient t"의 역할은?
( "S" "Search regexp sequential…" project-search :transient t )
( "n" "Next sequential" fileloop-continue :transient t )
@assistant transient
패키지에서 =:transient t=는 해당 키 바인딩이 일시적인(transient) 상태를 유지하도록 설정합니다. 이는 다음과 같은 의미를 가집니다:
일시적인 상태 유지 : 이 키를 누르면, 해당 명령이 실행된 후에도 트랜지언트 메뉴가 닫히지 않고 계속 열려 있게 됩니다. 즉, 사용자가 여러 번 같은 명령을 반복적으로 실행할 수 있습니다.
반복 실행 : 사용자가 이 키를 여러 번 누르면, 각각의 키 입력에 대해 명령이 반복적으로 실행됩니다. 예를 들어, =project-search=를 실행한 후에도 트랜지언트 메뉴가 열려 있으므로, 사용자는 계속해서 검색을 수행할 수 있습니다.
이러한 설정을 통해 사용자는 한 번의 키 입력으로 여러 번의 연속적인 작업을 수행할 수 있게 됩니다. 예를 들어, =project-search=를 실행한 후, 검색 결과를 순차적으로 탐색하는 =fileloop-continue=를 여러 번 실행할 수 있습니다.
이 기능은 특히 반복적인 작업을 수행할 때 유용하며, 사용자가 트랜지언트 메뉴를 닫지 않고도 여러 명령을 연속적으로 실행할 수 있게 해줍니다.
@user 이 부분을 projectile 패키지 기능을 이용해서 대체했으면 하는데 방법을 찾아봐줘
@assistant Projectile 패키지에서 =project-search=와 =fileloop-continue=를 대체할 수 있는 기능을 찾기 위해 다음과 같은 방법을 고려할 수 있습니다:
Projectile Search : Projectile에는 =projectile-grep=라는 함수가 있습니다. 이 함수는 현재 프로젝트 내에서 grep 검색을 수행합니다. 이는 =project-search=와 유사한 기능을 제공합니다.
( "S" "Search regexp sequential…" projectile-grep :transient t )
Sequential Search : Projectile에는 =projectile-grep-next=라는 함수가 있습니다. 이는 grep 검색 결과를 순차적으로 탐색할 수 있게 해줍니다. 이는 =fileloop-continue=와 유사한 기능을 제공합니다.
( "n" "Next sequential" projectile-grep-next :transient t )
이렇게 하면 Projectile의 기능을 사용하여 트랜지언트 메뉴에서 검색과 다음 결과 탐색을 수행할 수 있습니다.
(transient-define-prefix casual-editkit-project-tmenu ()
"Menu for ‘Project’ commands using Projectile.
Commands pertaining to project operations can be accessed here."
[ "Project"
:description ( lambda () (casual-editkit--current-project-label))
[ "Search/Replace"
( "r" "Search regexp…" projectile-grep)
( "q" "Query replace regexp…" projectile-replace)
( "S" "Search regexp sequential…" projectile-grep :transient t )
( "n" "Next sequential" projectile-grep-next :transient t )]
;; ... 나머지 메뉴 항목들 ...
])
이렇게 변경하면 Projectile의 검색 기능을 사용하여 트랜지언트 메뉴에서 검색과 다음 결과 탐색을 반복적으로 수행할 수 있습니다.
@user Projectile 리포지토리는 다음과 같거든 검토 좀 해줘. projectile-grep-next 함수가 없어. bbatsov/projectile - github.com
@assistant Projectile 리포지토리를 확인한 결과, projectile-grep-next
함수는 존재하지 않습니다. 대신, Projectile에는 검색 결과를 순차적으로 탐색하는 기능이 포함되어 있지 않습니다. 그러나, 다음과 같은 대체 방법을 고려할 수 있습니다:
Projectile Grep : =projectile-grep=를 사용하여 프로젝트 내에서 검색을 수행한 후, grep 결과를 순차적으로 탐색하는 방법을 사용할 수 있습니다. grep 결과는 일반적으로 grep 버퍼에 나타나며, 이 버퍼에서 다음 결과로 이동하는 키 바인딩을 사용할 수 있습니다.
( "S" "Search regexp sequential…" projectile-grep :transient t )
grep-next-file : grep 결과를 순차적으로 탐색하는 기본 Emacs 함수인 =grep-next-file=를 사용할 수 있습니다. 이 함수는 grep 결과 버퍼에서 다음 파일로 이동합니다.
( "n" "Next sequential" grep-next-file :transient t )
grep-next-match : grep 결과 버퍼에서 다음 일치 항목으로 이동하는 기본 Emacs 함수인 =grep-next-match=를 사용할 수도 있습니다.
( "n" "Next sequential" grep-next-match :transient t )
이러한 방법을 사용하면 Projectile의 검색 기능을 활용하면서도 grep 결과를 순차적으로 탐색할 수 있습니다. 트랜지언트 메뉴에서 projectile-grep=를 실행한 후, grep 결과 버퍼에서 =grep-next-file
또는 =grep-next-match=를 사용하여 다음 결과로 이동할 수 있습니다.
(transient-define-prefix casual-editkit-project-tmenu ()
"Menu for ‘Project’ commands using Projectile.
Commands pertaining to project operations can be accessed here."
[ "Project"
:description ( lambda () (casual-editkit--current-project-label))
[ "Search/Replace"
( "r" "Search regexp…" projectile-grep)
( "q" "Query replace regexp…" projectile-replace)
( "S" "Search regexp sequential…" projectile-grep :transient t )
( "n" "Next sequential" grep-next-file :transient t )] ;; 또는 grep-next-match
;; ... 나머지 메뉴 항목들 ...
])
이렇게 하면 Projectile의 검색 기능과 Emacs의 기본 grep 탐색 기능을 함께 사용할 수 있습니다.
@user 그렇다면 왜 casual 패키지는 project-search, fileloop-continue 로 구성된 것인가?
@assistant casual
패키지가 =project-search=와 =fileloop-continue=를 사용하는 이유는 다음과 같을 수 있습니다:
프로젝트 검색 기능 : project-search=는 프로젝트 내에서 검색을 수행하는 기능을 제공합니다. 이는 Projectile의 =projectile-grep=와 유사한 기능을 제공합니다. =casual
패키지의 개발자가 Projectile 대신 project
패키지를 사용하거나, Projectile의 grep 기능이 충분하지 않다고 판단하여 자체적으로 검색 기능을 구현했을 가능성이 있습니다.
순차적 검색 : fileloop-continue=는 검색 결과를 순차적으로 탐색하는 기능을 제공합니다. Projectile에는 이와 동일한 기능을 제공하는 함수가 없기 때문에, =casual
패키지의 개발자는 Emacs의 기본 grep 기능을 활용하여 이 기능을 구현했을 가능성이 큽니다. =fileloop-continue=는 grep 결과 버퍼에서 다음 일치 항목으로 이동하는 기능을 제공합니다.
사용자 경험 : casual
패키지의 개발자는 사용자 경험을 개선하기 위해 특정 기능을 자체적으로 구현했을 수 있습니다. 예를 들어, =project-search=와 =fileloop-continue=를 사용하면 사용자가 프로젝트 내에서 검색을 수행하고 그 결과를 쉽게 탐색할 수 있습니다. 이는 Projectile의 기본 기능을 보완하거나 대체하는 방법일 수 있습니다.
커스터마이징 : casual
패키지의 개발자는 사용자 맞춤형 기능을 제공하기 위해 프로젝트 검색과 순차적 탐색을 자체적으로 구현했을 수 있습니다. 이는 Projectile의 기본 기능을 사용하는 것보다 더 세밀한 제어를 가능하게 합니다.
패키지 의존성 : casual
패키지가 Projectile에 의존하지 않거나, Projectile의 기능을 사용하지 않기로 결정했을 가능성도 있습니다. 이 경우, =project-search=와 =fileloop-continue=를 사용하여 필요한 기능을 직접 구현했을 수 있습니다.
결론적으로, casual
패키지가 =project-search=와 =fileloop-continue=를 사용하는 이유는 Projectile의 기본 기능을 보완하거나 대체하기 위해 자체적으로 검색 및 순차적 탐색 기능을 구현했기 때문입니다. 이는 사용자 경험을 개선하고, 패키지의 독립성을 유지하기 위한 선택일 수 있습니다.
@user
@user 이맥스 Projectile 패키지의 검색 기능 관련 질문이야. 다음 질문에 대해서 확인해줘.
projectile-regenerate-tags, projectile-find-tags가 어떤 기능인가?
특정 파일 확장자의 파일에서만 검색하는 방법(예를 들어 소스코드)
소스코드의 주석(comment)에서만 검색 또는 코드에서만 검색
@assistant 물론입니다. 다음은 Projectile 패키지의 검색 기능에 대한 답변입니다:
projectile-regenerate-tags, projectile-find-tags가 어떤 기능인가?
projectile-regenerate-tags : 현재 프로젝트의 태그 파일을 재생성합니다. 이는 프로젝트 내의 모든 파일에서 태그를 추출하여, 나중에 빠르게 검색할 수 있도록 합니다. 태그는 함수, 변수, 클래스 등의 정의를 가리킵니다.
projectile-find-tags : 프로젝트 내에서 태그를 검색하여 해당 태그가 정의된 위치로 이동합니다. 이는 주로 함수나 변수의 정의를 찾을 때 사용됩니다.
특정 파일 확장자의 파일에서만 검색하는 방법(예를 들어 소스코드)
Projectile은 기본적으로 프로젝트 내의 모든 파일을 검색합니다. 하지만 특정 파일 확장자만 검색하려면, projectile-grep
명령을 사용하여 grep 명령에 -i
옵션과 함께 확장자 필터를 추가할 수 있습니다. 예를 들어, .c
파일에서만 검색하려면:
(projectile-grep "검색어" "-i *.c" )
소스코드의 주석(comment)에서만 검색 또는 코드에서만 검색
Projectile 자체에는 주석이나 코드만을 대상으로 하는 검색 기능이 기본적으로 포함되어 있지 않습니다. 하지만, projectile-grep
명령을 사용하여 grep 명령에 적절한 옵션을 추가하면 가능합니다:
주석에서만 검색 : 주석의 형식에 따라 다르지만, 예를 들어 C 코드에서 =//=로 시작하는 주석을 찾으려면:
(projectile-grep "검색어" "-i *.[ch] | grep -E '//.*검색어'" )
코드에서만 검색 : 주석을 제외하고 코드만 검색하려면, 주석을 제외하는 grep 명령을 사용해야 합니다. 예를 들어, C 코드에서 주석을 제외하고 검색하려면:
(projectile-grep "검색어" "-i *.[ch] | grep -v '//' | grep -v '/*'" )
이 방법들은 grep 명령을 활용한 것이므로, 사용하는 프로그래밍 언어의 주석 형식에 맞게 grep 명령을 조정해야 합니다. 또한, Emacs 내에서 이러한 복잡한 검색을 자주 사용한다면, 커스텀 함수나 키 바인딩을 설정하는 것도 고려해볼 만합니다.
@user 혹시 Projectile이 아니더라도 위에 이슈를 이맥스에서 다룰 수 있는 방법이 있는지 찾아봐줘
@assistant 물론입니다. Projectile 패키지 외에도 Emacs에서 특정 파일 확장자나 주석/코드만을 대상으로 검색할 수 있는 여러 방법이 있습니다:
grep 명령 사용 :
Emacs 내장 grep 명령인 M-x grep=을 사용하여 특정 파일 확장자나 패턴을 검색할 수 있습니다. 예를 들어, =.c
파일에서만 검색하려면:
M-x grep RET 검색어 *.c RET
주석이나 코드만을 대상으로 검색하려면, grep 명령에 적절한 옵션을 추가해야 합니다. 예를 들어, C 코드에서 주석을 제외하고 검색하려면:
M-x grep RET 검색어 *.[ch] | grep -v '// ' | grep -v '/* ' RET
rg (ripgrep) 사용 :
rg=는 매우 빠른 grep 대안입니다. Emacs에서 =rg
패키지를 사용하여 검색할 수 있습니다. rg=는 기본적으로 주석을 무시하고 검색하지만, =-u
옵션을 사용하여 주석을 포함할 수 있습니다. 예를 들어:
M-x rg 검색어 -u *.c
특정 파일 확장자만 검색하려면:
M-x rg 검색어 -g *.c
ag (The Silver Searcher) 사용 :
ag=도 빠른 검색 도구입니다. Emacs에서 =ag
패키지를 사용하여 검색할 수 있습니다. ag=는 기본적으로 주석을 무시하지만, =--comments
옵션을 사용하여 주석을 포함할 수 있습니다:
M-x ag 검색어 --comments *.c
특정 파일 확장자만 검색하려면:
M-x ag 검색어 -G *.c
Emacs 내장 검색 기능 사용 :
occur
명령을 사용하여 현재 버퍼에서 특정 패턴을 검색할 수 있습니다. 예를 들어, 주석만 검색하려면:
M-x occur RET ^//.*검색어 RET
=occur=는 주석이나 코드만을 대상으로 검색하는 데는 제한이 있지만, 정규 표현식을 사용하여 특정 패턴을 찾을 수 있습니다.
Custom Search Functions :
Emacs Lisp를 사용하여 커스텀 검색 함수를 작성할 수 있습니다. 예를 들어, 특정 파일 확장자나 주석/코드만을 대상으로 검색하는 함수를 작성할 수 있습니다. 이는 Emacs의 강력한 확장성 덕분에 가능합니다.
이러한 방법들은 Emacs의 다양한 검색 도구를 활용하여 특정 조건에 맞는 검색을 수행할 수 있게 해줍니다. 사용자의 필요에 따라 적절한 도구를 선택하여 사용하면 됩니다.
@user