The only workaround I found is to run a script after each terminal prompt, which sets the terminal theme by choosing from the available profiles. You must therefore first create a dark and a light profile via the Preferences menu of the terminal.
Process
To run after each terminal prompt, we will define the PROMPT_COMMAND shell variable in the ~/.bashrc file, such that it calls a function prompt_command (inspired from Bob's answer). The function will be in charge of changing the terminal's theme if necessary and building the prompt in that order:
# ~/.bashrc
function prompt_command {
# script that sets terminal's theme inserts here
# script that builds prompt runs last, for instance:
export PS1="\033[1mmy prompt:\033[0m$";
}
export PROMPT_COMMAND=prompt_command;
To access the different profiles, we make use of the shortcuts on the keyboard (inspired from brotherJ4mes answer): using the sequence Shift+F10 r enter selects profile 1 in the list, sequence Shift+F10 r down enter selects profile 2, Shift+F10 r down down enter profile 3, etc. I did not find a more elegant way to do it.
To run these sequences programmatically, we use xdotool (for the X window system), or ydotool (for other window systems). For clarity, we write a separate script ~/.local/bin/chp that will run these sequences using a variable number of down keystrokes.
# ~/.local/bin/chp
str="";
for (( n = 1; n <= $1; n++ )) do
str="$str down"; # add one "down" key to the sub-sequence
done
run key sequence
eval "ydotool key shift+F10 r$str enter";
Try calling chp 0 from the command line to apply profile 1 in the list, or chp 2 for profile 3. You may notice a warning message from ydotool that you can safely ignore (see Additional remarks). In my case, the "dark" profile is in position 1 and the "light" profile in position 2 as shown in the screenshot:
terminal profile list.
In order to apply the appropriate terminal profile, we need to known which theme is using the system (dark or light). The system theme is stored in GNOME's settings under the key org.gnome.desktop.interface.color-scheme. In my case, it takes the value 'prefer-dark' when in dark mode and 'default' in light mode. You can check it for yourself using the configuration tool dconf-editor.
To obtain the system's theme programmatically, we use:
sys_theme=`gsettings get org.gnome.desktop.interface color-scheme`;
and set the terminal profile accordingly:
case $sys_theme in
"'prefer-dark'")
chp 0;
;;
"'default'")
chp 1;
;;
esac
Finally, to run the key sequence only when the terminal profile needs to be changed (execution of ydotool is annoying for multiple reasons, see Additional remarks), we will set an environment variable TERM_PROFILE that will contain the name of the actual terminal profile. We initialize TERM_PROFILE in ~/.bashrc with a dummy value:
# initialize terminal profile with dummy name
export TERM_THEME="dummy";
and actualize its value each time the terminal profile is changed with prompt_command:
if [ "$sys_theme" != "$TERM_THEME" ]; then
export TERM_THEME="$sys_theme"; # set terminal profile name to actual system theme
fi
In my case, TERM_THEME will take the value 'prefer-dark' when my system is in dark mode, and 'default' when in light mode.
Final script
To wrap it up, this is what my ~/.bashrc file looks like:
# ~/.bashrc
function prompt_command {
# read system theme
sys_theme=gsettings get org.gnome.desktop.interface color-scheme;
# if terminal profile is different from system theme, switch to appropriate profile
if [ "$sys_theme" != "$TERM_THEME" ]; then
export TERM_THEME="$sys_theme";
case $sys_theme in
"'prefer-dark'")
chp 0;
;;
"'default'")
chp 1;
;;
esac
fi
# build prompt, for instance:
export PS1="\033[1mmy prompt:\033[0m$";
}
execute prompt_command function after each prompt
export PROMPT_COMMAND=prompt_command;
initialize terminal profile with dummy name
export TERM_THEME="dummy";
and my ~/.local/bin/chp file looks like:
# ~/.local/bin/chp
str="";
for (( n = 1; n <= $1; n++ )) do
str="$str down"; # add one "down" key to the sub-sequence
done
run key sequence
eval "ydotool key shift+F10 r$str enter";
Additional remarks:
This workaround is not perfect:
- the profile of the terminal will synchronize with the system theme only after a new prompt
- the profile applies to the current tab only (a new prompt in each tab is necessary)
ydotool is rather slow (you may even see the menu opening)
ydotool prints warning ydotool: notice: ydotoold backend unavailable (may have latency+delay issues) each time it is called, meaning each time the theme changes.