oils-for-unix / oils

Oils is our upgrade path from bash to a better language and runtime. It's also for Python and JavaScript users who avoid shell!
http://www.oilshell.org/
Other
2.85k stars 159 forks source link

Run bash-git-prompt #400

Open jyn514 opened 5 years ago

jyn514 commented 5 years ago

See https://github.com/magicmonty/bash-git-prompt.

Current errors:

    declare -Ff "${1}" >/dev/null;
    ^~~~~~~
gitprompt.sh:626: Assignments shouldn't have redirects
    declare -Ff "${1}"; # >/dev/null;
                ^
gitprompt.sh:626: Variable names must be unquoted constants

Note that this might be easier to fix upstream, since this would be better expressed as [ "$(type -t "${1}")" = function ].

PROMPT_COMMAND is not implemented, which bash-git-prompt makes heavy use of. From man bash:

PROMPT_COMMAND
              If  set,  the  value  is executed as a command prior to issuing each primary
              prompt.
andychu commented 5 years ago

The first issue is mentioned here:

https://www.oilshell.org/release/0.6.0/doc/known-differences.html#toc_12

I suspect that is one I might end up having to hide behind shopt -s strict-redirect, so scripts like this will run.

Actually, on second thought I think this might be overzealous. Let me file another issue.


The second one could be fixed by #236 , although it may take awhile for that to happen. And I agree it could be replaced by type -t.


Thanks for testing it! I definitely want to get more stuff like this running.

jyn514 commented 5 years ago

Found something strange about PROMPT_COMMAND: it's not executed the same as if you ran it on the command line. If you set SOME_VAR='echo;echo;' and then run $SOME_VAR, both bash and osh will say echo;echo: command not found, but if you set PROMPT_COMMAND='echo;echo' in bash, it will output two newlines.

andychu commented 5 years ago

Yeah I think PROMPT_COMMAND is basically like the argument to trap or eval. The whole string gets parsed an executed as a shell program. (PS1 is similar except it's a WORD, not a COMMAND.)

I have a rough list of such "plugins" here:

https://github.com/oilshell/oil/blob/master/doc/architecture-notes.md

$SOME_VAR is subject to word splitting, but ; isn't in $IFS. If you have SOME_VAR='echo echo it does the right thing.

andychu commented 5 years ago

FWIW bash is inconsistent with its plugins:

I think PS1 could also be a function too.

The plugins are enumerated here:

https://www.oilshell.org/release/0.6.0/doc/osh-quick-ref.html

I think it might be nice to provide "Oil versions" of these eventually with a consistent interface (e.g. add func to the language and be able to return a string), but for now it's important to run existing programs like bash-git-prompt.

jyn514 commented 5 years ago

How would I get an instance of an arg_vec? I'm looking at osh/cmd_exec.py and it has a function called _Eval that's perfect for this but if I pass it a string it throws a bunch of errors. I'm not using MakeOshParser directly because I'm putting the code in core/main_loop.py, which might run oil instead of osh in the future.

andychu commented 5 years ago

@jyn514 Can you tell me if this is closer to running with 0.7.pre2? I think it should be with the dynamic assignment fixes.

jyn514 commented 5 years ago

Different errors now, making progress!

(osh) ~/.../unchanged/bash-git-prompt ▶️ . gitprompt.sh 
  if [[ -z "${ColorNames+x}" || "${#ColorNames[*]}" = 0 || -z "${IntenseBlack:+x}" || -z "${ResetColor:+x}" ]]; then
            ^~
/home/joshua/Documents/Programming/unchanged/bash-git-prompt/prompt-colors.sh:76: fatal: Array 'ColorNames' can't be referred to as a scalar (without @ or *)
[%1] Started PID 18932
          disown -h
          ^~~~~~
gitprompt.sh:442: 'disown' not found
  if [[ -z "${ColorNames+x}" || "${#ColorNames[*]}" = 0 || -z "${IntenseBlack:+x}" || -z "${ResetColor:+x}" ]]; then
            ^~
/home/joshua/Documents/Programming/unchanged/bash-git-prompt/prompt-colors.sh:76: fatal: Array 'ColorNames' can't be referred to as a scalar (without @ or *)
jyn514 commented 5 years ago

Disown is #261.

I'm not sure what's going on with ColorNames, here's the relevant code:

define_color_names() {
  ColorNames=( Black Red Green Yellow Blue Magenta Cyan White )

  # def_color NAME ATTRCODE COLORCODE
  _def_color() {
    local def="${1}=\"\`_term_color ${2} ${3}\`\""
    eval "${def}"
  }

  _def_color IntenseBlack 0 90
  _def_color ResetColor   0 0
}

# do the color definitions only once
if [[ -z "${ColorNames+x}" || "${#ColorNames[*]}" = 0 || -z "${IntenseBlack:+x}" || -z "${ResetColor:+x}" ]]; then
  define_color_names
fi

${ColorNames+x} gives 'x' in bash.

andychu commented 5 years ago

Yeah that is an intentional difference and requires a patch unfortunately:

https://www.oilshell.org/release/0.7.pre2/doc/known-differences.html#toc_19

Technically speaking it is equivalent to this, adding a [0] for the first entry.

if [[ -z "${ColorNames[0]+x}"

But honestly I don't know why they are doing that, since the next thing tells if the array is empty:

 || "${#ColorNames[*]}" = 0 

But I think it's safe to just mechanically add [0] and not worry about this super weird code!