How do I change read/write mode for a file using Emacs? - emacs

If a file is set to read only mode, how do I change it to write mode and vice versa from within Emacs?

M-x read-only-mode
in very old versions of Emacs, the command was:
M-x toggle-read-only
On my Windows box, that amounts to Alt-x to bring up the meta prompt and typing "read-only-mode" to call the correct elisp function.
If you are using the default keyboard bindings,
C-x C-q
(which you read aloud as "Control-X Control-Q") will have the same effect. Remember, however, given that emacs is essentially infinitely re-configurable, your mileage may vary.
Following up from the commentary: you should note that the writeable status of the buffer does not change the writeable permission of the file. If you try to write out to a read only file, you'll see a confirmation message. However, if you own the file, you can write out your changes without changing the permissions on the file.
This is very convenient if you'd like to make a quick change to a file without having to go through the multiple steps of add write permission, write out changes, remove write permission. I tend to forget that last step, leaving potentially critical files open for accidental changes later on.

Be sure you're not confusing 'file' with 'buffer'. You can set buffers to read-only and back again with C-x C-q (toggle-read-only). If you have permission to read, but not write, a file, the buffer you get when you visit the file (C-x C-f or find-file) will be put in read-only mode automatically. If you want to change the permissions on a file in the file system, perhaps start with dired on the directory that contains the file. Documentation for dired can be found in info; C-h i (emacs)dired RET.

What I found is M-x set-file-modes filename mode
It worked at my Windows Vista box.
For example: M-x set-file-modes <RET> ReadOnlyFile.txt <RET> 0666

As mentioned up there by somebody else: M-x toggle-read-only would work.
However, this is now deprecated and M-x read-only-mode is the current way to do it, that it is set to C-x C-q keybinding.

CTRL + X + CTRL + Q

