[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: browsing files in huge projects emacs

From: Emanuel Berg
Subject: Re: browsing files in huge projects emacs
Date: Sat, 28 Sep 2013 00:30:05 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.4 (gnu/linux)

anurag Ramdasan <address@hidden> writes:

> I have been using Vim for a while although I would
> shift to E..macs for Org-mode and Slime. When I end up
> working on a huge project with hundreds or even
> thousands of files, I found the nerdtree vim plugin to
> be the best thing to suit my ways. Also I find dired a
> little difficult to browse through.
> So when I recently gave thoughts to completely moving
> to emacs, I couldn't find anything as good as
> Nerdtree. I did find dirtree but it didn't seem as
> easy to use as nerdtree. This made me wonder, how do
> most emacs users navigate through huge projects? Is
> there some common practice or some plugin that I
> haven't heard of yet? Also I use both vim and emacs
> from the terminal and not the GUI client.

This has always been a challenge for me, although I never
worked with as many files as did you. You will get
better answers as to what specific tool to use, but I
thought I'd show some of the things that I setup, that I
have found useful.

This post turned out huge! I'll put it here [1], if you
don't like to digest it all right now.

Although I made a text file of it, I think Elisp mode
would be beneficial as there is so much code, and you
probably want highlight and such to be able to
read/interact with it.

As *always*, any fixes and suggestions are welcome. I
use the stuff below every day, so if anything could be
improved I am very appreciative.

1. Find files

Go to a file that is mentioned - let's say, in a
comment (it requires the ~ notation for your home
directory, and not /home/username/... ). Will prompt for
super user privileges if needed.

(defun goto-file ()
  (let*((file (thing-at-point 'filename))
        (in-home (string= "~" (car (split-string file "/"))))
        (final-file (if in-home file
                      (format "%s%s" "/sudo::" file) )))
    (find-file final-file) ))

Open a script that you know by name, that is in

(defun cats (script)
  (interactive "s script: ")
  (find-file (format "%s/scripts/%s" (getenv "HOME") script)) )

2. Buffer menus and some useful shortcuts

In /etc/console-setup/

# caps
keycode 58       = U+0111  # caps
shift keycode 58 = U+0113  # S-caps

Get the keycode with the shell tool showkey. (It doesn't
matter what goofy Unicode chars you use.)

Update (for *all* Linux VTs): loadkeys -c -s key_map_file

or, in .zshrc

lkeys () {
   sudo loadkeys --clearcompose --clearstrings
     /etc/console-setup/ > /dev/null

Sometimes it is necessary to delete a cached keymap in
/etc/console-setup. Also, I'm on Debian. I don't know if
those paths are the same for other distros. On
altogether other systems, probably something similar
would still work.

Then, in ~/.emacs (or a file loaded from there), put

(define-key input-decode-map [?\u0114] [M-tab])
(global-set-key (kbd "<M-tab>") 'switch-buffer)

(define-key input-decode-map [?\u0111] [caps])
(global-set-key (kbd "<caps>") 'buffer-menu-files-only)

(define-key input-decode-map [?\u0113] [S-caps])
(global-set-key (kbd "<S-caps>") 'buffer-menu)

(defun switch-buffer ()
  (switch-to-buffer nil) )

(defun buffer-menu-files-only ()
  (buffer-menu t) )

Fast keys in the buffer menu that won't require you to
move your hands:

(let ((the-map Buffer-menu-mode-map))
  (define-key the-map (kbd "i") 'previous-line)
  (define-key the-map (kbd "k") 'next-line)
  (define-key the-map (kbd "w") 'kill-this-buffer)

3. Some integration with bash/zsh, in another Linux VT:

Again, in /etc/console-setup/, setup
minimal/close shortcuts:

# J - Emacs
alt keycode 36       = Console_1
ctrll alt keycode 36 = Console_1
# L - tmux and more
alt keycode 38       = Incr_Console
ctrll alt keycode 38 = Incr_Console

Then the script


LS_PATH="${DIR/$HOME/~}/`\ls -dl $1 | tr -s ' ' | cut -d' ' -f 9`"
echo -n $LS_PATH | xclip -d ":0" -selection clipboard -in
echo "(find-file \"$LS_PATH\")" > ~/.lsp_file

Usage: lsp filename.extension

Get back to Emacs by hitting M-j, then find the file
with the same command (M-x lsp RET, or assign a

(defun lsp ()
  (load-file "~/.lsp_file") )

Note: Wouldn't it be cool to get back to Emacs
immediately on lsp? The shell tool chvt could do it from
a basic Linux VT, but I run tmux on top of them, so I
get "Couldn't get a file descriptor referring to the

4. Kill and yank filenames and their paths

(defun kill-name ()
  (let ((name (buffer-name)))
    (message (format " Killed %s" name))
    (kill-new name) ))

(defun kill-path ()
  (require 'cl)
  (labels ((print-kill-path (killed)
             (message (format "killed %s" killed))
             (kill-new killed) )
           (print-kill-home-path (killed)
              (format "~%s" (substring file-name home-prefix-len)) )))
    (let*((file-name (buffer-file-name))
          (file-name-len (length file-name))
          (home-prefix (getenv "HOME"))
          (home-prefix-len (length home-prefix))
          (sudo-prefix "/sudo:")
          (sudo-prefix-len (length sudo-prefix))
           (format "address@hidden:" sudo-prefix (message-make-domain)) )
          (root-prefix-len (length root-prefix)) )
      (if (< file-name-len sudo-prefix-len)
          (print-kill-home-path file-name)
        (if (string= (substring file-name 0 sudo-prefix-len)
            (let ((stripped-file-name
                   (substring file-name root-prefix-len) ))
              (print-kill-path stripped-file-name) )
            (if (string= (substring file-name 0 home-prefix-len)
                (print-kill-home-path file-name)
              (print-kill-path file-name) )))))))

(defun yank-path ()
  (yank) )

5. Update file

 (defun refresh-file ()
    t t nil) ; ignore-auto(-save), noconfirm, preserve-modes
  (message "Up to date.") )

6. Jump between configuration files

(global-set-key (kbd "C-j") 'jump-to-register)

(set-register ?a (cons 'file "/sudo::/etc/apt/sources.list"))
(set-register ?b (cons 'file "~/News/KILL"))
(set-register ?C (cons 'file "/sudo::/etc/default/console-setup"))
(set-register ?c (cons 'file "~/.irssi/config"))
(set-register ?d (cons 'file "~/.emacs-dired"))
; etc.

7. Make a script executable, from the buffer in which you edit it

(defun make-executable ()
  (shell-command (concat "chmod +x " buffer-file-name)) )

8. Edit the current file as super user

(defun su-edit ()
  (let ((window-start (window-start))
        (point        (point))
        (mark (if mark-active (region-beginning) nil)) )
    (find-alternate-file (format "/sudo::%s" (buffer-file-name)))
    (if mark (set-mark mark))
    (goto-char point)
    (set-window-start nil window-start) ; nil - the selected window

9. Dired

Shorter and closer, and thus faster and more ergonomic,

(defun scroll-up-other-window ()
  (scroll-other-window-down 1) )
(defun scroll-down-other-window ()
  (scroll-other-window 1) )

(setq dired-deletion-confirmer '(lambda (x) t))

(let ((map dired-mode-map))
  (define-key map (kbd "C-d") 'dired-do-delete)
  ;; navigate
  (define-key map (kbd "w") 'dired-up-directory)
  (define-key map (kbd "s") 'dired-find-file-other-window)
  (define-key map (kbd "i") 'dired-previous-line)
  (define-key map (kbd "k") 'dired-next-line)
  ;; scroll
  (define-key map (kbd "d") 'scroll-up-other-window)
  (define-key map (kbd "f") 'scroll-down-other-window) )

10. Get a new prefix key to get more small and close
    shortcuts, that can be setup to reach files,
    navigate buffers, etc.

(defun init-C-o-prefix ()
  (define-prefix-command 'C-o-prefix)
  (global-set-key "\C-o" 'C-o-prefix)
  (init-C-o-keys) )
(add-hook 'after-init-hook 'init-C-o-prefix)

(defun init-C-o-keys ()
  (let ((the-map (current-global-map)))
    (define-key the-map "\C-oo" 'split-window-vertically-shift)
    ; etc

(defun split-window-vertically-shift ()
  (other-window 1) )

11. Split windows (sometimes)

The way I use Emacs, in a Linux VT with a huge font,
more than two windows is seldom useful. (I use a
projector, that's why I can't have it any other way.)
So, I setup M-o to split the window, only - if it is
already split - don't split, jump. (Also, M-p will
maximize the current window.)

(defun other-window-or-split ()
  (if (= 1 (count-windows)) (split-window-vertically))
  (other-window 1) )

(let ((the-map (current-global-map)))
  (define-key the-map "\M-o" 'other-window-or-split)
  (define-key the-map "\M-p" 'delete-other-windows) )

12. Jumping to files mentioned in the man pages

(let ((the-map Man-mode-map))
  (define-key the-map (kbd "M-RET") 'goto-file) ; mentioned above
  (define-key the-map (kbd "w") 'kill-this-buffer)
  ; etc.


Emanuel Berg - programmer (hire me! CV below)
computer projects:
internet activity:

reply via email to

[Prev in Thread] Current Thread [Next in Thread]