How to get equivalent of Vim's :Texplore in Emacs? - emacs

I know about M-x dire, but would like to customize it. I would like to hit one key (for example F2) and get dire buffer open. When I navigate across the directory hierarchy it shouldn't open new buffers.
And when I finally open the file it also shouldn't open new buffer for it (not strictly necessary, but strongly preferred).
Of course this behavior can be global, i.e. for all dire buffers/invocations.

Check out dired-single, which pretty much does what you want (except that last bit, where it reuses the dired buffer for the newly visted file).
Caveat Lector: I wrote it, so I'm biased towards its usefulness.

Some alternatives - EmacsWiki: DiredReuseDirectoryBuffer, and this short snippet from an awkwardly-formatted blog-entry.
caveat: haven't tried them, myself.

I know this is very old but All you have to do is press 'a' on a dir or file to get this functionality. It's already there.

Here's what I finally used:
(require 'dired)
(global-set-key [(f2)] 'my-dired)
(defun my-dired ()
(interactive)
(dired (file-name-directory (buffer-file-name))))
(defadvice dired-advertised-find-file (around dired-subst-directory activate)
"Replace current buffer if file is a directory."
(interactive)
(let ((orig (current-buffer)) (filename (dired-get-filename :no-error-if-not-filep t)))
ad-do-it
(when (not (eq (current-buffer) orig)) (kill-buffer orig))))

Related

How to run hook depending on file location

I am involved in python project where tabs are used, however i am not using them in every other code i write, it is vital to use them in that particular project. Projects are located in one directory under specific directories. I.E:
\main_folder
\project1
\project2
\project3
...etc
I have couple functions/hooks on file open and save that untabify and tabify whole buffer i work on.
;; My Functions
(defun untabify-buffer ()
"Untabify current buffer"
(interactive)
(untabify (point-min) (point-max)))
(defun tabify-buffer ()
"Tabify current buffer"
(interactive)
(tabify (point-min) (point-max)))
;; HOOKS
; untabify buffer on open
(add-hook 'find-file-hook 'untabify-buffer)
; tabify on save
(add-hook 'before-save-hook 'tabify-buffer)
If i put it in .emacs file it is run on every .py file i open which is not what i want. What i`d like to have is to have these hooks used only in one particular folder with respective subfolders. Tried .dir_locals but it works only for properties not hooks. I can not use hooks in specific modes (i.e. python-mode) as almost all projects are written in python. To be honest i tried writing elisp conditional save but failed.
A very easy solution is to just add a configuration variable that can be used to disable the hooks. For example:
(defvar tweak-tabs t)
(add-hook 'find-file-hook
(lambda () (when tweak-tabs (untabify (point-min) (point-max)))))
(add-hook 'before-save-hook
(lambda () (when tweak-tabs (tabify (point-min) (point-max)))))
Now you can add a .dir-locals.el file in the relevant directories, setting tweak-tabs to nil, disabling this feature there.
(But another problem is that this is a pretty bad way to deal with tabs. For example, after you save a file you do see the tabs in it.)
Just for the record, to answer the literal question in the title (as I reached this question via a web search): one way to add a hook that depends on file location is to make it a function that checks for buffer-file-name. (Idea from this answer.)
For example, for the exact same problem (turn on tabs only in a particular directory, and leave tabs turned off elsewhere), I'm currently doing something like (after having installed the package smart-tabs-mode with M-x package-install):
(smart-tabs-insinuate 'python) ; This screws up all Python files (inserts tabs)
(add-hook 'python-mode-hook ; So we need to un-screw most of them
(lambda ()
(unless (and (stringp buffer-file-name)
(string-match "specialproject" buffer-file-name))
(setq smart-tabs-mode nil)))
t) ; Add this hook to end of the list
(This is a bit inverted, as smart-tabs-insinuate itself modifies python-mode-hook and then we're modifying it back, but it should do as an example.)

How do I get emacs to write to read-only files automatically?

I am finding myself editing a lot of files that are read-only. I usually hit C-x C-q to call toggle-read-only. Then I hit C-x C-s to save and get,
File foo.txt is write-protected; try to save anyway? (y or n)
After hitting y, the file is saved and the permissions on the file remain read-only.
Is there a way to shorten this process and make it so that simply saving a file with C-x C-s does the whole thing without prompting? Should I look into inserting chmod in before-save-hook and after-save-hook or is there a better way?
Adding a call to chmod in before-save-hook would be clean way to accomplish this. There isn't any setting you can change to avoid the permissions check.
Based on the follow-up question, it sounds like you'd like the files to be changed to writable by you automatically upon opening. This code does the trick:
(defun change-file-permissions-to-writable ()
"to be run from find-file-hook, change write permissions"
(when (not (file-writable-p buffer-file-name))
(chmod buffer-file-name (file-modes-symbolic-to-number "u+w" (nth 8 (file-attributes buffer-file-name))))
(if (not (file-writable-p buffer-file-name))
(message "Unable to make file writable."))))
(add-hook 'find-file-hook 'change-file-permissions-to-writable)
Note: When I tested it on my Windows machine, the file permissions didn't show up until I tried to save the buffer, but it worked as expected. I personally feel uneasy about this customization, but it's your Emacs. :)
I agree with Trey that universally doing a chmod on write is risky -- read-only files are read-only for a reason, IMHO. Here's a way to specifically override things on a per-buffer basis. It's not ideal in that it overrides file-writable-p for the life of the buffer (or at least until you toggle my-override-mode-on-save back to nil), but it makes you make a conscious decision on a file-by-file basis (sort-of; it's really a buffer-by-buffer basis, which is fairly similar). Of course since you're looking to automatically toggle the read-only flag when the file is visited, you might not be interested in this distinction. Still, here it is; enjoy it or ignore it as you will.
(make-variable-buffer-local
(defvar my-override-mode-on-save nil
"Can be set to automatically ignore read-only mode of a file when saving."))
(defadvice file-writable-p (around my-overide-file-writeable-p act)
"override file-writable-p if `my-override-mode-on-save' is set."
(setq ad-return-value (or
my-override-mode-on-save
ad-do-it)))
(defun my-override-toggle-read-only ()
"Toggle buffer's read-only status, keeping `my-override-mode-on-save' in sync."
(interactive)
(setq my-override-mode-on-save (not my-override-mode-on-save))
(toggle-read-only))
P.S. Thanks to Trey for the ad-return-value pointer in the other SO question.
Since I find it useful to be constantly reminded that I am about to edit a file I do not have permissions to, when I open a file in a buffer I want to force myself to proactively make the buffer writable wit C-x q. Opening it with tramp by hand however is quite tedious so I advise save-buffer to prompt me for password if it fails to write. I totally recommend you put this snippet in your .emacs
(defadvice save-buffer (around save-buffer-as-root-around activate)
"Use sudo to save the current buffer."
(interactive "p")
(if (and (buffer-file-name) (not (file-writable-p (buffer-file-name))))
(let ((buffer-file-name (format "/sudo::%s" buffer-file-name)))
ad-do-it)
ad-do-it))
For a reason I could no determine the Trey Jackson solution does not work on my gnu emacs 25.2 under windows: the file-modes-rights-to-number called from file-modes-rights-to-number fails.
If someone is stuck with the same problem he could use a less elegant but working solution replace block :
(chmod buffer-file-name (file-modes-symbolic-to-number "u+w" (nth 8 (file-attributes buffer-file-name))))
with block :
(cond ((or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
(progn
(shell-command-to-string (concat "attrib -R " (buffer-file-name (current-buffer))))
(message "Setting file and buffer to writeable (%s style)" system-type)
))
((eq system-type 'gnu/linux)
(progn
(shell-command-to-string (concat "chmod u+w " (buffer-file-name (current-buffer))))
(message "Setting file and buffer to writeable (%s style)" system-type)
))
(t (message "file permission change not handle for OS %s" system-type))
)

Automatically closing the scratch buffer

What I must write in my .emacs file so that the *scratch* buffer is closed when I open Emacs?
(kill-buffer "*scratch*")
Not exactly the answer to your question, but you might like to know that you can choose to have a different buffer open on startup, or change the contents of the *scratch* buffer. For example:
;; Make *scratch* buffer blank.
(setq initial-scratch-message nil)
;; Make the buffer that opens on startup your init file ("~/.emacs" or
;; "~/.emacs.d/init.el").
(setq initial-buffer-choice user-init-file)
In the first example, the *scratch* buffer will be empty. In the second example, the *scratch* buffer will still exist, but user-init-file will be focused.
You can customize:
initial-buffer-choice
I set it to my homedir: "~/" to start in Dired mode.
I suspect from your question that you probably start emacs fairly often, perhaps even once for each file you want to edit. (If I'm wrong in this assumption, then the following comments don't apply to you.)
Emacs is designed to be started and then left running for weeks or months while you visit various files as you need to edit them. Emacs handles multiple files very well, so it's hardly even necessary to kill the associated buffers until you get 50 or 100 of them hanging around. I start emacs just after my window system starts, and it runs until my system shuts down or crashes. The initial scratch buffer is a non-problem in this mode, because I see it so infrequently.
I use this to kill the scratch buffer and open a new buffer in text mode called Untitled.
Found it on a newsgroup and modified it slightly.
(defun my-close-scratch ()
(kill-buffer "*scratch*")
(if (not (delq nil (mapcar 'buffer-file-name (buffer-list))))
(new-untitled-buffer)
))
(defun my-emacs-startup-hook ()
(my-close-scratch))
(add-hook 'emacs-startup-hook 'my-emacs-startup-hook)
(defun new-untitled-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "Untitled")))
(switch-to-buffer buf)
(normal-mode)
(setq buffer-offer-save t))
(add-hook 'kill-buffer-query-functions
'ask-to-save-modified nil t)
)
To close Untitled when opening files from filemanager when emacs is not open I use this:
(defun my-close-untitled ()
(if (get-buffer "Untitled")
(kill-buffers-by-name "Untitled")))
(add-hook 'find-file-hook 'my-close-untitled)
The proper way is to add inhibit-startup-screen to the custom-set-variables section of your .emacs file.
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(inhibit-startup-screen t)
)

Run sgml-pretty-print when opening an xml file in emacs?

I can currently use sgml-pretty-print to pretty print an xml file in emacs, but it's a manual process:
M-<
C-space
M->
M-x sgml-pretty-print
I'd like this to happen automatically (or at least have some option to do so). I'm new to emacs/elisp, and do not understand how:
emacs knows what code to run when you open a file (does this start in files.el?)
If you wanted to override that code with your own, how to do that
This should do the trick for you:
(add-hook 'find-file-hook 'my-sgml-find-file-hook)
(defun my-sgml-find-file-hook ()
"run sgml pretty-print on the file when it's opened (if it's sgml)"
(when (eq major-mode 'sgml-mode)
(sgml-pretty-print (point-min) (point-max))))
The key pieces of information are the find-file-hook, point-min (-max), and major-mode.
If you want to learn more about elisp, you can take a look at this question, which gives some pointers on how to figure things out.
A slightly simpler alternative to Trey Jackson's answer. Just add this to your ~/.emacs file:
(add-hook 'sgml-mode-hook #'(lambda ()
(sgml-pretty-print (point-min) (point-max))))

Emacs: reopen buffers from last session on startup?

Every day I start up emacs and open the exact same files I had open the day before. Is there something I can add to init.el file so it will reopen all the buffers I was using when I last quit emacs?
You can use the Emacs Desktop library:
You can save the desktop manually with
the command M-x desktop-save. You can
also enable automatic saving of the
desktop when you exit Emacs, and
automatic restoration of the last
saved desktop when Emacs starts: use
the Customization buffer (see Easy
Customization) to set
desktop-save-mode to t for future
sessions, or add this line in your
~/.emacs file:
(desktop-save-mode 1)
Although I suspect the question was looking for the emacs "desktop" functionality (see above answer), Lewap's approach can be useful if the set of files one uses really is the exact same file set. In fact, one can go a step further and define 'profiles' if one has different sets of regularly used files... Quickie example:
(let ((profile
(read-from-minibuffer "Choose a profile (acad,dist,lisp,comp,rpg): ")
))
(cond
((string-match "acad" profile)
(dired "/home/thomp/acad")
(dired "/home/thomp/acad/papers")
)
((string-match "lisp" profile)
(setup-slime)
(lisp-miscellany)
(open-lisp-dirs)
)
((string-match "rpg" profile)
(find-file "/home/thomp/comp/lisp/rp-geneval/README")
(dired "/home/thomp/comp/lisp/rp-geneval/rp-geneval")
... etc.
If you find that you regularly switch back and forth between different sets of regularly-used files as you work, consider using perspectives and populating each perspective with the desired set of regularly-used files.
For storing/restoring the buffers/tabs (specifically elscreen tabs): I use elscreen and the way I manage storing/restoring the desktop session and the elscreen tab configuration is the following code in my .emacs file (the names used are self-explanatory and if the storing/restoring functions should not be executed every time emacs starts just comment out the lines with "(push #'elscreen-store kill-emacs-hook)" and "(elscreen-restore)"):
(defvar emacs-configuration-directory
"~/.emacs.d/"
"The directory where the emacs configuration files are stored.")
(defvar elscreen-tab-configuration-store-filename
(concat emacs-configuration-directory ".elscreen")
"The file where the elscreen tab configuration is stored.")
(defun elscreen-store ()
"Store the elscreen tab configuration."
(interactive)
(if (desktop-save emacs-configuration-directory)
(with-temp-file elscreen-tab-configuration-store-filename
(insert (prin1-to-string (elscreen-get-screen-to-name-alist))))))
(push #'elscreen-store kill-emacs-hook)
(defun elscreen-restore ()
"Restore the elscreen tab configuration."
(interactive)
(if (desktop-read)
(let ((screens (reverse
(read
(with-temp-buffer
(insert-file-contents elscreen-tab-configuration-store-filename)
(buffer-string))))))
(while screens
(setq screen (car (car screens)))
(setq buffers (split-string (cdr (car screens)) ":"))
(if (eq screen 0)
(switch-to-buffer (car buffers))
(elscreen-find-and-goto-by-buffer (car buffers) t t))
(while (cdr buffers)
(switch-to-buffer-other-window (car (cdr buffers)))
(setq buffers (cdr buffers)))
(setq screens (cdr screens))))))
(elscreen-restore)
There are useful enhancements you can make to the basic desktop feature. Particular handy (IMO) are methods of auto-saving the desktop during the session, as otherwise if your system crashes you will be stuck with the desktop file you had started that session with -- pretty annoying if you tend to keep Emacs running for many days at a time.
http://www.emacswiki.org/emacs/DeskTop
The wiki also has useful information about persisting data between sessions in general:
http://www.emacswiki.org/emacs/SessionManagement
For desktops specifically, I thought that Desktop Recover looked particularly promising, however I've not yet tried it out.
(find-file-noselect "/my/file") will open it silently, ie w/o raising the buffer. Just saying.
EDIT This command is not interactive ; To test it you have to evaluate the expression, for example by positioning the cursor after the last parenthesis and hitting C-x C-e
Downvoting this is not cool ; this command definitely works and is in the scope of the question.