1

I have these function:

#execute vim and then exit on err return
ve() {
    vim "$@" || exit
}
export -f ve

#compile c source -> asm source in new tab in xfce terminal
casm() {
  [ -z ${1} ] && return
  fname=$1
  xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; ve $fname.s ;exec bash \""
}
export -f casm

In this case, the ve function ("vim and exit" == "ve"), is called in the second one in double quotes (see here:gcc -S $fname.c; ve $fname.s ;exec bash). The problem is the bash will give err bash: ve: command not found (I have export it afterwards, as you can see), I do not know what else I should do to make it more visible.

For second try, I have tried this:

#compile c source -> asm source in new tab in xfce terminal
casm() {
  [ -z ${1} ] && return
  fname=$1
  xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; $(ve $fname.s) ;exec bash \""
}
export -f casm

That is - make the command to be subshell, but then when trying to open it -> Vim: Warning: Output is not to a terminal, which makes it to crash the terminal. So the question is, how to embed a global function in double quotes and make it safe?

ctrl-alt-delor
  • 27,473
  • 9
  • 58
  • 102
Herdsman
  • 320
  • 4
  • 20
  • In the second, the command substitution is in double quotes, so it gets expanded before `xfce4-terminal` runs. It looks like the function doesn't end up in the inner shell at all. I don't know why xfce4-terminal or anything should clean it out from the environment, but if it was there, you shouldn't get "command not found" for it – ilkkachu Jun 02 '20 at 18:29
  • Your goal is not clear to me, but if the problem is related to the double quotes after `-e`, consider using `-x` instead. – Quasímodo Jun 02 '20 at 19:35
  • Possibly related to https://unix.stackexchange.com/questions/505358/how-to-export-functions-from-profile-during-graphical-login (the terminal emulator, or a shell spawned by it may clean up the environment and delete the exported functions before running the `bash -c` script). – Kusalananda Jun 02 '20 at 19:44

2 Answers2

0

Your first solution works flawlessly on my system.

Try testing it on another system: You may have something broken on your system.

In the second example, you can force vim to use /dev/tty:

ve() {     vim "$@" </dev/tty >/dev/tty || exit; }
Ole Tange
  • 33,591
  • 31
  • 102
  • 198
  • But this somehow breaks the ability to open the file in new tab (which it did before, with the `xfce4-terminal --tab ...`), is it different to use ` /dev/stdout`? or does /dev/tty means the same? – Herdsman Jun 02 '20 at 18:37
0

Trying this on Xubuntu, it seems like xfce4-terminal doesn't actually start a new process to run the new terminal window. Instead, it just calls on the existing process to create it. The shells I started in different windows were all children of the same xfce4-terminal process.

This means that the environment variables used to pass the function along can't be passed to the new shell, as it's not a child of the first one, the one where you exported the function. If you don't have a copy of xfce4-terminal running, then it does start a new process and the environment variables get passed ok. Or, if you run e.g. xterm instead, since it always creates a new process.

This is similar to but different from the issue Kusalananda linked in the comments, How to export functions from .profile during graphical login, but the same solution should work:

Put the function definition in ~/.bashrc instead, it should get read by the shells started here. If not, then you'll have to do it explicitly in the inner shell bash -c '. ~/.bashrc; gcc ...'.


In your second snippet:

xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; $(ve $fname.s) ;..."

The command substitution is in double quotes, so it's expanded right here and now, before xfce4-terminal is launched. So, regardless of if it's exported properly, it runs. Though even if it worked from inside the command substitution, it wouldn't do what you want since it would run before the compiler.

ilkkachu
  • 133,243
  • 15
  • 236
  • 397