I am writing a console application which makes use of the F1 key (for help). Unfortunately, while Konsole (of KDE) doesn't use this key, Gnome Terminal does, so the F1 key becomes inaccessible to my application. I don't think there's a way to detect whether the F1 key is already mapped in the GUI side of things (Gnome Terminal), but if there is, the answer to that will obviate this question. :)
Ergo, my next best bet is to try to detect whether I am running inside Gnome Terminal. Is there some way to do that? I'm primarily interested in gleaning this from within Ruby, but if it can be done via shell or environment variables, or virtual filesystem (/proc, /dev, etc.) then that will suffice.
I'm hoping for a reliable way to do this, but I can settle for "best guess" approaches like grepping the environment variables for clues that can let me reasonably assume that Gnome Terminal is the wrapping terminal.
Extra info: other keys are also "stolen" by Gnome Terminal. I intend to display some sort of informative message about alternative keys for Gnome users.
Googleage has revealed that I might be able to rely on Gnome Terminal setting the COLORTERM environment variable to 'gnome-terminal'.
For zsh:
[[ "$COLORTERM" == "gnome-terminal" ]] || [[ ${$(ps -p $(ps -p $$ -o ppid=) -o cmd=):t} == gnome-terminal* ]]
gnome-terminal used to set $COLORTERM, but this has been dropped (in 3.12.0-67-g1d5c1b6).
Normally you use termcap info aka terminfo. This tells you what kind of terminal you're working with and also what the keys are.
It is the user's choice, and since Gnome Terminal reports itself as probably a kind of x-term, as Konsole likely does, there is likely a way for the user to create an F1 keypress. Therefore, I suspect that the terminal capabilities of the two will be reported as equivalent.
This investigation of Function Key Escape Codes might be interesting to you without actually explaining how, if it is even possible, that the gnome terminal could be made to produce an F1 press. Thinking of the Mac OS X terminal I used a long time back, it caught PageUp and PageDown for the scroll bar, while Command-PageUp and Command-PageDown passed them through to the terminal.
A rather crude method, if you feel like delegating this to the shell -- otherwise, in C or C++, you will have to wade through your /proc, if you have one:
ps x | grep `ps o ppid,fname | grep bash | grep -v grep | head -1 | awk '{print $1}'` | grep 'gnome-terminal' | wc -l
If running from your own program, through system() for instance, you may with to 'grep' your program's name rather than 'bash'
I know, it's definitely "hack like a pirate" ;)
fwiw, this is a setting in gnome-terminal; users can go to Edit -> Keyboard Shortcuts in the gnome-terminal menus and change or delete the F1 keybinding.
I simply check the $TERM for the terminal emulator of my choice and then add an alias for spawning a new terminal in the current directory.
if [[ $TERM == 'xterm' ]] ; then
alias nw='gnome-terminal --working-directory=$PWD'
fi
Related
I'm using, OS X, and mainly terminal and emacsclient.
When I do shell stuff, I background my emacsclient with Control-Z
Someties I forget whether i've done that, and end up spawning additional emacsclient sessions, which I don;t want to do.
It would be cool if the bash prompt can tell me whether emacsclient jobs up in the jobs output
Minimal example for bash, using sleep instead of emacsclient.
PS1="\`if jobs | grep -q sleep; then echo 'sleep jobs' ; else echo 'no sleep jobs' ; fi\`\\\$ "
You might want to filter on stopped jobs (jobs -s).
You can get fancier by echoing escape sequences instead of just strings to colorize it.
While I think #jpkota provides a workable answer, I wonder if maybe your worrying too much. Provided emacsclient is working OK, there is no problem with having multiple emacsclient sessions running at once - in fact, it is sort of designed to do that. The emacsclient connections are light-weight and if there is a chance you might need to use the same file/buffer again, you may as well keep them around and just open new ones when needed and get rid of the ones you don't think you will need. The whole benefit of emacscleint is that opening new windows/buffers is really fast and if you use the GUI verison, they just pop up in their own window.
There is also a package in elpa which may be useful called osx-pseudo-daemon, which addresses a problem that can occur if you close all emacsclient windows which prevents the main emacs from responding (this is when yu run emacs from launchctl.
What I tend to do is run emacsclient in GUI mode rather than inside a terminal. When I run emacsclient I put it in the background so that it doesn't block my terminal and use the -c flag.(I actually have a shell script which makes this easy - see http://emacsformacosx.com/tips for some ideas. I leave the emacsclient window open and just switch to it if I need to do some emacs editing etc.
I need to write lot of code and compile very often. I hate switching back and forth various windows just to compile the code. Is it possible to open a small window at bottom and run invoke shell and close that window when needed?
With GVim or MacVim, you can run external commands in the command-line: Gvim/MacVim comes with a (very) limited shell that will happily show you whatever the compiler outputs. The general usage pattern is:
:!command
:!command %
With CLI Vim, the same method will pause Vim and return to the shell to execute your command.
In both cases, you'll get a message asking you to press ENTER to come back to your normal editing.
Using :make | cw would be a slightly more sophisticated alternative, with the added bonus of showing the errors in the quickfix window.
An even more sophisticated approach would be to use Tim Pope's Dispatch plugin in combination with tmux or screen.
Sounds like a problem for Screen
http://www.gnu.org/software/screen/
Quick reference of commands
http://aperiodic.net/screen/quick_reference
I use tmux to achieve something like that. I have the following in my ~/.tmux.conf file:
bind s splitw -v -p 25 -c '#{pane_current_path}' '/bin/bash'
bind q kill-pane
On pressing Ctrl-b + s (prefix + s), a new pane containing a bash shell opens up at the bottom. I can run shell commands from there: find, grep, make, etc. When I'm done, I press Ctrl-b + q to close the shell.
To enable tmux on every bash session, add the following to your ~/.bashrc:
[[ -z "$TMUX" ]] && exec tmux
Maybe map a key to shell out to the compiler and run the program if compilation is successful:
:map F8 :!cc % && ./a.out
Or maybe just
:sh
make run
Ctrl-D
Another option is to suspend vi, using Ctrl-Z and do your stuff in the shell, then type fg to bring vim back to the foreground. Note that this is actually a feature of your shell, rather than vim but it produces the effect you seek.
Note this idea originates from the book "Efficient Linux at the Command Line" by Daniel Barrett. I forget the page number.
I want to run steam on linux, and I don't want to install xterm, there are two moments when does it want xterm
echo -e "$*" >$tmpfile
xterm -T "$title" -e "cat $tmpfile; echo -n 'Press enter to continue: '; read input"
rm -f $tmpfile
and
# Fall back to sudo in a terminal
xterm -e sudo -p "$prompt
[sudo] password for user: " $*
is it safe for posix to use ${TERM} instead of xterm here?
Assuming the script will be running in an X session; no, there is no reason to believe that TERM will be set under those circumstances (and if it is, it would be a coincidence for it to point to a binary of the same name -- the contents of this variable should be a key for Termcap or Terminfo; a lot of the time, on modern systems, it might be something like vt220 if it's not some variant of xterm, or emacs or dumb).
On the other hand, if your environment is X, you are basically guaranteed to have xterm.
Debian defines x-terminal-program (IIRC) to let the user or system administrator pick a different default terminal emulator.
I don't think POSIX 1003 has any concept of the problem you are attempting to solve (and we are guessing, too; perhaps you could add more details to your question?)
A better platform to require users to have available might be Freedesktop.org but I have no idea whether e.g. Mac OSX adheres to any useful subset of that. (They might implement all if it; I simply don't know.)
On the other hand, the simple, crude fix would be to require the script to be run from a terminal in the first place; then, you can simply use cat to display text files (your EULA, I would guess?) and echo (or cat again) and read to interact with the user. That is, don't attempt to open a new terminal window for these things. Maybe do all interaction near the beginning of the script to make it easy to bail out early.
If you want graphical interaction, you need to limit your target platform, or write complex wrapping for each different environment.
I am not exactly a pro at BASH Scripting, but I can get by with the basics. I use MRXVT with Cygwin on my windows box (MRXVT is an RXVT Terminal with tabs. RXVT is a Standard Cygwin terminal, but with enhanced features). I found a command to change the tab names for MRXVT:
echo -ne "\e]62;New tab title\a"
It works like a charm. I'm not, however, interested in A)Changing it manually or B)Changing it to a static String
I use a lot of SSH. I'd like the tab title to be username#host[current directory] at any given time.
I'm not sure if I'm supposed to use a trap for this. Frankly, I don't understand how traps work. I guess I could create an ssh alias that pulls the first argument of the ssh command and sets the tab title to that...This would be sufficient, but not preferred.
Do you guys have any ideas?
Found an answer. added
trap 'echo -ne "\e]62;mrxvt: $USER#${HOSTNAME}\007"' DEBUG
to the very end of my .bashrc. I decided I didn't like having the path in my tabs (or titlebar for that matter). Also, I had to add "mrxvt: " to the beginning of the string because of an AHK script that I wrote; it wouldn't work properly otherwise. The full answer to this is:
trap 'echo -ne "\e]62;$USER#${HOSTNAME}[${pwd}]\007"' DEBUG
Again, just add that line to the end of your .bashrc, and you're good to go.
Hope this helps somebody else :)
I tried this just now:
grep -RlI "id=\"kw\"" * | xargs vim
That gave me 16 results. It opened the first result in Vim. I made my very first edit and hit :q since I didn't know the shortcut to jump to the next file.
It threw me back to the console ( I am SSHed in to a server ). My console is messed up now. Anything I type I can't see, and anytime I hit enter it seems like it processes the command but the display/view is screwed up so
[meder#linode] is tabbed in on my console, at least halfway. reset does nothing since it seems to have messed up my real console.
Can anyone offer a solution that doesn't have this same downside? Or can anyone provide an explanation for why :qing out of the very first file messed up my console?
Background information: My PC is Debian Ubuntu, I am SSHed into a RHEL box. The files I opened were text/ascii files phtml/php files and not some weird binary files with crazy characters in them.
Here's a screenshot of what happened
EDIT #1: I just typed reset again and it seemed to work. The first reset did not work I think because somehow the console inserted some whitespaceish character inside it? Anyways, I would like an explanation for this weird behaviour.
Try:
vim -o `grep -RlI "id=\"kw\"" * `
From the man page for xargs:
Undefined behavior may occur if utility reads from the standard input.
That line isn't in the Linux man page but it is present on my Mac. If you want to run a program that you intend to read standard input, the usual linux version of xargs will need an argument to read its input from a file:
OPTIONS
--arg-file=file, -a file
Read items from file instead of standard input.
If you use this option, stdin remains unchanged
when commands are run. Otherwise, stdin is
redirected from /dev/null.
Vim is intended to run with both standard input and standard output connected to real (a very rare case these days) or pseudo tty devices. Wierd things will happen if you upset this arrangement.
The fundamental problem with your command was that, with standard input redirected to the pipe, xargs had no way to run a vim with a "normal" standard input. So the vim mode changes and command input were not what you expected.
You can probably fix this by typing a return, a tilde, and a period. This will force your ssh session closed from your end, you can then ssh in again, and run "ps" to check for anything left hung in the background that you should kill(1).
You can use :next or :n to get to the next file to edit. You can also use vim -o to open up all the matching files in different windows in Vim.
Not sure why your console is messed up though. I tried using your command and my console was fine.
Console options are set by stty, so you may want to save its options to a bash variable and restore them after vim exits, like this:
function vim()
{
STTYOPTS="$(stty --save)"
vim "$#"
stty "${STTYOPTS}"
}
But it is probably the better way to use zsh for this task: if you put the only line ttyctl -f into your ~/.zshrc, then zsh will automatically restore terminal options after program exits. ttyctl is a zsh builtin, so you cannot use it from bash.
Other folks covered what happened and what to do about it. As to why, the answer to that probably lies in what input Vim received from the xargs command and tried to execute as if that input came from a terminal. I don't know how to talk terminal, but you can imagine that Vim got some strange commands that crashed it or told it to quit. Similarly unpredictable things happen when you cat a binary file.
Anway, I have another idea. Have you tried using vimgrep to browse a list of files matching a pattern?
:vimgrep /id="kw"/ *
:copen
This greps for id="kw" in all files in the current directory. :copen opens up a window with a list of matches. You can browse that list, clicking enter to jump to a file position.
For more information, see
:help grep
:help :vimgrep
:help :copen
:help quickfix
If you really need that -I option, see
:help :grep
:help 'grepprg'
See also: Vim: Warning: Input is not from a terminal
Try to use ... | xargs sh -c '...' and then read from the controlling terminal device /dev/tty.
echo ~/.profile ~/.bashrc | xargs sh -c 'vim "$#" </dev/tty' dummy_script_name
# based on a tip by Laszlo Ersek on http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2010-03/msg00051.html
#find . -maxdepth 1 -type f | xargs sh -c 'rm -i "$#" </dev/tty' dummy_script_name