If only the buffer (and not the file) is read-only, you can use toggle-read-only, which is usually bound to C-x C-q.
If the file itself is read-only, however, you may find the following function useful:
(defun set-buffer-file-writable ()
"Make the file shown in the current buffer writable.
Make the buffer writable as well."
(interactive)
(unix-output "chmod" "+w" (buffer-file-name))
(toggle-read-only nil)
(message (trim-right '(?\n) (unix-output "ls" "-l" (buffer-file-name)))))
The function depends on unix-output and trim-right:
(defun unix-output (command &rest args)
"Run a unix command and, if it returns 0, return the output as a string.
Otherwise, signal an error. The error message is the first line of the output."
(let ((output-buffer (generate-new-buffer "*stdout*")))
(unwind-protect
(let ((return-value (apply 'call-process command nil
output-buffer nil args)))
(set-buffer output-buffer)
(save-excursion
(unless (= return-value 0)
(goto-char (point-min))
(end-of-line)
(if (= (point-min) (point))
(error "Command failed: %s%s" command
(with-output-to-string
(dolist (arg args)
(princ " ")
(princ arg))))
(error "%s" (buffer-substring-no-properties (point-min)
(point)))))
(buffer-substring-no-properties (point-min) (point-max))))
(kill-buffer output-buffer))))
(defun trim-right (bag string &optional start end)
(setq bag (if (eq bag t) '(?\ ?\n ?\t ?\v ?\r ?\f) bag)
start (or start 0)
end (or end (length string)))
(while (and (> end 0)
(member (aref string (1- end)) bag))
(decf end))
(substring string start end))
Place the functions in your ~/.emacs.el, evaluate them (or restart emacs). You can then make the file in the current buffer writable with M-x set-buffer-file-writable.

If you are looking at a directory of files (dired), then you can use Shift + M on a filename and enter the modespec, the same attributes used in the chmod command.
M modespec <RET>
See the other useful commands on files in a directory listing at
http://www.gnu.org/s/libtool/manual/emacs/Operating-on-Files.html

I tried out Vebjorn Ljosa's solution, and it turned out that at least in my Emacs (22.3.1) there isn't such function as 'trim-right', which is used for removing an useless newline at the end of chmod output.
Removing the call to 'trim-right' helped, but made the status row "bounce" because of the extra newline.

C-x C-q is useless. Because your also need the permission to save a file.
I use Spacemacs. It gives me a convenient function to solve this question. The code is following.
(defun spacemacs/sudo-edit (&optional arg)
(interactive "p")
(if (or arg (not buffer-file-name))
(find-file (concat "/sudo:root#localhost:" (ido-read-file-name "File: ")))
(find-alternate-file (concat "/sudo:root#localhost:" buffer-file-name))))
I call spacemacs/sudo-edit to open a file in emacs and input my password, I can change the file without read-only mode.
You can write a new function like spacemacs/sudo-edit.

Related

Execute a particular command on multiple emacs buffers

Is there a way to execute emacs command on multiple buffers without having to selecting them individually and executing it on each individual buffer.
I usually open multiple files matching a particular regex, e.g. ~/*.py and wish to enable a particular mode, say hs-minor-mode or glasses-mode on each, or say execute C-c # C-M-h on each. Currently I have to select each one of them and do it individually. So is there a hack or a loop to automate the task.
Lets say I mark the buffers from the buffer-list and then run the command for all those marked.
I tried this but after executing the commands in eval-expression I completely lost access to my minibuffer, meaning whenever I typed M-x the minibuffer returned this
unable to access the minibuffer emacs error "Process Menu Mode doesn't support Hideshow Minor Mode"
and I was forced to actually kill the entire emacs process because the C-x C-s wasn't working neither was the End Task.
PS: I have no experience in elisp
You can use ibuffer mode for this (It is part of the default Emacs distribution).
(global-set-key "\C-x\C-b" 'ibuffer) ;; make ibuffer the default
In *Ibuffer* you can mark the required buffers with m and then
execute a form in each with E.
Generally, ibuffer is a lot more flexible then the usual buffer list and I think ibuffer should really be the default buffer-list in Emacs.
If you do this often, you might want to switch those particular modes on every time you enter python mode by attaching them to the mode-hook:
(add-hook 'python-mode-hook 'hs-minor-mode)
(add-hook 'python-mode-hook 'glasses-mode)
I didn't know ibuffer had that feature!
Anyway, for those who are more familiar with dired, here is a command that do the same. Select the files in dired with m or any other more powerful method. Then do, M-xdired-do-command and write a form or a command just as in M-x.
(defun dired-do-command (command)
"Run COMMAND on marked files. Any files not already open will be opened.
After this command has been run, any buffers it's modified will remain
open and unsaved."
(interactive
(list
(let ((print-level nil)
(minibuffer-history-position 0)
(minibuffer-history-sexp-flag (1+ (minibuffer-depth))))
(unwind-protect
(read-from-minibuffer
"Command: " (prin1-to-string (nth 0 command-history))
read-expression-map t
(cons 'command-history 0))
;; If command was added to command-history as a
;; string, get rid of that. We want only
;; evaluable expressions there.
(if (stringp (car command-history))
(setq command-history (cdr command-history)))))))
(dolist (filename (dired-get-marked-files))
(with-current-buffer (find-file-noselect filename)
(if (symbolp command)
(call-interactively command)
(eval command)))))

Refactoring in Emacs

I am working on splitting code into smaller files and refactoring it a bit. Consider the following code below as the section I want to extract:
(require 'package)
(add-to-list 'package-archives
'("marmalade" . "http://marmalade-repo.org/packages/") t)
(package-initialize)
(when (not package-archive-contents)
(package-refresh-contents))
(defvar my-packages '(org magit)
"A list of packages to ensure are installed at launch.")
(dolist (p my-packages)
(when (not (package-installed-p p))
(package-install p)))
I want to take the section above and replace it with something like (require `file-name)
Then take the text replaced and place that in a new file in the current directory named file-name.el
And then add a line to the top of the file (provides `file-name)
It would be great if I could hit a keychord and then type a name and have this happen. If there is an easy way to do this then I would love to hear possible solutions.
Edit:
I'm starting a bounty because I think this applies to more types of code than Lisp and I would like to have something a little more general that I can expand upon.
I have considered yasnippet but I don't think it's powerful enough to perform the task at hand. Basically the ideal workflow would be marking the lines to be extracted, replacing that with an appropriate require or include directive and sending the text off to it's own file. Ideally one command and something that is aware of the type of file being edited or at least the major mode so the behavior can be customized, again yasnippet is good at performing different tasks when editing in different major modes however I would have no idea how to make that work or evaluate the possibility of making it work.
Let me know if you need any more information.
A general solution to this type of problem are keyboard macros (not to be confused with (Emacs) LISP macros). Basically Emacs allows you to record a sequence of keystrokes and "play them back" afterwards. This can be a very handy tool in situations where writing custom LISP code seems overkill.
For instance you could create the following keyboard macro (type the key combinations on the left hand side, the right hand side shows explanations for each key stroke):
C-x ( ; start recording a keyboard macro
C-x h ; mark whole buffer
C-w ; kill region
(require 'file-name) ; insert a require statement into the buffer
C-x C-s ; save buffer
C-x C-f ; find file
file-name.el <RET> ; specify the name of the file
M-< ; move to the beginning of the buffer
C-u C-y ; insert the previously killed text, leaving point where it is
(provide 'file-name) <RET> <RET> ; insert a provide statement into the buffer
C-x ) ; stop recording the keyboard macro
Now you can re-play that macro in some other buffer by typing C-x e, or save it for later use. You can also bind a macro to a shortcut just like a function.
However, there is one weakness with this approach: you want to be able to actually specify the file-name, and not just use the string "file-name" every time. That is a bit difficult - by default, keyboard macros provide no general facility for querying the user (except the very minimal C-x q, as documented here).
The Emacs Wiki has some work-arounds for that, however, instead of prompting the user in the minibuffer, it can sometimes be sufficient to start the macro by killing the current line and saving its text to a register.
C-x (
C-e C-<SPC> C-a ; mark current line
C-x r s T ; copy line to register T
C-k C-k ; kill current line
... ; actual macro
C-x )
Now when you want to use your macro, you would first write the desired file-name in an otherwise empty line, and then do C-x e in that line. Whenever the value of the file-name is needed in the macro you can retrieve it from the register T:
C-x r i T ; insert file-name into buffer
For instance, for the provide statement in the above macro, you could write: (provide ' C-x r i T ). Note that this technique (inserting) also works in the minibuffer, and of course you could save multiple lines to different registers.
May sound complicated, but is actually quite easy in practice.
Slightly tested:
(defun extract-to-package (name start end)
(interactive (list (read-string "Package name to create: ")
(region-beginning) (region-end)))
(let ((snip (buffer-substring start end)))
(delete-region start end)
(insert (format "(require '%s)\n" name))
(with-current-buffer (find-file-noselect (concat name ".el"))
(insert snip)
(insert (format "(provide '%s)\n" name))
(save-buffer))))
For a such thing I use the following snippet (with yasnippet):
;; `(buffer-name)`
;; Copyright (C) `(format-time-string "%Y")` name
;; Author: name <email>
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of
;; the License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
$0
(provide '`(subseq (buffer-name) 0 (- (length (buffer-name)) 3))`)
1st create the file C-xC-ffile-name.elRET
then insert the snippet with C-c&C-s
and add any piece of code you wish.
I've also the following hook:
(add-hook 'after-save-hook 'autocompile)
(defun autocompile ()
"Byte compile an elisp."
(interactive)
(require 'bytecomp)
(let ((filename (buffer-file-name)))
(if (string-match "\\.el$" filename)
(byte-compile-file filename))))
to produce an .elc whenever I save a .el.
(defun region-to-file+require (beg end file append)
"Move region text to FILE, and replace it with `(require 'FEATURE)'.
You are prompted for FILE, the name of an Emacs-Lisp file. If FILE
does not yet exist then it is created.
With a prefix argument, the region text is appended to existing FILE.
FEATURE is the relative name of FILE, minus the extension `.el'."
(interactive "#*r\nG\nP")
(when (string= (expand-file-name (buffer-file-name)) (expand-file-name file))
(error "Same file as current"))
(unless (string-match-p ".+[.]el$" file)
(error "File extension must be `.el' (Emacs-Lisp file)"))
(unless (or (region-active-p)
(y-or-n-p "Region is not active. Use it anyway? "))
(error "OK, canceled"))
(unless (> (region-end) (region-beginning)) (error "Region is empty"))
(unless (or (not append)
(and (file-exists-p file) (file-readable-p file))
(y-or-n-p (format "File `%s' does not exist. Create it? " file)))
(error "OK, canceled"))
(write-region beg end file append nil nil (not append))
(delete-region beg end)
(let ((feature (and (string-match "\\(.+\\)[.]el$" file)
(match-string 1 file))))
(when feature
(insert (format "(require '%s)\n" feature)))))

How to open multiple terminals?

In Emacs, I often find myself in a situation where I need to jump back and forth between various source files to various terminals. However, I feel like I do not have a good way to do this efficiently and it's clumsy that you can only open one shell in Emacs (shell, eshell, or term).
Moreover, I need an efficient way of juggle between multiple terminals and source files.
How can I achieve this?
You can have as many terminals and shells open at once as you want. Just use M-x rename-buffer to change the name of an existing *term* or *shell* buffer, and the next time you do M-x term or M-x shell, a brand new buffer will be created. In the case of M-x shell, a prefix argument will cause you to be prompted for the name of the new shell buffer, as offby1 noted.
A few years ago I had a job where I had to regularly log in to various production servers named "host01.foo.com", "host02.foo.com", etc. I wrote a little function like this one to make it easier to manage them all:
(defun ssh-to-host (num)
(interactive "P")
(let* ((buffer-name (format "*host%02d*" num))
(buffer (get-buffer buffer-name)))
(if buffer
(switch-to-buffer buffer)
(term "/bin/bash")
(term-send-string
(get-buffer-process (rename-buffer buffer-name))
(format "ssh host%02d.foo.com\r" num)))))
Then I bound this command to (say) s-h (super H), enabling me to just type M-5 s-h. If I didn't already have a buffer named *host05*, it would start a new terminal emulator buffer, rename it to *host05*, and ssh me into host05.foo.com. If buffer *host05* already existed, it would simply switch me to it. Quite handy!
You can certainly have multiple interactive shells open. Try typing C-u M-x shell RET RET.
Try using MultiTerm to open multiple shells.
You can use Emacs Lisp Screen, which emulates GNU Screen and provides easy key bindings to jump to and between a number of different shells.
I use many methods for incorporating my terminal life into Emacs:
elscreen.el is a life saver, if you have a complicated window layout like gdb or have simply become overwhelmed with clutter you just open a new screen. In your case you could dedicate one screen to terminals.
multi-term.el makes managing terminals a bit easier.
shell-pop.el, a great tool for quick terminal access. shell-pop lets you assign a key to opening and closing a specific shell buffer window, if you've used drop-down terminals like tilda you know how incredibly handy this can be:
Here's and example of my shell-pop configuration, I use the key C-t to pop up an eshell:
(require 'shell-pop)
(shell-pop-set-internal-mode "eshell") ; Or "ansi-term" if you prefer
(shell-pop-set-window-height 60) ; Give shell buffer 60% of window
;; If you use "ansi-term" and want to use C-t
;; (defvar ansi-term-after-hook nil)
;; (add-hook 'ansi-term-after-hook
;; '(lambda ()
;; (define-key term-raw-map (kbd "C-t") 'shell-pop)))
;; (defadvice ansi-term (after ansi-term-after-advice (org))
;; (run-hooks 'ansi-term-after-hook))
;; (ad-activate 'ansi-term)
(global-set-key (kbd "C-t") 'shell-pop)
I usually do an an M-x server-start and then use emacsclient --no-wait to open files. I've aliased that to e with some embellishments so that it's a little more convenient.
I do all my work in a single terminal and just "throw" the files I want to edit into Emacs using e. Inside Emacs, I juggle around using iswitchb and it works just fine. YMMV.
I regularly used 10 or so shells in my old workplace. The secret is you have to rename additional shell buffers. I did this automatically though in my .emacs, creating and naming the shells logically (I had projnameRun and projnameBuild for every project). Worked really well together with anything, making it very easy to refind the right shell (you use the end of the project name combined with either r or b for run/build).
Instead of having several terminal windows in emacs, I spawn a different xterm whenever I need a new terminal. This of course is bearable because I use a very lightweight terminal emulator (urxvt) which starts in under 0.2s.
Then I use my window manager to switch between them and emacs frames. A configurable window manager will have plenty of options to tune to switch between windows (extremely) efficiently. Inside emacs, I use windmove and ido-mode, and have bound to C-tab a function that switches to the last buffer (because I use C-x b in that fashion a lot).
So um, not sure how useful it is to you since it's quite different from your use pattern, but this is what works for me.
I had exactly the same problem some years ago, and found nothing that satisfied me; so I wrote my own "toggle shell" function. It toggles between the current frame or window configuration and a system shell buffer. It can also put the shell into a dedicated frame, and inject a pushd to the current buffer directory.
This is an excerpt from my .emacs:
(defvar --toggle-shell-last-window-conf nil "The last window configuration.")
(defvar --toggle-shell-last-buf nil "The last buffer object in case there's no last window configuration.")
(defvar --toggle-shell-last-frame nil "The frame that was selected when opening a shell buffer.")
(defun --toggle-shell-have-conf ()
(window-configuration-p --toggle-shell-last-window-conf))
(defun --toggle-shell-store-last-conf ()
(setq --toggle-shell-last-buf (current-buffer)
--toggle-shell-last-frame (selected-frame)
--toggle-shell-last-window-conf (current-window-configuration)))
(defun --toggle-shell-restore-last-conf ()
(if (--toggle-shell-have-conf)
(progn (raise-frame --toggle-shell-last-frame)
(set-window-configuration --toggle-shell-last-window-conf))
(let ((bufnam (if (bufferp --toggle-shell-last-buf)
(buffer-name --toggle-shell-last-buf) --toggle-shell-last-buf)))
(if bufnam
(if (get-buffer bufnam) (switch-to-buffer bufnam t)
(message "%s: buffer not available" bufnam))))))
(defun --toggle-shell (&optional display inject-cd)
"Toggles between current buffers and a system shell buffer. With prefix-arg
close the shell.
When DISPLAY is 'vertical splits the shell as vertical window; when 'frame uses
a dedicated frame (default: single window). When INJECT-CD executes a `pushd'
to the working directory of the buffer from which you toggled the shell."
(interactive)
(let* ((shell-buf (get-buffer "*shell*"))
(shell-window ; non-nil when currently displayed
(if shell-buf (get-buffer-window shell-buf t)))
(shell-frame
(if shell-window (window-frame shell-window)))
(in-shell (eq (current-buffer) shell-buf))
(vertical (string= display 'vertical))
(popup-frame (or (string= display 'frame)
(and inject-cd (not (bufferp shell-buf)))
(and (framep shell-frame)
(not (eq shell-frame (selected-frame)))))))
;; With prefix-arg close shell, restore windows. Otherwise (no prefix-arg)
;; toggle shell window; restore windows when called twice in a row, or the
;; current buffer is the shell buffer (`in-shell').
(if current-prefix-arg
(if (bufferp shell-buf)
(progn (message "Exiting shell '%s'" (buffer-name shell-buf))
(kill-buffer shell-buf)
(if in-shell (--toggle-shell-restore-last-conf)))
(error "No shell buffer to kill."))
;; If already in shell-buffer toggle back to stored frame-configuration.
(if (and in-shell (not inject-cd))
(progn
(--toggle-shell-restore-last-conf)
;; Recurse to reopen the shell-buffer in a dedicated frame, or
;; close the dedicated frame and reopen the buffer in a window.
(if (and popup-frame (eq shell-frame (selected-frame)))
(--toggle-shell 'frame inject-cd)
(when (and popup-frame shell-frame)
(delete-frame shell-frame)
(--toggle-shell nil inject-cd))))
;; Not in shell buffer. Warp to it or create new one.
(unless in-shell
(--toggle-shell-store-last-conf))
(if popup-frame
(progn (switch-to-buffer-other-frame (or shell-buf "*shell*"))
(raise-frame
(or shell-frame (window-frame (get-buffer-window "*shell*" t)))))
(if (> (count-windows) 1)
(delete-other-windows)))
;; Finally `cd' into the working directory the current buffer.
(let ((new-shell (not (bufferp shell-buf)))
(new-dir ; `default-directory' of `--toggle-shell-last-buf'
(if --toggle-shell-last-buf
(buffer-local-value 'default-directory --toggle-shell-last-buf))))
;; Open shell, move point to end-of-buffer. The new shell-buffer's
;; `default-directory' will be that of the buffer the shell was
;; launched from.
(when vertical
(if (> (count-windows) 1)
(delete-other-windows))
(split-window-vertically) (other-window 1))
(funcall 'shell)
(when new-shell
(message "New shell %s (%s)" (buffer-name (current-buffer)) new-dir)
(if inject-cd (sit-for 2))) ; wait for prompt
(goto-char (point-max))
;; If on a command-prompt insert and launch a "cd" command (assume no
;; job is running).
(when (and inject-cd new-dir)
(save-excursion
(backward-line-nomark) (end-of-line)
(unless (setq inject-cd (re-search-forward comint-prompt-regexp (point-max) t))
(error "Cannot `pushd', shell is busy")))
(when (and inject-cd)
(let* ((cmd (format
"pushd '%s' %s" (comint-quote-filename new-dir)
(if (buffer-file-name --toggle-shell-last-buf)
(format "# '%s'" (file-name-directory (buffer-file-name --toggle-shell-last-buf)))
""))))
;; `shell-process-cd' set new `default-directory' and set
;; `shell-last-dir' to old. (If the pushd command is
;; successful, a dirs is performed as well; >nul discards this
;; output.)
(shell-process-cd new-dir)
(insert cmd)
(comint-send-input)
(message "%s: cd '%s'" (buffer-name --toggle-shell-last-buf) new-dir))
)
)
)
)
)
)
)
--toggle-shell is the function that does the trick. I bind it to F12:
;; F12 toggle between shell buffer and current window configuration
;; SHIFT-F12 like before, but let shell buffer appear in a dedicated frame
;; ALT-F12 inject a pushd to change to directory of current buffer
;; CTRL-F12 `shell-command'
(global-set-key [(f12)] '--toggle-shell)
(global-set-key [(shift f12)] '(lambda()(interactive)(--toggle-shell 'frame)))
(global-set-key [(meta f12)] '(lambda()(interactive)(--toggle-shell nil t)))
(global-set-key [(meta f10)] '(lambda()(interactive)(--toggle-shell nil t)))
(global-set-key [(control f12)] 'shell-command) ; alias M-!
This is a significant bunch of code to be posted here. But it shall work well.
Semi related - you can quickly run a shell command on selected file with
M+shift+!
It saves a lot of time for smaller commands chmod etc
And maybe my quick pop-up shell also might help you. A quick pop-up shell for emacs
Ecb + eshell will be what you want exactly!
I use vi, but hope this helps. I can open as many terminals as I want by (eg. in Ubuntu 16.04):
ctrl + alt + t
I usually open 2 terminals, and move (position) one terminal to the right by:
ctrl + super + right-arrow
and move the other terminal to the left by:
ctrl + super + left-arrow
so that I have a divided screen by 2 terminals.

The function to show current file's full path in mini buffer

I need to get the full path of the file that I'm editing with emacs.
Is there a function for that?
If not, what would be the elisp function for getting that?
How can I copy the result (path name) to a clipboard so that I can reuse it?
I'm using Mac OS X and Aqumacs.
(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???
ADDED
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name))
(kill-new (file-truename buffer-file-name))
)
(global-set-key "\C-cz" 'show-file-name)
Combining the two answers that I got, I could get what I want. Thanks for the answers. And some more questions.
What's for (file-truename)?
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
It's the built-in function buffer-file-name that gives you the full path of your file.
The best thing to do is to have your emacs window to always show your system-name and the full path of the buffer you're currently editing :
(setq frame-title-format
(list (format "%s %%S: %%j " (system-name))
'(buffer-file-name "%f" (dired-directory dired-directory "%b"))))
You can also do something like this :
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name)))
(global-set-key [C-f1] 'show-file-name) ; Or any other key you want
To borrow from Jérôme Radix's answer, if you just want to quickly see the file path of the current buffer, you can do M-: buffer-file-name.
Alternately, type (buffer-file-name) in the buffer somewhere and run C-x C-e on the closing parenthesis (this will work in any mode, not just lisp-mode).
My trick is to do a C-x C-f like to open a file, it wil prefill the minibuff with the current file path, C-g to quit. Faster than M-: buffer-file-name but far far uglier than any other methods.
The direct implementation of what you want is:
(defun copy-full-path-to-kill-ring ()
"copy buffer's full path to kill ring"
(interactive)
(when buffer-file-name
(kill-new (file-truename buffer-file-name))))
That said, I find it incredibly useful to be able to get the full path of what is in the minibuffer, and this is what I use:
(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
"Try to resolve symbolic links into true paths."
(interactive)
(beginning-of-line)
(let* ((file (buffer-substring (point)
(save-excursion (end-of-line) (point))))
(file-dir (file-name-directory file))
(file-true-dir (file-truename file-dir))
(file-name (file-name-nondirectory file)))
(delete-region (point) (save-excursion (end-of-line) (point)))
(insert (concat file-true-dir file-name))))
And then if I want it in the clipboard, I just kill the line (C-a C-k). But we could easily copy the truename to the clipboard in the above command, just change the last line to be:
(insert (kill-new (concat file-true-dir file-name)))))
The new part is the call to 'kill-new which puts the string in the kill ring.
No need for extra function, just
M-! pwd
C-x C-b shows a list of buffers and the file path for each buffer where applicable.
C-x C-d, also callable via M-x list-directory, will show you the directory for your current file, and you only need to hit the "Enter" key to clear the minibuffer. Additional details are available here.
I have the following code already in use for a long time.
It copies the full file path to the kill ring when I press the middle mouse button on the buffer name in the mode-line. It copies just the buffer name to the kill-ring when I press shift-mouse-2 on the buffer-name in the mode-line.
(defun copy-buffer-file-name (event &optional bufName)
"Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
(interactive "eP")
(save-selected-window
(message "bufName: %S" bufName)
(select-window (posn-window (event-start event)))
(let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
(message "Saved file name \"%s\" in killring." name)
(kill-new name)
name)))
(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))
C-u C-x C-b lists buffers currently visiting files.
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
You can if you shell out to something like xclip (Linux), pbcopy (Mac), putclip (Cygwin).
I personally use wrapper scripts c and p for copy and paste respectively, the first reading from standard input, the latter writing to standard output. That way, this works on all my development platforms:
(shell-command (format "echo '%s' | c" buffer-file-name))
I find this more reliable and configurable than using the Emacs clipboard support. For example, my c command copies the input to all 3 clipboards on Linux (primary, secondary, clipboard), so I can paste with either Ctrl-V or middle click.
The simplest way and would be
(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area
(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>
Borrowing from Trey Jackson
I came up with this:
(defun buffer-kill-path ()
"copy buffer's full path to kill ring"
(interactive)
(kill-new (buffer-file-name)))
You can find more information on site
copy-buffer-file-name-as-kill from [0] does exactly what you need I think. It also has the option to copy just directory name, or just file name.
[0] http://www.emacswiki.org/emacs/download/buffer-extension.el
To do what the title says (show the current file path in the minibuffer) you can do this:
M-x buffer-file-name
To permanently show it in the mode-line, you can use this:
(setq-default mode-line-buffer-identification
(list 'buffer-file-name
(propertized-buffer-identification "%12f")
(propertized-buffer-identification "%12b")))
Or this (color + abbrev) :
(setq-default mode-line-buffer-identification
'((:eval
(list (propertize (abbreviate-file-name
(expand-file-name buffer-file-name))
'face 'font-lock-string-face)))))

How to format all files under a dir in emacs?

In emacs, I format a file as:
1) C-x h (or M-x mark-whole-buffer)
2) C-M-\ (or M-x indent-region)
I need help show me how to format all files under a dir?
Here's another way to go about it:
First, evaluate this function definition in your *scratch* buffer:
(defun indent-marked-files ()
(interactive)
(dolist (file (dired-get-marked-files))
(find-file file)
(indent-region (point-min) (point-max))
(save-buffer)
(kill-buffer nil)))
Next, open a Dired buffer at the top level of the directory under which you want to change all of the files. Give the dired command a numeric prefix so that it will ask for the switches to give to the ls command, and add the R (recurse) switch: C-u C-x d R RET your-directory RET.
Next, mark all of the regular files in the recursive directory listing: first * / to mark all the directories, then * t to toggle the selection.
Finally, run the above command: M-x indent-marked-files.
Be aware that if you already have any buffers visiting any of the target files, they'll be killed by indent-marked-files. Also be aware that none of the file changes will be undoable; use with caution! I tested it in a simple case and it seems to work as described, but I make no guarantees.
Create a macro to do it. Open the directory in dired (C-x d), and then:
Put point on the first file.
Press F3 to start recording the macro.
Hit RET to open the file.
Format it with C-x h, C-M-\.
Bury the buffer with M-x bury-buffer. You'll be back in the dired buffer.
Go down one line.
Hit F4 to stop recording the macro.
So now you have a macro that opens the file on the current line, formats it, drops back to dired, and puts point to the next line. Run it with F4 as many times as needed.
I am late in answering this question, but this is still the first result on Google.
I made an improvement to #Sean's answer to remove the need for the complicated Dired interaction.
(defun my/indent-files (directory extension)
(interactive (list (read-directory-name "Directory: ")
(read-string "File extension: ")))
(dolist (file (directory-files-recursively directory extension))
(find-file file)
(indent-region (point-min) (point-max))
(save-buffer)
(kill-buffer nil)))
Sample use: M-x my/indent-files then ~/Dropbox then .org.
This will run indent-region on the all .org files, save the buffer then kill it.
You can try this:
(defun format-all-files (regexp)
"Format multiple files in one command."
(interactive "sFind files matching regexp (default all): ")
(when (string= "" regexp) (setq regexp ""))
(let ((dir (file-name-directory regexp))
(nodir (file-name-nondirectory regexp)))
(when dir (cd dir))
(when (string= "" nodir) (setq nodir "."))
(let ((files (directory-files "." t nodir nil t))
(errors 0))
(while (not (null files))
(let ((filename (car files)))
(if (file-readable-p filename)
(progn
(set-buffer (find-file-noselect filename))
(mark-whole-buffer)
(indent-region-or-balanced-expression)
(save-buffer)
(kill-buffer (current-buffer)))
(incf errors))
(setq files (cdr files))))
(when (> errors 0)
(message (format "%d files were unreadable." errors))))))
But note that this must load the file-specific mode over and over again, which may involve syntax highlighting or whatever initialization happens on a load of that type. For really big formatting jobs, a batch program such as indent which only indents will be much faster.