Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to use the following script:

#!/usr/bin/env bash
# Edit xselection in gvim
xsel > /tmp/xselection
gvim /tmp/xselection
xsel < /tmp/xselection

But the final line does not seem to be correctly loading the file into xselection. If I run that line immediately after calling the script it succeeds. I can't understand why. What am I missing?

share|improve this question
add comment

4 Answers

up vote 4 down vote accepted

You're missing the fact that the call to gvim does not block until you exit gvim, it returns immediately. So the xsel < /tmp/xselection is processing the file before you edit it.

share|improve this answer
add comment

You need to use the -i option. (-o is the default)

xsel -i </tmp/xselection
# -o, --output   write the selection to standard output.  
# -i, --input   read standard input into the selection.*

These optons work on the X primary selection (not the clipboard), so you need to center-click to see the resullt. I've tested it with a pause before the final command. This allowed me to manually select some other text before the final command executed. The I center-clicked and it worked fine... and it works without the delay.

However testing it without the delay doesn't prove much, becaust the original selection is still selected... and, of course, if you select something else in the meantime, you will lose the script's primary selection.

Perhaps your issue is a combination of both the -i option, and Paul Tomblin's answer about the way gvim detaches from the script process.

share|improve this answer
    
No, you don't need -i here: if stdin is not a terminal, xsel sets the selection from standard input. That's not to say that explicitly passing -i isn't a good idea, but it can't be the source of the problem. –  Gilles Feb 27 '12 at 23:12
    
@Gilles: Thanks for pointing that out; I wasn't aware of that syntax. I've now re-read the man page, and yes, it does (seem to) state that no options are needed, but that is not what I experience in all situations (on my test Ubuntu system). Those stdin/out rules only apply when the script is run from the terminal. When the script is launched via the "Run Application" dialog, or via a shortcut-key, it definitely needs the -i option. Now I understand why I was getting strange results (until I used -i). I've added another answer which deals with both issues: options and detaching. –  Peter.O Feb 28 '12 at 6:23
add comment

My previous answer was getting a bit crowded and was incomplete (and had only one edit-itteration left). So here is an amended answer which includes both ideas... options and detaching.

As I've mentioned in a follow-up commen to Giles comment (previous answer), the -i option is definitely needed in some situations (on the test Ubuntu system).. so -i and -o are used here.

Because 'gvim' detaches from the script's process, it doesn't wait, and the next command is executed immediately. (Paul Tomblin has already pointed thos out in hes answer).

You can't use bash's wait command, as it only works for child processes. As workaround, you can set up a loop which waits for the non-child process to terminate. This works for an editor which starts with a new process each time (as 'gvim' does in this case).

Here is the modified script

xsel -o >/tmp/xselection

gvim /tmp/xselection 2>/dev/null
pid=$(pgrep -n "gvim")  # get gvim's pid and wait
while kill -0 "$pid" 2>/dev/null; do sleep 0.5; done

xsel -i </tmp/xselection

The above assumes that gvim` pid is already established by the time control is passed back to the script. If, under a high system load, the pid hasn't been established upon executing the next command, then this method of waiting for gvim should work.

xsel -o >/tmp/xselection

pre=$(pgrep -n gvim)    # get previous gvim pid
gvim /tmp/xselection 2>/dev/null
while pid=$(pgrep -n "gvim"); [[ "$pid" == "$pre" ]]; do sleep .1; done
while kill -0 "$pid" 2>/dev/null; do sleep 0.5; done

xsel -i </tmp/xselection
share|improve this answer
    
I found gvim also has a flag -f that makes it stay in the foreground, which keeps the script a little simpler. Thank you for both of your answers though! –  rob.g.greer Feb 28 '12 at 15:52
add comment

I ended up incorporating information from both/all three answers to generate the following:

#!/usr/bin/env bash
# Edit xselection in gvim

xsel > /tmp/xselection
gvim -f /tmp/xselection
xsel -i < /tmp/xselection
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.