How to identify which REPL is running in the terminal? - linux

I am trying to have my terminal title change depending on what that specific window is doing. So far I have the following which will update based on directory and server.
function settitle() {
if [[ -z "$ORIG" ]]; then
ORIG=$PS1
fi
TITLE="\[\e]2;$*:$(dirs -0)\a\]" #dirs -0 is like pwd but with ~/ instead of /home/user/
PS1=${ORIG}${TITLE}
}
PROMPT_COMMAND="settitle local" # local is the server name in this case
Now, sometimes I'm in the PHP (php -a) or MySQL (mysql -u user -ppass) REPL, and I'd like the title to reflect that instead of just being whatever directory I launched the REPL from.
The best I can figure is getting the last command somehow, then figuring out what the first word is, and running an if check in settitle(). I've tried everything from here and here among other places, and while I can usually get part of it to work in the command line, non of it works in settitle(). For example.
local:~$ echo 'foobar'
foobar
local:~$ !:0
echo
# I add echo !:0 to settitle()
local:~$ source .bashrc
!:0
local:~$
A note: It should be "source", or at least "echo" from before. !:0 does not recognize itself as a command so it will repeat the last real command over and over. The "!:0" being echoed is a literal string, not the results of the command. Additionally, saving to a var does not work, and just putting the command without trying to echo/save the result gives !:0: command not found.
I don't want to make this an XY problem, so if I am barking up the wrong tree here at any step of the process, please let me know. The goal is to be able to change the title of my terminal window if I enter an REPL. How can I identify when a command will enter me into one?

