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))

#퍼플렉시티

2024-12-22

@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=를 대체할 수 있는 기능을 찾기 위해 다음과 같은 방법을 고려할 수 있습니다:

  1. Projectile Search: Projectile에는 =projectile-grep=라는 함수가 있습니다. 이 함수는 현재 프로젝트 내에서 grep 검색을 수행합니다. 이는 =project-search=와 유사한 기능을 제공합니다.

       ("S" "Search regexp sequential…" projectile-grep :transient t)
  2. 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에는 검색 결과를 순차적으로 탐색하는 기능이 포함되어 있지 않습니다. 그러나, 다음과 같은 대체 방법을 고려할 수 있습니다:

  1. Projectile Grep: =projectile-grep=를 사용하여 프로젝트 내에서 검색을 수행한 후, grep 결과를 순차적으로 탐색하는 방법을 사용할 수 있습니다. grep 결과는 일반적으로 grep 버퍼에 나타나며, 이 버퍼에서 다음 결과로 이동하는 키 바인딩을 사용할 수 있습니다.

       ("S" "Search regexp sequential…" projectile-grep :transient t)
  2. grep-next-file: grep 결과를 순차적으로 탐색하는 기본 Emacs 함수인 =grep-next-file=를 사용할 수 있습니다. 이 함수는 grep 결과 버퍼에서 다음 파일로 이동합니다.

       ("n" "Next sequential" grep-next-file :transient t)
  3. 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=를 사용하는 이유는 다음과 같을 수 있습니다:

  1. 프로젝트 검색 기능: project-search=는 프로젝트 내에서 검색을 수행하는 기능을 제공합니다. 이는 Projectile의 =projectile-grep=와 유사한 기능을 제공합니다. =casual 패키지의 개발자가 Projectile 대신 project 패키지를 사용하거나, Projectile의 grep 기능이 충분하지 않다고 판단하여 자체적으로 검색 기능을 구현했을 가능성이 있습니다.

  2. 순차적 검색: fileloop-continue=는 검색 결과를 순차적으로 탐색하는 기능을 제공합니다. Projectile에는 이와 동일한 기능을 제공하는 함수가 없기 때문에, =casual 패키지의 개발자는 Emacs의 기본 grep 기능을 활용하여 이 기능을 구현했을 가능성이 큽니다. =fileloop-continue=는 grep 결과 버퍼에서 다음 일치 항목으로 이동하는 기능을 제공합니다.

  3. 사용자 경험: casual 패키지의 개발자는 사용자 경험을 개선하기 위해 특정 기능을 자체적으로 구현했을 수 있습니다. 예를 들어, =project-search=와 =fileloop-continue=를 사용하면 사용자가 프로젝트 내에서 검색을 수행하고 그 결과를 쉽게 탐색할 수 있습니다. 이는 Projectile의 기본 기능을 보완하거나 대체하는 방법일 수 있습니다.

  4. 커스터마이징: casual 패키지의 개발자는 사용자 맞춤형 기능을 제공하기 위해 프로젝트 검색과 순차적 탐색을 자체적으로 구현했을 수 있습니다. 이는 Projectile의 기본 기능을 사용하는 것보다 더 세밀한 제어를 가능하게 합니다.

  5. 패키지 의존성: casual 패키지가 Projectile에 의존하지 않거나, Projectile의 기능을 사용하지 않기로 결정했을 가능성도 있습니다. 이 경우, =project-search=와 =fileloop-continue=를 사용하여 필요한 기능을 직접 구현했을 수 있습니다.

결론적으로, casual 패키지가 =project-search=와 =fileloop-continue=를 사용하는 이유는 Projectile의 기본 기능을 보완하거나 대체하기 위해 자체적으로 검색 및 순차적 탐색 기능을 구현했기 때문입니다. 이는 사용자 경험을 개선하고, 패키지의 독립성을 유지하기 위한 선택일 수 있습니다.

@user

2024-12-23

@user 이맥스 Projectile 패키지의 검색 기능 관련 질문이야. 다음 질문에 대해서 확인해줘.

  1. projectile-regenerate-tags, projectile-find-tags가 어떤 기능인가?
  2. 특정 파일 확장자의 파일에서만 검색하는 방법(예를 들어 소스코드)
  3. 소스코드의 주석(comment)에서만 검색 또는 코드에서만 검색

@assistant 물론입니다. 다음은 Projectile 패키지의 검색 기능에 대한 답변입니다:

  1. projectile-regenerate-tags, projectile-find-tags가 어떤 기능인가?

    • projectile-regenerate-tags: 현재 프로젝트의 태그 파일을 재생성합니다. 이는 프로젝트 내의 모든 파일에서 태그를 추출하여, 나중에 빠르게 검색할 수 있도록 합니다. 태그는 함수, 변수, 클래스 등의 정의를 가리킵니다.
    • projectile-find-tags: 프로젝트 내에서 태그를 검색하여 해당 태그가 정의된 위치로 이동합니다. 이는 주로 함수나 변수의 정의를 찾을 때 사용됩니다.
  2. 특정 파일 확장자의 파일에서만 검색하는 방법(예를 들어 소스코드)

    • Projectile은 기본적으로 프로젝트 내의 모든 파일을 검색합니다. 하지만 특정 파일 확장자만 검색하려면, projectile-grep 명령을 사용하여 grep 명령에 -i 옵션과 함께 확장자 필터를 추가할 수 있습니다. 예를 들어, .c 파일에서만 검색하려면:
           (projectile-grep "검색어" "-i *.c")
  3. 소스코드의 주석(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에서 특정 파일 확장자나 주석/코드만을 대상으로 검색할 수 있는 여러 방법이 있습니다:

  1. 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
  2. rg (ripgrep) 사용:

    • rg=는 매우 빠른 grep 대안입니다. Emacs에서 =rg 패키지를 사용하여 검색할 수 있습니다. rg=는 기본적으로 주석을 무시하고 검색하지만, =-u 옵션을 사용하여 주석을 포함할 수 있습니다. 예를 들어:
           M-x rg 검색어 -u *.c
    • 특정 파일 확장자만 검색하려면:
           M-x rg 검색어 -g *.c
  3. ag (The Silver Searcher) 사용:

    • ag=도 빠른 검색 도구입니다. Emacs에서 =ag 패키지를 사용하여 검색할 수 있습니다. ag=는 기본적으로 주석을 무시하지만, =--comments 옵션을 사용하여 주석을 포함할 수 있습니다:
           M-x ag 검색어 --comments *.c
    • 특정 파일 확장자만 검색하려면:
           M-x ag 검색어 -G *.c
  4. Emacs 내장 검색 기능 사용:

    • occur 명령을 사용하여 현재 버퍼에서 특정 패턴을 검색할 수 있습니다. 예를 들어, 주석만 검색하려면:
           M-x occur RET ^//.*검색어 RET
    • =occur=는 주석이나 코드만을 대상으로 검색하는 데는 제한이 있지만, 정규 표현식을 사용하여 특정 패턴을 찾을 수 있습니다.
  5. Custom Search Functions:

    • Emacs Lisp를 사용하여 커스텀 검색 함수를 작성할 수 있습니다. 예를 들어, 특정 파일 확장자나 주석/코드만을 대상으로 검색하는 함수를 작성할 수 있습니다. 이는 Emacs의 강력한 확장성 덕분에 가능합니다.

이러한 방법들은 Emacs의 다양한 검색 도구를 활용하여 특정 조건에 맞는 검색을 수행할 수 있게 해줍니다. 사용자의 필요에 따라 적절한 도구를 선택하여 사용하면 됩니다.

@user