Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take a stab at PROMPT_COMMAND #414

Merged
merged 8 commits into from
Jul 17, 2019

Conversation

jyn514
Copy link
Contributor

@jyn514 jyn514 commented Jul 7, 2019

Location information is wrong - PROMPT_COMMAND=';' gives a traceback
pointing to ~/.local/oil/oshrc instead of [ interactive ] or
[ PROMPT_COMMAND ]

Other than that, this seems to be working pretty well with my patched version of bash-git-prompt.

Addresses #400

Location information is wrong - PROMPT_COMMAND=';' gives a traceback
pointing to ~/.local/oil/oshrc instead of [ interactive ] or
[ PROMPT_COMMAND ]

Addresses oils-for-unix#400
@andychu
Copy link
Contributor

andychu commented Jul 7, 2019

I think this needs to be similar in spirit to WordParser.EvalForPlugin() and Tracer in core/dev.py.

PS4 is evaluating something for every line for set -x. And PROMPT_COMMAND is for every line of the interactive shell.

For example I believe it should avoid changing $? -- I think you reported that bug with $PS1 or something.

That said, if you can add a test case in spec/interactive.test.sh, and make it pass for bash and osh, then we can merge that and figure out all the details in a subsequent change. (e.g. followups for location info.)

- Don't let command change status
- Handle arrays. Previously, osh would crash on `PROMPT_COMMAND=(1 2 3)`
@jyn514
Copy link
Contributor Author

jyn514 commented Jul 7, 2019

My local .profile is messing up the tests for bash. Would you be willing to consider an ignored --noprofile argument for osh? I didn't open an issue since it would basically only be useful for tests.

@andychu
Copy link
Contributor

andychu commented Jul 7, 2019

I usually do something like:

case $SH in *bash) flag='--noprofile' ;; esac
$SH $flag -i ...

Does that work?

@jyn514
Copy link
Contributor Author

jyn514 commented Jul 7, 2019

Hmm, that worked which makes me confused why the tests aren't passing. I'm running test/spec.sh interactive and bash fails all the tests. The weird thing is if I run the command manually, without going through test/spec.sh, it works fine. Here's the test case I'm looking at:

#### fatal errors continue

# NOTE: tried here doc, but sys.stdin.isatty() fails.  Could we fake it?
case $SH in *bash) flag='--noprofile';; esac
$SH $flag -i -c '
echo $(( 1 / 0 ))
echo one
exit 42
'
## status: 42
## STDOUT:
one
## END

Running the command through spec.sh:

$ test/spec.sh interactive -v
interactive.test.sh
case    line    dash    bash    mksh    osh
  0       4     N-I     FAIL    N-I     pass    'exit' in oshrc (regression)
[bash stdout] Expected 'one\n', got 'To run a command as administrator (user "root"), use "sudo <command>".\nSee "man sudo_root" for details.\n\none\n'
bash stdout:
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

one

Running manually:

$ /bin/bash --noprofile --rcfile /home/joshua/Documents/Programming/oil/_tmp/spec-tmp/interactive.test.sh/oshrc -i -c 'echo hello'
one

@andychu
Copy link
Contributor

andychu commented Jul 8, 2019

OK weird, I reproduced this on another machine. Let me see what's going on!

@andychu
Copy link
Contributor

andychu commented Jul 8, 2019

Weirdly it works on Travis:

https://travis-ci.org/oilshell/oil/builds/555543685

@andychu
Copy link
Contributor

andychu commented Jul 8, 2019

I don't understand why /etc/bash.bashrc is being run... but somehow it is... still looking.

https://askubuntu.com/questions/22607/remove-note-about-sudo-that-appears-when-opening-the-terminal

@andychu
Copy link
Contributor

andychu commented Jul 8, 2019

OK I think this is system bash vs. hermetic bash from test/spec-bin.sh. Although Travis maybe has a newer version of Ubuntu.

I think Ubuntu must have patched bash to run /etc/bash.bashrc even if --rcfile is passed?? That is annoying. And maybe they got rid of it in a later version of Ubuntu.

andy@lisa ~/git/oilshell/oil (master)$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
andy@lisa ~/git/oilshell/oil (master)$ _tmp/spec-bin/bash --version
GNU bash, version 4.4.0(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

Here's my Ubuntu:

andy@lisa ~/git/oilshell/oil (master)$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"

@andychu
Copy link
Contributor

andychu commented Jul 8, 2019

I mention the spec-bin stuff here, along with issue #159

https://github.com/oilshell/oil/wiki/Spec-Tests

I guess you just have to compile bash once, and it should go away. And it's better to do that anyway so all the rest of the tests pass. There are definitely differences between bash 4.3 and bash 4.4, so if your system has 4.3 it's worth the time.

- Set $HOME variable so bash doesn't print message about sudo.
See oils-for-unix#414 (comment)
- Don't source startup files, they could print a message (and in my
case, did)
@jyn514
Copy link
Contributor Author

