Mouse events in terminal emulator - bash

Question
Is it possible, in a terminal emulator, to run a command whenever a mosue event happens?
What I've tried
I think I'm halfway there - using echo -e "\e[?1003h" (see here for details) and waving the mouse about over the terminal produces a desirable effect of printing a bunch of characters, related to the occurred mouse event. (Note: echo -e "\e[?1003l" turns this off)
echo -e "\e[?1003h"
# move mouse over terminal window, in the character input line, NOT to stdout:
> CF*CC+C#,C;.C:/C8/C8/C8/C8/C9/C9/C9/C90C90C80C81C81C81C81C81C90C:/C;/C;.C<.C<.
# After deleting that, I enter:
> echo -e "\e[?1003l"
# mouse move, all is quiet
I've also tried hooking it up to output to a file. This was to see if I could watch the file and run a command according to that. It went as follows:
> echo -e "\e[?1003h" >> file.txt
# elevator music whilst I move the mouse about
> echo -e "\e[?1003l"
# move mouse a bit, nothing
> cat file.txt
# nothing but blank lines, fair enough. But, mouse moves and in the terminal input is printed...
> CF*CC+C#,C;.C:/C8/C8/C8/C8/C9/C9/C9/C90C90C8 ...
# Delete that output, and then I type:
> echo -e "\e[?1003l"
# mouse moves, no output
What I want
How can I either capture this output so that it is going to stdout, or to a file, so that I can then use the changing output to trigger running a command? If that's not possible, is there any other way to capture when a mouse click occurs in a terminal emulator, with the event coordinates?

It's not output, it's input.
There are multiple ways to read input in bash. Here's one that reads everything until stopped:
echo -e "\e[?1003h"
echo "Press enter and then ctrl-d to stop reading"
cat > myfile
When done and correctly exited with Enter and Ctrl+D you can inspect myfile to see all the mouse events.
A proper mouse application would disable local echo and terminal buffering before reading and decoding the escape sequences from the terminal.

Related

Send echo command to an external xTerm

I have a bash script, and I want to be able to keep a log in an xterm, and be able to send echo to it anytime.
How would I do this?
Check the GPG_TTY variable in your xterm session. It should have the value similar to
GPG_TTY=/dev/pts/2
This method should be available for terminals that support GNU Pinentry.
Another option to determine the current terminal name is to use
readlink /proc/self/fd/0
The last method applies only to Linux
Now if your bash script implements a command
echo "Hello, world!" > /dev/pts/2
This line should appear on the xterm screen.
I managed to make a console by running an xterm with a while loop clearing the screen, reading the contents of the log file, pauseing for a second, then looping again. Here was the command:
xterm -T Console -e "while true: do cls && cat ${0}-LOG.txt && sleep 1; done"
Then to send something to the console:
echo -e "\e[91;1mTest" >> ${0}-LOG.txt
And the console will update each second.

Why isn't this command returning to shell after &?

