Ok. If I understand correctly, you basically have a Terminator window in a split view, where the one buffer is a Bash shell and the other is a Python interpreter. Now, whenever you type a command like cd Pictures/
in the Bash buffer, you want to automatically send the command os.chdir("Pictures/")
to the Python buffer, so that it changes directories simultaneously with your Bash shell. Kind of like in this image:
...where the os.chdir
command in the Python buffer should be entered automatically when you type a cd
command in the Bash buffer. Right? If yes, here's a...
Solution
Step 1: Assign the two buffers to the same group
Terminator supports groups of windows. We'll assign those two buffers to the same group, in order to later use Terminator's feature of broadcasting commands to windows in the same group. In this example I will assign both buffers to a group named Tau (actual name doesn't matter, but make sure it's the same for both buffers).
Step 2: Define keyboard shortcuts to switch group broadcasting on and off
By default Terminator does not have keyboard shortcuts for these, but we need them now, so we'll define them via Terminator's Preferences menu. I used Ctrl+Insert to switch group broadcasting on, and Ctrl+Delete to switch it off. You can pick any other keyboard shortcuts you like, though you will have to adapt Step 3 appropriately.
Now, you can press Ctrl+Insert, and whatever you type in the one buffer will appear in the other buffer. By typing Ctrl+Delete you deactivate that behavior again.
If the Python interpreter understood a command such as cd Pictures/
, to change a directory in both buffers, all you would have to do now would be something like Ctrl+Insertcd Pictures/
Ctrl+Delete, to broadcast the command as is. But the normal Python interpreter does not understand this cd
command. You could use IPython, which does understand it, instead of the pure Python interpreter. However I assume that (1) you want the pure Python interpreter and (2) you don't want having to remember pressing these key combinations before and after each cd
command. So, let's head to Step 3.
Step 3: Translate and send the cd
command automatically to the Python buffer
We will re-alias Bash's builtin cd
command to do a little more before actually changing the working directory in the current shell. Namely, whenever a user types cd somewhere
,
- We translate the command to Python
- We use
xdotool
to simulate pressing Ctrl+Insert
- We use
xdotool
to simulate typing the translated command
- We use
xdotool
to simulate pressing Return
- We use
xdotool
to simulate pressing Ctrl+Delete
In this way, the translated command will be sent to the Python buffer. If you don't have it, install xdotool
:
sudo apt-get install xdotool
The script that we want as an alias for cd
will look something like this:
function cd_to_pybuf {
xdotool type "#"
xdotool key Ctrl+Insert
xdotool type "os.chdir(\"$1\")"
xdotool key Return
xdotool key Ctrl+Delete
cd "$1"
}
cd_to_pybuf
Explanation: When we alias cd
to the above script, then whenever we type cd somewhere
, Bash translates that to OURSCRIPT somewhere
. Since our script ends with the function call cd_to_pybuf
, it will actually call the function cd_to_pybuf
with somewhere
as argument (available as $1
within the function; note that bash expansion would not work here, so we can't use something like !*
to get at the arguments of the original command, and $BASH_COMMAND
is problematic too). This function performs exactly the steps enumerated above. On a sidenote, we also simulate typing #
before we simulate pressing Ctrl+Insert, because whatever we type after that will appear in both buffers, and Bash does not understand the os.chdir
command, so with that #
sign we make it into a comment for Bash. After the xdotool
stuff, we also perform the actual cd
command in the Bash buffer.
So now, we re-alias cd
to that script, and test it:
It works! That os.chdir("..")
command in the Python buffer was typed automatically. I didn't do it. All I did was type cd ..
in the Bash buffer. You can see that the command #os.chdir("..")
was also automatically typed into the Bash buffer, but since it's a comment it had no real effect.
To make this change permanent, put that alias into ~/.bashrc
, i.e., in your ~/.bashrc
add the line:
alias cd='function cd_to_pybuf { xdotool type "#"; xdotool key Ctrl+Insert; xdotool type "os.chdir(\"$1\")"; xdotool key Return; xdotool key Ctrl+Delete; cd "$1"; }; cd_to_pybuf'
And voilà! That was it.
Bonus: an alias for pwd
Sometimes you may want to check what the current working directory is in both buffers at once. We can use the very same technique as for cd
, and re-alias pwd
. The following command will do the trick, and you can also put it into your ~/.bashrc
if you like:
alias pwd='function pwd_to_pybuf { xdotool type "#"; xdotool key Ctrl+Insert; xdotool type "os.getcwd()"; xdotool key Return; xdotool key Ctrl+Delete; pwd; }; pwd_to_pybuf'
What you will have to remember
For this to work in the future, whenever you open up a split view with a Bash and a Python buffer, you will have to do two things:
- Assign both buffers to the same group in Terminator
import os
in your Python buffer
That's all.
Troubleshooting
This is not perfect. There are some minor problems:
It's a little ugly that this #os.chdir
thingy gets printed to the Bash buffer also. It's really cosmetic, but you might consider doing something different, e.g., after you simulated typing the command and before simulating pressing Return, deactivate broadcasting temporarily and remove that command (e.g., simulate a lot of backspaces, or the sequence Ctrl+A, Ctrl+K) from the Bash buffer or whatever.
Some special arguments to cd
will not work. Things like cd -
(change to $OLDPWD
), cd ~
(change to $HOME
), or cd
(without arguments, also change to $HOME
). Here also, the script could be improved to account for such special cases (check if $1
is special, and translate appropriately). Such things should be a piece of cake from here, though.
Optional parameters to cd
, such as, e.g., cd -P somewhere
, will not work because the translation would be os.chdir("-P")
here. You could use $@
instead of $1
to look at all arguments, and then do the appropriate thing.
Hope I could help :) It was an interesting challenge!