Any editor/IDE that supports or could be hacked to support viewing diffs live while editing? - vim

Is there any editor/IDE that provides a live view of differences (probably using diff) while I am editing a file. The ideal setting would be when I open a file for editing in such a diff-mode, the file is buffered in two independent panes (but put side by side), so that when I edit the contents of one, the differences of the two are highlighted for me.

There doesn't seem to be an existing Emacs mode to do exactly what you want, but a cursory googling turned up this and this.
From the second one (with mildly fixed formatting):
(defun diff-buffer-against-file (context)
"diff the current [edited] buffer and the file of the same name"
(interactive "P")
(let (($file buffer-file-name)
($tempFile "/tmp/emacs.diff")
($tempBuffer "emacs.diff"))
(delete-other-windows)
(push-mark (point) t)
(generate-new-buffer $tempFile)
(copy-to-buffer $tempBuffer (point-min) (point-max))
(set-buffer $tempBuffer)
(write-file $tempFile)
(shell-command (concat (if context "diff -c " "diff ") $file " " $tempFile))
(kill-buffer $tempFile)
(pop-mark)))
(global-set-key "\C-cd" 'diff-buffer-against-file)
The operation looks a bit too intense to bind to a change hook, but there's nothing preventing you from doing so if you're into that sort of thing.
Edit: Stefan points out that diff-buffer-with-file exists, and has the behavior you're looking for (it takes a buffer, and diffs that buffer with its file, showing that output in an unfocused temporary buffer), so you don't even need to define the above. I did try it though, and the naive
(defun diff-current (start end len) (diff-buffer-with-file (current-buffer)))
(add-hook 'after-change-functions 'diff-current)
makes editing too uncomfortable for my tastes. You'll probably want to follow Stefan's suggestion and use a timeout instead of diffing immediately on every change.

Related

emacs run shell command against current buffer's file name [duplicate]

I can run a shell command quickly by hitting M-!. One thing I'd like to do is perform shell quick operations on the current file. An example would be checking the file out through perforce:
M-! p4 edit buffer-file-name RET
(Yes there are perforce integrations, but I'm more interested in the minishell/variable problem rather than a specific workflow)
Of course, the buffer-file-name variable is not evaluated before the command is sent to the shell.
Is there an easy on-the-fly way to do this? Or will I have to roll a custom elisp function?
It seems current Emacs has something built-in to achieve the desired result, after M-! (shell-command) press <down>, you will get the file name you are currently visiting on the prompt. Now you can edit it to add the command you want to run on it.
In dired-mode it will give you the file your cursor is currently on.
Indeed using C-u M-: is almost right. I'm not so sure about using shell-quote-argument in eval-to-shell-argument since it only works on strings making it impossible to use eval-to-shell-argument to insert a number or a symbol. You could try something like:
(defun sm-minibuffer-insert-val (exp)
(interactive
(list (let ((enable-recursive-minibuffers t))
(read-from-minibuffer "Insert: "
nil read-expression-map t
'read-expression-history))))
(let ((val (with-selected-window (minibuffer-selected-window)
(eval exp)))
(standard-output (current-buffer)))
(prin1 val)))
and then bind this function in your minibuffer with (define-key minibuffer-local-map [?\M-:] 'sm-minibuffer-insert-val).
Of course, if the only thing you ever want to insert is the buffer-file-name, then your execute-shell-command-on-buffer is simpler.
I did roll my own elisp function, and it looks like this:
(defun execute-shell-command-on-buffer (shell-command-text)
(interactive "MShell command:")
(shell-command (format shell-command-text (shell-quote-argument buffer-file-name)))
)
https://gist.github.com/2367513
I bound it to M-", so now my example can be completed with:
M-"p4 edit %sRET
I won't accept this as the answer, because I did ask for solutions that don't require a function.
You can use C-u M-: (eval-expression with a universal prefix argument) to evaluate any Lisp expression and insert its value at point in the current buffer (including minibuffers, as long as you have enable-recursive-minibuffers set to a non-nil value).
In your example: C-u M-: buffer-file-name RET.
Note that the result of the expression is printed in Lisp form: that is, quoted in such a way that a subsequent call to read would construct an equal Lisp value. For strings, this means enclosing in double quotes, which will probably be interpreted as you expect by the inferior shell. However, you may run into problems with strings that contain special characters, which need different escaping by Elisp and the shell.
The more correct way uses shell-quote-argument, as in phils' solution. Here's a quick defun that reads a Lisp expression and inserts its value at point as a properly quoted shell word:
(defun eval-to-shell-argument (form)
(interactive "XEval: ")
(insert (shell-quote-argument form)))
The read-and-evaluate step happens automatically by using an "X" as the argument to interactive.
Edited to add: As #tenpn notes, the above solution doesn't work for inserting buffer-local variables like buffer-file-name in a minibuffer like the one M-! pops up (more precisely, it inserts the buffer-local value of the minibuffer, which is unlikely to be useful). Here is a revised version which seems to work. If the minibuffer is active, it makes the buffer of the previously-selected window temporarily active while reading and evaluating an expression.
Final edit: From #Stefan's answer I see that I should have used (minibuffer-selected-window) to find the previously-selected window. I've also added a (format "%s" ..) to allow inserting non-string values, while still quoting special characters in strings. Here's the final version:
(defun eval-to-shell-argument ()
(interactive)
(let* ((buffer
(if (minibufferp)
(window-buffer (minibuffer-selected-window))
(current-buffer)))
(result
(with-current-buffer buffer
(eval-minibuffer "Eval: "))))
(insert (shell-quote-argument (format "%s" result)))))
You can't do that with M-!, but you can evaluate arbitrary elisp from the minibuffer, so writing a function isn't strictly necessary:
M-: (shell-command (format "p4 edit %s" (shell-quote-argument buffer-file-name))) RET
In this case however, I think eshell is what you want to use:
M-x eshell-command RET p4 edit (eval buffer-file-name) RET
Edit: Except unfortunately that doesn't work, as the *eshell cmd* buffer is selected when that is evaluated. One solution would be:
M-x eshell-command RET p4 edit (eval buffer-file-name (other-buffer nil t)) RET
(Not quite as elegant, sorry.)
Everyone seems to be rolling their own version, so here's mine -- it will substitue the current filename or marked dired-files or current dired file wherever a % is in the shell command. It follows the same conventions as M-! so I bind it to that.
(defun my-shell-command (command &optional output-buffer error-buffer)
"Run a shell command with the current file (or marked dired files).
In the shell command, the file(s) will be substituted wherever a '%' is."
(interactive (list (read-from-minibuffer "Shell command: "
nil nil nil 'shell-command-history)
current-prefix-arg
shell-command-default-error-buffer))
(cond ((buffer-file-name)
(setq command (replace-regexp-in-string "%" (buffer-file-name) command nil t)))
((and (equal major-mode 'dired-mode) (save-excursion (dired-move-to-filename)))
(setq command (replace-regexp-in-string "%" (mapconcat 'identity (dired-get-marked-files) " ") command nil t))))
(shell-command command output-buffer error-buffer))

Vim: load changes from previous unsaved session

I have edited file X and closed the file without saving it. Now when I try to open file X vim alerts "No write since last change...".
Is there a way to get those changes back?
Below explanation from :help message
*E37* *E89*
No write since last change (add ! to override)
No write since last change for buffer {N} (add ! to override)
You are trying to |abandon| a file that has changes. Vim protects you from
losing your work. You can either write the changed file with ":w", or, if you
are sure, |abandon| it anyway, and lose all the changes. This can be done by
adding a '!' character just after the command you used. Example: >
:e other_file
changes to: >
:e! other_file
*E162*
No write since last change for buffer "{name}"
This appears when you try to exit Vim while some buffers are changed. You
will either have to write the changed buffer (with |:w|), or use a command to
abandon the buffer forcefully, e.g., with ":qa!". Careful, make sure you
don't throw away changes you really want to keep. You might have forgotten
about a buffer, especially when 'hidden' is set.
[No write since last change]
This appears when executing a shell command while at least one buffer was
changed. To avoid the message reset the 'warn' option.

Change Emacs window appearance when it loses focus

When I program I use two screens with Emacs on both with two buffers split in each window totaling 4 open source files on screen at any one time.
I switch between buffers with C-x b and between Windows with Alt-TAB. I change the appearance of buffers when I switch between them by defining different faces for mode-line and mode-line-inactive. But how do I inactivate a buffer when I switch from the Emacs window completely to another Emacs window via Alt-TAB?
It's probably also relevant that I'm using Emacs 23.2.1 on Ubuntu 11.04 with Gnome 2.32.1.
PS: The question How to automatically save files on lose focus in Emacs is after a different goal but with the same original event of "window losing focus".
It may depend on your window manager and how it manages multiple windows, or frames, in emacs parlance. The code below works like a champ in fvwm but not always in gnome.
I map a keystroke, C-o, to go between frames, this helps when you want to go to the other frame but an alt-tab would take you through a number of superfluous apps on the way.
If you're running a single instance of emacs with two frames you could use something like the following:
(defun pgr-previous-frame ()
"go to the previous frame"
(interactive)
(pgr-switch-frame (previous-frame)))
(defun pgr-next-frame ()
"go to the next frame"
(interactive)
(pgr-switch-frame (next-frame)))
(defun pgr-switch-frame (frame)
"go to the specified frame and raise it"
;; reset the frame properties here
(select-frame frame)
(raise-frame frame)
;;change the display in some manner here
)
You could also try adding some advice to raise-frame and lower-frame haven't tried it but it's worth a try.
I really liked #logoscia answer, which allowed me to do this more generic version. It uses the mode-line-inactive face when no focus.
(add-hook 'focus-out-hook
(lambda ()
(copy-face 'mode-line '--mode-line-backup)
(copy-face 'mode-line-inactive 'mode-line)))
(add-hook 'focus-in-hook
(lambda ()
(copy-face '--mode-line-backup 'mode-line)))
In Emacs 24.4 and later, you can use focus-in-hook and focus-out-hook. This piece of code seems to work, such that the active window of an inactive frame has the same colour as an inactive window:
(defvar my-mode-line-active-background "gray75")
(defvar my-mode-line-inactive-background "gray40")
(defun my-unhighlight-mode-line ()
(set-face-attribute 'mode-line nil
:background my-mode-line-inactive-background))
(add-hook 'focus-out-hook 'my-unhighlight-mode-line)
(defun my-highlight-mode-line ()
(set-face-attribute 'mode-line nil
:background my-mode-line-active-background))
(add-hook 'focus-in-hook 'my-highlight-mode-line)
I don't know if it can be done only with Emacs, but a possible alternative is running wmctrl in a shell script which perodically checks which window has the focus and if there is a change then it lets Emacs know via emacsclient which can send lisp code to a running Emacs for evaluation:
-e'--eval'
Tell Emacs to evaluate some Emacs Lisp code, instead of visiting
some files. When this option is given, the arguments to
`emacsclient' are interpreted as a list of expressions to
evaluate, not as a list of files to visit.

Better window navigation in Emacs?

When I split window in emacs several times (under terminal) the whole screen is divided into several parts with hierarchical arrangement. In vim it is easy to switch between windows intuitively with Control-w + (h,j,k,l), but in Emacs I can only use Control-x + o to switch to "the other window", which probably would require several iterations to finally get to the window I intend. I wonder if there is a better way similar to that in Vim to easily navigate between windows?
Have you tried WindMove? It comes bundled with Emacs 21+. You move around with Shift-up, Shift-down, Shift-left, and Shift-right, though you can change the modifier. From the docs:
;; Installation:
;;
;; Put the following line in your `.emacs' file:
;;
;; (windmove-default-keybindings) ; shifted arrow keys
;;
;; or
;;
;; (windmove-default-keybindings 'hyper) ; etc.
;;
;; to use another modifier key.
;;
;;
;; If you wish to enable wrap-around, also add a line like:
;;
;; (setq windmove-wrap-around t)
I find the default binding for other-window to be really tedious, too. I've defined the following in my .emacs:
(global-set-key [(control ?,)] (lambda () (interactive) (other-window -1)))
(global-set-key [(control ?.)] (lambda () (interactive) (other-window 1)))
Just find some easy-to-reach keybindings (I use a Dvorak layout, so C-, and C-. may not be as easy for you to reach), preferably right next to each other, to bind to those lambdas.
Also, I found the Emacs wiki a few months ago. Nifty Tricks has a nice list of ways to make Emacs easier to use!
In Icicles, by default C-x o is bound to the multi-command icicle-other-window-or-frame, which works this way:
With no prefix arg or a non-zero numeric prefix arg:
If the selected frame has multiple windows, then this is
other-window. Otherwise, it is other-frame.
With a zero prefix arg (e.g. C-0):
If the selected frame has multiple windows, then this is
icicle-select-window with windows in the frame as candidates.
Otherwise (single-window frame), this is icicle-select-frame.
With plain C-u:
If the selected frame has multiple windows, then this is
icicle-select-window with windows from all visible frames as
candidates. Otherwise, this is icicle-select-frame.
Well then, what are icicle-select-window and icicle-select-frame?
They are multi-commands that let you choose a window or frame to select by name. (You can bind them separately, if you want -- they each change their behavior based on their own prefix args.)
Window and frame names are taken from their displayed buffers, with [N] (N=1,2,...) appended if needed for a unique name if the same buffer is displayed in more than one window/frame.
Being multi-commands, you can choose by completing and/or cycling. Completion can be prefix, substring, regexp, or fuzzy.
http://www.emacswiki.org/emacs/Icicles_-_Multi-Commands
See switch-window. It will number windows to let you switch directly to the one you want.
That was also my first experience with emacs. But, using windmove, I can suite it, they way I want it. I use this as the modifier for windmove :
(windmove-default-keybindings 'meta)
I use ALT for the navigation of windmove

How to open files in web browsers (e.g Firefox) within editors like vim or emacs?

How to open files in browsers (e.g Firefox) within editors like vim or emacs? Notepad++ open files in browsers by pressing Ctrl+Shift+Alt+X (Firefox). Is there a way to do this in gVim or Emacs?
browse-url-of-file is an interactive compiled Lisp function in
`browse-url.el'.
It is bound to <menu-bar> <HTML> <Load this Buffer in Browser>, C-c
C-z v.
(browse-url-of-file &optional file)
Ask a WWW browser to display file.
Display the current buffer's file if file is nil or if called
interactively. Turn the filename into a URL with function
browse-url-file-url. Pass the URL to a browser using the
browse-url function then run browse-url-of-file-hook.
In emacs I don't think this is built in, I may be wrong, but if not here is a function to do it:
(defun open-in-browser()
(interactive)
(let ((filename (buffer-file-name)))
(browse-url (concat "file://" filename))))
For whatever reason, my EmacsW32 on WinXP install kept sending browse-url directives to shell with "open file:// alone, and that didn't work so well*. Cutting it off at the knees, and modifying justin's original as below worked for me:
(defun open-in-browser()
"open buffer in browser, unless it is not a file. Then fail silently (ouch)."
(interactive)
(if (buffer-file-name)
(let ((filename (buffer-file-name)))
(shell-command (concat "start firefox.exe \"file://" filename "\"")))))
Needs some improvement. As well as replacement of your favorite browser. d**n you, hard-coding.
* I think the problem was the system-type check in browse-url-default-windows-browser, but not positive.
In gVim:
:!start cmd /c "C:\Users\pierre\AppData\Local\Google\Chrome\Application\chrome.exe" file:///"%:p""
You need the file:// URI to indicate that it is from the file system, this will work with all browsers. %:p produces the full file path for the current file. The quotes are necessary.
Simply map that to whatever you choose. You may need to do set shell=cmd.exe if you've set your shell to bash or something else.
In emacs (quoting justinhj):
(defun open-in-browser()
(interactive)
(let ((filename (buffer-file-name)))
(browse-url (concat "file://" filename))))
You mean you'd like to open the file currently being edited in a web browser?
In Vim, use something like :!firefox %.
Edit: You could, in fact, use nmap <silent> <C-M-X> :!firefox %<CR> to cause Vim to act very much like Notepad++ (though this mapping won't care whether you press shift or not).
Note that not every browser will actually render the file's contents when given the filename on the command line; e.g. Google Chrome will open a "save as" dialogue instead, as if you were downloading the file in question. Look up your browser's docs if in doubt. Firefox will 'just work', though.
Depending what you want to do with this, you might consider Emacs + MozRepl, which basically lets you send javascript commands to Firefox via telnet. Unfortunately I can't seem to write the elisp to make this work, but a related trick for reloading webpages from within emacs is shown by Sard in What's in your .emacs?. More information on integrating emacs and mozrepl from the original source and also here for a cool trick that updates the page in the browser as you type in the emacs buffer - it's pretty nice for getting instant feedback when working with html.
I reckon the same thing would work with vim, but I've only used it in emacs.
I do it an Elisp function using shell command xdg-open.
Then I define a key in html-mode to call the function.
You've gotta be comfortable adding stuff to your .emacs file.
(defun open-html()
"Get the HTML file path & open it"
(interactive)
(let (html-file-path)
(setq html-file-path (buffer-file-name))
(shell-command (format "xdg-open '%s'" html-file-path)))
)
This answer is based on Emacs 26.2
Emacs has the functions for opening a file in a browser built in but the behavior on different platforms may be different. Looking into the source code and documentation of browse-url-of-file by entering C-h f browse-url-of-file you'll see that the variable browse-url-browse-function determines which browser is used. You can then customize this variable to use, say, Chrome, by choosing browse-url-chrome and then apply and save the change. To access the customization page either entering C-h f browse-url-browser-function and then selecting the customize hyperlink, or M-x customize then searching for browse-url-browser-function.

Resources