In Ubuntu 14.04, I created the following bash script:
flock -nx "$1" xdg-open "$1" &
The idea is to lock the file specified in $1 (flock), then open it in my usual editor (xdg-open), and finally return to prompt, so I can open other files in sequence (&).
However, the & isn't working as expected. I need to press Enter to make the shell prompt appear again. In simpler constructs, such as
gedit test.txt &
it works as it should, returning the prompt immediately. I think it has to do with the existence of two commands in the first line. What am I doing wrong, please?
EDIT
The prompt is actually there, but it is somehow "hidden". If I issue the command
sudo ./edit error.php
it replies with
Warning: unknown mime-type for "error.php" -- using "application/octet-stream"
Error: no "view" mailcap rules found for type "application/octet-stream"
Opening "error.php" with Geany (application/x-php)
__
The errors above are not related to the question. But instead of __ I see nothing. I know the prompt is there because I can issue other commands, like ls, and they work. But the question remains: WHY the prompt is hidden? And how can I make it show normally?
Why isn't this command returning to shell after &?
It is.
You're running a command in the background. The shell prints a new prompt as soon as the command is launched, without waiting for it to finish.
According to your latest comment, the background command is printing some message to your screen. A simple example of the same thing:
$ echo hello &
$ hello
The cursor is left at the beginning of the line after the $ hello.
As far as the shell is concerned, it's printed a prompt and is waiting a new command. It doesn't know or care that a background process has messed up your display.
One solution is to redirect the command's output to somewhere other than your screen, either to a file or to /dev/null. If it's an error message, you'll probably have to redirect both stdout and `stderr.
flock -nx "$1" xdg-open "$1" >/dev/null 2>&1 &
(This assumes you don't care about the content of the message.)
Another option, pointed out in a comment by alvits, is to sleep for a second or so after executing the command, so the message appears followed by the next shell prompt. The sleep command is executed in the foreground, delaying the printing of the next prompt. A simple example:
$ echo hello & sleep 1
hello
[1] + Done echo hello
$
or for your example:
flock -nx "$1" xdg-open "$1" & sleep 1
This assumes that the error message is printed in the first second. That's probably a valid assumption for you example, but it might not be in general.
I don't think the command is doing what you think it does.
Have you tried to run it twice to see if the lock cannot be obtained the second time.
Well, if you do it, you will see that it doesn't fail because xdg-open is forking to exec the editor. Also if it fails you expect some indication.
You should use something like this
flock -nx "$1" -c "gedit '$1' &" || { echo "ERROR"; exit 1; }

grep from screen output and detach

I'm currently writing a bash script which periodically checks for some special words in the server output of a detached screen session, but it enters the session (if grep found something) instead of showing the grepped output. Here is what I've tried:
screen -r foo | grep bar
This gives me the correct return code, but doesn't detach the session afterwards! I also tried && screen -d but that changes nothing.
So how can my script tell me if "bar" is in the output of the server running in my "foo" screen session?
Your problem, I think, is that screen doesn't output in a way that can be searched by grep. If it did, then your attempt at screen -r foo | grep bar && screen -d would likely have been the right way to go about it.
I'd suggest starting the initial screen session with the -L option to enable logging. Then you can search the log file for the value you want.

pager (less) -- get current scroll position?

I am scripting the display of the output of a script (well, it is just the program git diff) with tmux: Once a filesystem change is detected the shell script executes tmux send-keys q enter C-l "git diff" enter which has it effectively refresh the git diff view.
You might consider this similar to functionality provided by iTerm's coprocesses.
Problem is, I want it on refresh to scroll back to the same position that it was in.
One of the reasons for using tmux is that the window is actually a totally normal and interactive terminal session that can be interacted with as normal to scroll around to look at the full output.
But I want to obtain the scroll position somehow.
Suppose I want to actually do computation on the text content of the terminal window itself, exactly like iTerm2's coprocess does, but so that I can use it on Linux (over ssh). Does tmux provide this ability?
I'm unsure about capturing this with a script, but less -N will show line numbers.
And -jn or --jump-target=n can jump to a location.
About iTerm's coprocesses,
tmux has a command pipe-pane that can be used to pipe the input and output of a shell command to the output and input of a target pane specified by -t.
So if I have a shell program, ~/script.sh for example:
#!/usr/bin/env bash
while read line; do
if [[ "$line" = "are you there?"* ]]; then
echo "echo yes"
fi
done
Note that read line will read every line printed to the pane, i.e. the prompt as well.
I can connect its stdin and stdout to pane 0 in my-session:my-window like so:
tmux pipe-pane -IO -t my-session:my-window.0 "~/script.sh"
and then at the prompt, type echo are you there?, and it responds:
$ echo are you there?
are you there?
$ echo yes
yes
Be careful using -IO together as it can easily cause a feedback loop (I had to kill the tmux server a few times while experimenting with this feature, lol).

How can I make bash terminal to beep when its output screen changes?

I am using gnome-terminal.
Is it possible to make it(or any other terminal) beep whenever its output screen changes (like some new output line came)?
I want it for only one particular window.
Possibly of use:
The GNU screen program has features for monitoring background windows for activity as well as inactivity.
http://www.gnu.org/software/screen/manual/screen.html#Monitor
Something called lTerm has "tabs with activity alerts"
http://lterm.sourceforge.net/
But at this point I'm turning into a meta search engine.
$ ./myprogram | sed 's/$/\a/'
for example
$ for i in {1..10}; do echo $i; sleep 1; done | sed 's/$/\a/'

Resources