views:

461

answers:

2

I want open a path to vim from Screen's copy-mode by

Ctrl-A f

similarly as I can open external files in Vim by

Ctrl-W f

How can you open a path in Vim in Screen's copy-mode?


--- Thank you for Samuil to get the crux move

Let's assume mouse is at PATH/file in the following code which represents display when Screen is on

text[space]PATH/file[space]text

I press ^A f at PATH/file. It should save the PATH of the file to /tmp/screenCopyFile such that we can use cat in the following command which the ^A f should start:

^A: exec vim `cat PATH/file`

I run the command manually unsuccessfully. It did not expand the cat command, but it opens a file called cat.

In other words, we want to make the letter f stands for

exec vim `cat /tmp/screenCopyFile`

by binding in .screenrc.

Thank you Rampion for your answer!

+1  A: 

I do not know vim too good, but with a few commands it should be done easily. When you already have filename in your pastebuffer, you can use these useful commands:

^A : writebuf /tmp/.screenpomfile
^A : exec vim parameters

I do not know how to make vim read filename from file (I think it is possible), but you could :exec your own script written in a shell able to parse `expr ` expressions:

#!/bin/sh
vim `cat /tmp/.screenpomfile`

Later you can bind your own keys to these actions, and use them quite effectively.

samuil
@samuil: You can make Vim read filename from file by moving your cursor on top of the file with its exact path and press Ctrl-w f at normal mode.
Masi
@Masi: by "file" I didn't mean file opened with vim, but one saved on disk. Using this ^w f shortcut makes no sense in this case.
samuil
+1  A: 

Ok, here's a solution:

Put the following in /path/to/edit-file-under-cursor.screen:

# edit-file-under-cursor.screen

# prevent messages from slowing this down
msgminwait 0
# copy path starting at cursor
stuff " Ebe "
# write the path to a file
writebuf /tmp/screen-copied-path
# open that file in vim in a new screen window
screen /bin/sh -c 'vim `cat /tmp/screen-copied-path`'
# turn message waiting back on
msgminwait 1

# vi: ft=screen

Then add this line to your .screenrc:

# bind CTRL-f to open the file starting at the cursor
# when in copy mode
bindkey -m ^f source /path/to/edit-file-under-cursor.screen

(changing the /path/to/ appropriately)

Then, to use, make sure you restart screen (or reload the .screenrc). Enter copy mode with ^A[, cursor to the first character of a filename, then hit CTRL-f.

I've tested this, and it works for me, so tell me if you have any issues.

If you want to see how I knew how to do this, check man screen to see how all the various commands work.

One improvement that could be made is to be able to find the beginning of a path, but I couldn't do that reliably with only screen's copy mode movement commands (e.g. anything that moved to the first / of " /a/path" moved to the | of "|/a/path")

This is due to the limitations of screen's movement commands in copy mode:

Movement keys:
  h, j, k, l move the cursor line by line or column by column.
  0, ^ and $ move to the leftmost column, to the first or last non-whitespace character on the line.
  H, M and L move the cursor to the leftmost column of the top, center or bottom line of the window.
  + and - positions one line up and down.
  G moves to the specified absolute line (default: end of buffer).
  | moves to the specified absolute column.
  w, b, e move the cursor word by word.
  B, E move the cursor WORD by WORD (as in vi).
  C-u and C-d scroll the display up/down by the specified amount of lines while preserving the cursor position. (Default: half screen-full).
  C-b and C-f scroll the display up/down a full screen.
  g moves to the beginning of the buffer.
  % jumps to the specified percentage of the buffer.
...
Searching:
  / Vi-like search forward.
  ? Vi-like search backward.
  C-a s Emacs style incremental search forward.
  C-r Emacs style reverse i-search.

So if we changed the stuff line above to

stuff "Bw Ebe "

it would move to the start of a path, but it would also include any non-whitespace junk that came before the path. So as long as all your paths are whitespace delimited (on both sides) this should work.

Actually

stuff "B//^M E?/^Me "

seems to work fairly well, since that uses searching to find the first and last / (type the ^M in vim by hitting CTRL-v, then enter). I haven't tested all the edge cases, but it seems to work for:

 /a/path
 #/a/path
 /a/path#

However, it's going to fail for

 a/relative/path
rampion
@rampion: Thank you for your answer! The code also works for me. --- Could you please paste the code which you described your last paragraph? I will try to find the problem.
Masi
@rampion: The command "Bw Ebe" seems to be the most useful command of the rest. --- I am testing it to see if it has any flaws.
Masi
I noticed one bug. It would be useful to get the end character of the match to be also "," and ".". This would help you in reading manuals.
Masi
In that case, you might want to just drop the `stuff` line, highlight the path manually, copy it to a register, then hit the key combo to open the copied path in vim.
rampion
@rampion: Do you mean to copy the path in Copy-mode, and then hit `Ctrl-A Esc Ctrl-f`? --- This method did not work for me: the problem is that I am not sure about coping to register.
Masi
@rampion: I found another bug with long PATHs. I opened a new question http://stackoverflow.com/questions/1081943/unable-to-get-screen-see-the-current-working-directory-when-opening-to-vim
Masi