Note that PROMPT_COMMAND and similar shell features are not relevant when you're in a different REPL; from the point of view of the shell, the entire REPL session is one single command. The shell prompt doesn't show up again until you exit that REPL, and that's the point at which PROMPT_COMMAND and friends are activated.
One thing you can do is alias the command you use to start the REPL so that it sets the title of the window first:
alias phpa='setttitle PHP; php -a'
alias mysqli=`settitle MySQL; mysql -u "$USER"'
or something like that.
The sequence goes like this:
PROMPT_COMMAND runs.
The shell prints its prompt.
You type the command to start a REPL
You are in the REPL. The prompt you see is printed by the REPL, not the shell, which is not involved at this point. The shell is just hanging out waiting for you to exit the REPL; it's not printing any prompts, so it's not ever running PROMPT_COMMAND.
You type commands in the REPL. No matter how many you run, it's part of a single session that the shell sees as a single command.
You exit the REPL.
PROMPT_COMMAND runs.
The shell prints its prompt.

Related

Can I react on entered command in bash?

I would like to configure my bash in a way so that I react on the event that the user enters a command. The moment they press Enter I would like my bash to run a script I installed first (analog to any PROMPT_COMMAND which is run each time a prompt is given out). This script should be able to
see what was entered,
maybe change it,
maybe even make the shell ignore it (i. e. make it not execute the line),
decide on whether the text shall be inserted in the history or not,
and maybe similar things.
I have not found a proper way to do this. My current implementations are all flawed and use things like debug traps to intervene before executing a command or (HISTTIMEFORMAT='%s '; history 1) to ask the history after the command execution is complete about things when the command was started etc (but that is only hindsight which is not really what I want).
I'd expect something like a COMMAND_INTERCEPTION variable which would work similar to PROMPT_COMMAND but I'm not able to find anything like it.
I also considered to use command line completion to achieve my goal but wasn't able to find anything about reacting on sending a finished command in this, but maybe I just didn't find it.
Any help appreciated :)
You can use the DEBUG trap and the extdebug feature, and peek into BASH_COMMAND from the trap handler to see the running command. (Though as noted in comments, the debug trap is sprung on every simple command, not every command line. Also subshells elude it.)
The debug handler can prevent the command from running, but can't change it directly. Though of course you could run any command inside the debugger, possibly using BASH_COMMAND and eval to build it and then tell the shell to ignore the original command.
This would prevent running anything starting with ls:
$ preventls() { case "$BASH_COMMAND" in ls*) echo "no!"; return 1 ;; esac; }
$ shopt -s extdebug
$ trap preventls DEBUG
$ ls -l
no!
Use trap - DEBUG to remove the trap. Tested on Bash 4.3.30.

Setting a part of a PWD as a prompt and keeping a variable updated

I'm using tcsh, and I'm trying to set a part of the PWD to appear always in the prompt (so I will always know in which "parent" directory I am).
I managed to extract the needed part of the prompt in the following way, and it works fine (I call it MyTreePath):
set MyTreePath=`echo $PWD | awk '{... print whichTree}'`
I've added the code above to my .tcshrc and I've added %$MyTreePath to my set prompt line in .tcshrc.
The problem is that once the shell is opened, the MyTreePath doesn't change, even if I'm going to a totally different path.
How to keep a variable that appears in the prompt updated?
Use the magical cwdcmd alias! It is used for defining a command which executes everytime the cwd changes. In your case, you need to updated your variable.
From the manpage:
The beepcmd, cwdcmd, periodic, precmd, postcmd, and jobcmd Special
aliases can be set, respectively, to execute commands when the
shell wants to ring the bell, when the working directory changes,
every tperiod minutes, before each prompt, before each command gets
executed, after each command gets executed, and when a job is started
or is brought into the foreground.
Here's a quick example:
alias cwdcmd 'set FOO=`pwd`'
set prompt='%$FOO >>> '
field testing:
cd /
/ >>> cd dev
/dev >>>
So all that's left is to replace pwd in the alias above with your own command.
For more info and other magic aliases, see here.

advanced unix command-line trick

I want help regarding unix command line.
In command line if i type any command like date; konsole should automatically execute ls and than execute date.
example: if i type date
than interface should be like ls ; date.
I can do alias but i want not only for date for every other command also. even if i don't supply any command and press empty enter it should execute ls.
I tried confugiring in set prompt variable. but i didn't got it and the variable is not reloading automatically.
Are you using konsole as your terminal emulator and tclsh as your interactive shell? If so, the former is irrelevant and the latter is an interesting tool choice. More likely, you are running bash as your interactive shell, in which case you can simply add a trap on DEBUG. To test the behavior type:
trap ls DEBUG
After executing this in bash, in this shell only, ls will be executed before every command. If this is the behavior you want, set the trap in ~/.bashrc.
Note that this is bash specific. Other shells have different mechanisms for getting this behavior.

How can I revert my last choice on terminal if it shows > symbol?

I'll be glad if someone can fix the title to be more appropriate since I'm pretty new to terminal.
I have an issue with terminal. Once I execute a command, if it goes to the next line, I can't close it or revert it. I assume it starts the executable or asks for more parameters using >
For example:
//Windows Machine
vagrant up
//Vagrant Instance Unix Machine
$ git
>
>
>
> ... it goes on like this, I can't close > so I can't execute other commands
The only solution on fixing is restarting the terminal (which means I need to restart Vagrant instance)
It happens on some commands only - not all, so I don't know what makes a difference.
For example, executing composer, I get information about Composer and terminal goes back to main state. However, if I execute things like php, git, mysql, > symbol appears and I can't return from there.
So, two basic questions;
What causes this?
How can I terminate the current command to go back main state?
Any help would be greatly appreciated.
Ps. I use both windows terminal and unix terminal and this issue happens on both.
Normally you'll see a > prompt if you've entered a command that's syntactically incomplete, for example if there's a unterminated string literal:
$ echo 'hello
> '
hello
$
It means that the shell is waiting for you to type the rest of the command, or at least enough of it to make for something that's not a syntax error.
In this example, the default prompt, $PS1, is '$ ', and the secondary prompt, $PS2, is '> '. Read the documentation for your shell (probably bash) for more information.
You can cancel the current command and get back to your primary prompt for a new command by typing Control-C.
This is all about the behavior of your shell; it has nothing to do with your terminal (almost certainly a terminal emulator), which merely provides a GUI for your shell to run in.

What can I use to capture every command I run in bash (a-la history)

I know history will capture commands that I run, but it is shell specific. I work with multiple shells and multiple hosts and would like to write a small script which, after every command I run, dumps that command to some file along with the host name. This way, i can implement my own history command which reads from that file, and can take a host as an argument which would be handy for me. I'm not sure how to get the first part though..i.e., get every shell command I type to trigger a "dump that command into a file" part. Any ideas?
Thanks
In bash, the PROMPT_COMMAND environment variable contains a command that will be executed before the PS1 prompt is displayed. So yours could be something like history | tail -n1 | perl -npe 's/^\s+\d+\s+//' | yourcommand HOST
The script utility should solve your problem. It records everything you type and all that is printed on the terminal in a file (even including terminal control codes, so if you cat that file on the console, you even reproduce the original text colors).

Resources