如何直接定位到一个很深的文件夹?

需求是这样的:

在 /proj 里,有很多以项目名称命名的文件夹,而这每个文件夹再往下的结构和命名都是完全相同的,我负责的部分在其中一个很深的位置,平时需要从 /proj 往下6层,之后才有在两个同级文件夹之间切换、新建文件等需求。

那么问题来了,怎样直接把路径定位到我需要的位置?就是说只要保证 /proj 的次一层中项目名称选择正确,就能把我指定的位置之前的路径都补全。项目名称都是字母数字编号,最好还能用上补全工具。

举例:

/proj/ha-01-he/path/to/my/working/path1/
/proj/he-02-hu/path/to/my/working/path2/

我需要选择的部分是/proj下边01还是02或其他名字,/path/to/my/working的若干层都是一致的,而干活时需要在path1或path2下新建文件,并写内容;我拿到的都是用脚本建好的各层文件夹,PS,我们也不是IT类的,就我一个人用git。

用 ivy系列、dired啥的都行,可以给个思路吗?谢谢!

1 个赞

projectlie 项目名称+文件名 不行吗?

文件夹是用脚本建好的,我这边负责的内容都要在固定位置新建文件,projectile有力使不上啊 :joy:

需求再举个例子会更好,“我希望x操作出现a,再y操作出现b”

find-directory-in-project-by-selected from find-file-in-project.

另外还有find-file-in-current-directory我比较常用。

4 个赞
  1. emacs 书签功能
  2. 在一个工作目录创建符号链接直接指向深层目录,符号链接可以用脚本自动创建。
1 个赞

写个函数根据2级目录作为参数去新建/保存buffer。或者也写个脚本自动生成需要的文件后再打开emacs。

  • linux 可以用 locate rgrep
  • windows 上用 everything 使用正则表达式搜索

直接上代码了,大概这样?

(defun deep-into ()
  (interactive)
  (let* ((level1 (read-directory-name "Dir: " "/mnt/")) ;; /proj
         (deep-dir (concat (expand-file-name level1) "path/to/my/working/")) ;; common path
         (level2 (read-directory-name "Level2: " deep-dir))) ;; path1 or path2
    (dired level2) ;; or create buffer blabla
    )
  )

1 个赞

我也遇到过目录很深的项目,目录超级多(几千个),按一个统一的文件夹命名规则,即使没有文件,目录也必须要存在,不能删除不能改名(为了以后在增加文件时统一位置?)

光是确定那些文件夹是空的,那些文件夹是有文件的就花去很多时间了,让人怀疑是不是真的有必要建那么多文件夹。

当一个文件夹没有任何文件时,git是不是会自动删除这个文件夹(发现github会),感觉这是非常好的设置

使用fzf不可以吗?

虽然我没试过,但大概可以写个函数扔到 .dir-local.el 里。

我是分两步,第一步是定位到Project,第二步是定位到file。 Project是自己写的代码继承自ede的cpp-project,在emacs 启动时建立/proj/*目录下的project列表。

可以试试 Emacs 自带的 filesets 功能。

直接counsel-fd-dired-jump跳到对应目录

2 个赞

把需要打开的路径都存到一个文件里面,使用xah定位的函数。可以直接打开光标下面的文件。

函数如下:绑定一个好用的按键就好:


(defun xah-open-file-at-cursor ()
  "Open the file path under cursor.
If there is text selection, uses the text selection for path.
If the path starts with “http://”, open the URL in browser.
Input path can be {relative, full path, URL}.
Path may have a trailing “:‹n›” that indicates line number. If so, jump to that line number.
If path does not have a file extension, automatically try with “.el” for elisp files.
This command is similar to `find-file-at-point' but without prompting for confirmation.

URL `http://ergoemacs.org/emacs/emacs_open_file_path_fast.html'
Version 2018-10-08"
  (interactive)
  (let* (($inputStr (if (use-region-p)
                        (buffer-substring-no-properties (region-beginning) (region-end))
                      (let ($p0 $p1 $p2
                                ;; chars that are likely to be delimiters of file path or url, e.g. space, tabs, brakets. The colon is a problem. cuz it's in url, but not in file name. Don't want to use just space as delimiter because path or url are often in brackets or quotes as in markdown or html
                                ($pathStops "^  \t\n\"`'‘’“”|()[]{}「」<>〔〕〈〉《》【】〖〗«»‹›❮❯❬❭〘〙·。\\")) 
                        (setq $p0 (point))
                        (skip-chars-backward $pathStops)
                        (setq $p1 (point))
                        (goto-char $p0)
                        (skip-chars-forward $pathStops)
                        (setq $p2 (point))
                        (goto-char $p0)
                        (buffer-substring-no-properties $p1 $p2))))
         ($path
          (replace-regexp-in-string
           "^file:///" "/"
           (replace-regexp-in-string
            ":\\'" "" $inputStr))))
    (if (string-match-p "\\`https?://" $path)
        (if (fboundp 'xahsite-url-to-filepath)
            (let (($x (xahsite-url-to-filepath $path)))
              (if (string-match "^http" $x )
                  (browse-url $x)
                (find-file $x)))
          (progn (browse-url $path)))
      (if ; not starting “http://”
          (string-match "^\\`\\(.+?\\):\\([0-9]+\\)\\'" $path)
          (let (
                ($fpath (match-string 1 $path))
                ($line-num (string-to-number (match-string 2 $path))))
            (if (file-exists-p $fpath)
                (progn
                  (find-file $fpath)
                  (goto-char 1)
                  (forward-line (1- $line-num)))
              (when (y-or-n-p (format "file no exist: 「%s」. Create?" $fpath))
                (find-file $fpath))))
        (if (file-exists-p $path)
            (progn ; open f.ts instead of f.js
              (let (($ext (file-name-extension $path))
                    ($fnamecore (file-name-sans-extension $path)))
                (if (and (string-equal $ext "js")
                         (file-exists-p (concat $fnamecore ".ts")))
                    (find-file (concat $fnamecore ".ts"))
                  (find-file $path))))
          (if (file-exists-p (concat $path ".el"))
              (find-file (concat $path ".el"))
            (when (y-or-n-p (format "file no exist: 「%s」. Create?" $path))
              (find-file $path ))))))))

2 个赞

counsel或textmate