xilun / cbwin

Launch Windows programs from "Bash on Ubuntu on Windows" (WSL)
Other
327 stars 25 forks source link

Default command handler #21

Open poma opened 7 years ago

poma commented 7 years ago

Here is a script for people that want to use WSL like Cygwin. If command is not found on Linux it will attempt to run it on windows automatically:

# Whether to attempt to run command from %USERPROFILE% dir.
# This is useful when current path can't be translated to a windows path.
# Also potentially dangerous for example if you run windows delete commands
# in /tmp it may actually delete your windows home dir
ATTEMPT_TO_RUN_IN_HOME_DIR=false

# Choose one from 'wcmd', 'wrun', 'wstart'
COMMAND="wrun"

try_cbwin() {
    if [[ $# -gt 0 ]]; then
        if $COMMAND where "$1" > /dev/null 2>&1; then
            $COMMAND "$@"
            return 0
        fi
        if [ "$ATTEMPT_TO_RUN_IN_HOME_DIR" = true ] && $COMMAND : where "$1" > /dev/null 2>&1; then
            $COMMAND : "$@"
            return 0
        fi
    fi

    return 1
}

save_old_command_handler() {
    if declare -f command_not_found_handler > /dev/null; then
        eval "$(echo "orig_command_not_found_handler(){"; declare -f $1 | tail -n +2)"
        OLD_COMMAND_HANDLER=true
    else
        OLD_COMMAND_HANDLER=false
    fi
}

command_not_found_chain_handler() {
    if try_cbwin "$@"; then
        return 0
    elif [ $OLD_COMMAND_HANDLER = true ]; then
        orig_command_not_found_handler "$@"
        return $?
    else
        return 1
    fi
}

case "${SHELL}" in
    */zsh)
        save_old_command_handler "command_not_found_handler"
        command_not_found_handler() {
            command_not_found_chain_handler "$@"
            return $?
        }
        ;;
    */bash)
        save_old_command_handler "command_not_found_handle"
        command_not_found_handle() {
            command_not_found_chain_handler "$@"
            return $?
        }
        ;;
esac

Just save this script to a file and add source this_script.sh to .bashrc or .zshrc depending on your shell. This is pretty basic implementation, feel free to improve it

zerocool4u2 commented 7 years ago

@poma hi, i'm having some little troubles with this, first, i couldn't ever change my shell to zsh with chsh command, so i start my outbash.exe with ~ -c "zsh --login", so i'm entering to the bash case, because my $SHELL variable is "/bin/bash", then i changed it to command_not_found_handler() to get it properly working, but the thing is that the if statement of try_cbwin gets executed and throws an error because is trying to find a "which" file, if i change it to $COMMAND "$1" then i get the command executed twice, my question is, is this only happening to me because i didn't change the shell properly? and if you could walk me through that if statement on what is doing, i don't really know that much about shell scripting, i know this > /dev/null 2>&1 is for redirect the error output(right?xd), but the first part and what is the which for, no clue, i would really like to have this working and also add support, eventually, for the case of been on the home_directory and automatically append the : for using windows_home_path in those cases, thanks in advance, regards!

poma commented 7 years ago

Try sudo chsh -s /bin/zsh yourUser

The idea of this script is to run which command in windows shell to determine if a file (first argument) exists. We are not interested in its output (hence > /dev/null 2>&1), we just need the return code. If it succeeds then run the whole command in windows. Obviously it will work only for executables and not built-in cmd commands.

I've just realized that my script uses which command provided by Cygwin and that's why it doesn't work on your machine. The windows equivalent for which is where. I've fixed my script to reflect that.

poma commented 7 years ago

Also updated script to allow commands from home dir (false by default) but be careful with it

zerocool4u2 commented 7 years ago

thanks man! works perfect!! i couldn't be happier right now, i really appreciated, chsh in the other hand, still not working, i just change "command_not_found_handle" to "handler" for now, if it becomes a problem in the future, so it be lol, thanks again man and take care, regards! PD: time to delete all those aliases =)

xilun commented 7 years ago

Cool script! Any idea if Ctrl-Z can be made to work properly with it? Oddly suspension is propagated to the win32 side but I don't get back the shell prompt (tried with bash)

xilun commented 7 years ago

Update about Ctrl-Z: hm and it's not just because of the use of a function and not even because of the use of command_not_found_handle. Weird. I will take another look later.

poma commented 7 years ago

Found a bug: this script will override default command-not-found script that suggests to install packages when command is not found (enabled in bash by default and in zsh via command-not-found plugin). Updated my script to copy and invoke old function if it is defined. Also I've missed quotes around @$ in first version. Result is a bit verbose and probably still has some bugs as I have no experience with bash

poma commented 7 years ago

@xilun Ctrl-Z works for me. I can successfully freeze notepad, get shell prompt, and then unfreeze it.

xilun commented 7 years ago

More testing: with this command not found handler, Ctrl-Z works under zsh, but not bash. This might be a bash bug or a WSL bug, I'm looking into it.

xilun commented 7 years ago

This seems to be mainly a bash bug, however the behavior of bash is actually worse on a real Linux system in this case (Ctrl-C after a Ctrl-Z does not work), so there might also be a WSL bug (which in this case slightly improves the usability) to find in there :p