jyn514 commented Jul 16, 2019

I set HOME instead and that seems to have fixed it. I do have 4.4 installed, I don't think it's a version error.

@jyn514
Copy link
Contributor Author

jyn514 commented Jul 16, 2019

I added a test case, could you take another look?

core/main_loop.py Outdated Show resolved Hide resolved
core/main_loop.py Outdated Show resolved Hide resolved
case $SH in
*bash) echo "$TEST_CASE" | $SH --noprofile --norc -i;;
*osh) $SH --rcfile /dev/null -i -c "$TEST_CASE";;
*) $SH -i -c "$TEST_CASE";;
Copy link
Contributor

@andychu andychu Jul 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm also this seems to be doing a ton of stuff that's different for each shell, which makes the validity of the test hard to gauge at a glance.

Are you trying to avoid the spurious stdout from bash?

If doing the test/spec-bin.sh stuff in your environment fixes it, then please do that instead.

I added test/spec.sh interactive on Travis, and it doesn't have that problem. For now that is sort of the "golden environment".

If for some reason you can't get a _tmp/spec-bin/bash, or the instructions don't make sense, let me know.

Copy link
Contributor Author

@jyn514 jyn514 Jul 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that should have been commented. This isn't an issue with spurious output, this is because osh and bash have different ideas of what it means to be interactive.

bash -i -c 'PROMPT_COMMAND="echo hi"' does not give any output, but echo 'PROMPT_COMMAND="echo hi"'' | bash -i does.

osh goes the other way and prints the prompt:

$ echo 'PROMPT_COMMAND="echo hi"' | osh -i
osh$ hi
osh$ ^D
$

I agree not having the same test for both isn't ideal but I didn't see another way to check this.

@jyn514
Copy link
Contributor Author

jyn514 commented Jul 17, 2019

Speaking of exceptions, this patch crashes osh if PROMPT_COMMAND throws an exception:

(osh) ~/.../Programming/oil ▶️ echo 'PROMPT_COMMAND=""; :' | bin/^C
(osh) ~/.../Programming/oil ▶️ PROMPT_COMMAND='which which'
/usr/bin/which
(osh) ~/.../Programming/oil ▶️ prlimit --nproc=1 --pid=$$
osh I/O error: Resource temporarily unavailable
(bash) ~/src/oil ▶️

I'm looking into how EvalForPlugin works.

@jyn514
Copy link
Contributor Author

jyn514 commented Jul 17, 2019

I'm not sure how to treat the word returned by EvalForPlugin as a command substitution, I have the following code but it just prints the word instead of running a command.

  w_parser = parser.parse_ctx.MakeWordParserForPlugin(command)
  try:
    ps1_word = w_parser.ReadForPlugin()
  except util.ParseError as e:
    ps1_word = word.ErrorWord("<ERROR: Can't parse PS1: %s>", e)
    _parse_cache[ps1_str] = ps1_word

  # Evaluate, e.g. "${debian_chroot}\u" -> '\u'
  print(ex.word_ev.EvalForPlugin(ps1_word).s)

@andychu
Copy link
Contributor

andychu commented Jul 17, 2019

I think that behavior is OK for now.

I will probably do some refactoring, i.e. instead of _Eval, add something like RunFuncForCompletion. But if some new tests pass, then I won't worry too much about the details.

OK thanks for letting me know about the bash/osh difference. Please add a comment about that in the test.

My main issue now is setting $HOME because your version of bash is reading a file in ~. That is sort of regressing against issue $42.

We could set $HOME to something _tmp/spec-tmp/dummy-home, but it shouldn't be the actual HOME dir, which can have arbitrary files.

I think it will pass on Travis without that, so please remove it for now, and then we can figure out what to do if it's still failing on your machine.

Avoids dependence on files in HOME.
Requested in oils-for-unix#414 (comment)
@jyn514
Copy link
Contributor Author

jyn514 commented Jul 17, 2019

Ok I took HOME out, let me know if there's any more changes I should make. The tests are failing locally, I'm going to try building bash from source finally.

Yup, building from source fixed it. Maybe we should add that to the wiki?

@andychu
Copy link
Contributor

andychu commented Jul 17, 2019

Great, yes feel free to update the wiki!

@andychu andychu merged commit 54272e8 into oils-for-unix:master Jul 17, 2019
@andychu
Copy link
Contributor

andychu commented Jul 17, 2019

BTW I got the tests working roughly the same under bash/OSH:

82d22cc

Thanks for adding this!

@jyn514 jyn514 deleted the feature/prompt-command branch July 17, 2019 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants