You are not logged in.
Abstract: how to check if one is starting certain application from already open terminal (bash in 'terminator'/'urxvt'), or from launcher (like 'dmenu' or 'gmrun')?
Real-live example: I like to use the 'ranger', my favorite file manager, but the 'ranger' happens to be a terminal application. It means that I have to open terminal first, and then type in 'ranger'.
Of course, I can hook this to key combo and/or right-click menu entry ... but what about 'dmenu' and/or 'gmrun'? Try to enter 'ranger' in any one of them (activated by S-D or Alt-F2, respectively), and nothing will happen. Of course, shell has to be started first and then 'ranger'. Effectively, instead of only 'ranger', you would have to enter:
x-terminal-emulator -e "/usr/bin/ranger" "$@"
("@" denotes possible additional arguments supplied to 'ranger' - thanks HoaS).
Is there a simpler way? Of course there is ...
Solution1 (not so nifty):
It is doable by little scripting. Let's continue with the 'ranger'. Simply, create file '$HOME/bin/ranger' (yes, the very same name as original application), put this code into it
#!/bin/bash
#
# Solution1 (not so nifty)
x-terminal-emulator -e "/usr/bin/ranger" "$@"
and make it executable by
chmod u+x $HOME/bin/ranger
Now, you can enter 'ranger' in 'dmenu' and/or 'gmrun', and it will start in new terminal.
Are we done? Not yet! Namely, open terminal and enter 'ranger' ... it will open another terminal with 'ranger'. This is not what we want - not another terminal!
What's wrong? Well, our little script - as instructed - starts new terminal every time. It would be much much better if we could first see if we are in terminal or not, and open new terminal only if we were not in one. (Yes, 'dmenu' and/or 'gmrun' are not terminals ...)
Solution2 (better solution):
Let us rewrite '$HOME/bin/ranger' script with this.
#!/bin/bash
#
# Solution2 (better solution)
if [ "$(tty)" == "not a tty" ] # test if we are in terminal
then
# we are not in terminal -> start new one
x-terminal-emulator -e "/usr/bin/ranger" "$@"
else
# we are already in terminal -> do not start new one
/usr/bin/ranger
fi
Try now 'dmenu' and/or 'gmrun', and inside terminal ... Voila: now it will open new terminal only when needed!
Solution3 (BL users only):
In BL, there is already such a function. (I was ignorant of this as I do not use BL primarily.) See johnraff's post below.
Final remark: this works, in principle, with any other application. And it uses 'tty' program, which is independent on shell.
And ... I hope someone might find this useful.
Edit: added "$@" per HoaS suggestion, and rubbing johnraff's itchy spot
Last edited by iMBeCil (2016-09-21 08:34:32)
Postpone all your duties; if you die, you won't have to do them ..
Offline
Thanks, I just noticed that mc is launching its own (default) terminal by default. Any clues how mc does it?
Offline
^You're welcome.
As for the mc (midnight commander), it doesn't work with dmenu (Alt+F3), but does work with gmrun (Alt+F2).
Why it does work with gmrun? See Archwiki gmrun entry ... and search for 'AlwaysInTerm' in gmrun config file ~/.gmrunrc.
Postpone all your duties; if you die, you won't have to do them ..
Offline
don't know if i remember correctly, but most my ~/.bashrc's have this at the beginning:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
doesn't that '[[ $- != *i* ]]' do the same?
Offline
Great guide iMBeCil, thanks
If I may, this construct can be used to launch the program:
x-terminal-emulator -e "/usr/bin/ranger" "$@"
Arguments can then be passed to the script, for example `ranger /usr/share` would open in that folder.
Offline
@iMBeCil You hit an itchy spot there!
Your solution looks fine, but, as it happens, there is already a function in /usr/lib/bunsen/common/bl-include.cfg which does this very thing.
Here it is:
# rerun script in terminal if necessary
# Usage: terminalCheck [ -T title ] [arguments...]
terminalCheck() {
if ! [[ -t 0 && -t 1 && -t 2 ]]; then # not attached to terminal
if [[ -n $DISPLAY ]]; then # running X
if [[ ${1-} = '-T' ]];then
local title=${2-}
shift 2
exec x-terminal-emulator -T "$title" -e "$0" "$@"
else
exec x-terminal-emulator -e "$0" "$@"
fi
else
echo "$0: no terminal" >&2
exit 1
fi
fi
}
It allows you to set a title on the terminal, and it avoids opening a new shell, by using exec.
Alternatively, source the above file and just call the function at the top of a script:
BL_COMMON_LIBDIR='/usr/lib/bunsen/common'
if ! . "$BL_COMMON_LIBDIR/bl-include.cfg" 2> /dev/null; then
echo $"Error: Failed to locate bl-include.cfg in $BL_COMMON_LIBDIR" >&2
exit 1
fi
terminalCheck() -T 'My Title' "$@"
@ohnonot Thank you for '[[ $- != *i* ]]' I didn't know that one.
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
Thanks for your comments. In particular:
@ohnonot: thanks, didn't know for
[[ $- != *i* ]]
Nice! Although, it seems characteristic for 'bash' only ...
@ HoaS: thanks for the tip ... included in solution
@johnraff: sorry for duplicate job As I needed this functionality and I don't primarily use BL, I - of course - missed existence of the 'terminalCheck()' function ... I added a reference to this in the first post, as not to derail BL user O:)
Last edited by iMBeCil (2016-09-21 08:35:20)
Postpone all your duties; if you die, you won't have to do them ..
Offline
Great thread. Thanks, iMBeCiL and contributors.
Offline