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

Example of customization: left prompt only, $ as the symbol #9

Closed
wants to merge 3 commits into from

Conversation

borekb
Copy link

@borekb borekb commented Jul 7, 2018

UPDATE: the customization via forking is no longer necessary, see #9 (comment).


First of all, thank you for this prompt. On Mac, I use the Pure prompt but that doesn't work on Windows due to the zsh/zpty issue in zsh-async (mafredri/zsh-async#26). Yours is the only one I found so far that works in MSYS2 and is asynchronous, which is awesome.

Now, I prefer the simpler style of pure so I've customized your prompt a bit. I don't expect a merge or anything but wanted to share this as a possible inspiration for others.

A side note is that it seems to me that most prompts hardcode a lot of decisions into their source codes, which makes forking the only way to customize them. I have a very limited knowledge of shell scripting and was in awe looking at the source code of this prompt, almost none of which I understood, but it would be great, IMO, if I could easily specify the left/right location of various pieces of info, whether to include them at all, etc.

The forked prompt with some slight color customization (AGKOZAK_COLORS_BRANCH_STATUS=243) looks like this:

image

@borekb borekb force-pushed the prompt-customization branch from ab16353 to bba91ce Compare July 7, 2018 20:58
@borekb
Copy link
Author

borekb commented Jul 8, 2018

@agkozak would you possibly be interested in making your prompt fully customizable? For example, as I was looking for a prompt, I was usually interested in customizing:

  • Which character (and color) is used before the command.
  • The above but per a couple of typical conditions such as normal vs. error state, standard vs. elevated prompt, etc.
  • How to present the path, and where (full / trimmed / nor included at all; if included, in left prompt or in right prompt?)
  • Same for user@host, possibly depending on whether this is a local or SSH session.
  • How to present Git info (which characters and colors to use for various states), and where (left vs. right prompt).

I know this would be quite some work and that's probably the reason why most prompts hardcode a lot of things but it would be so nice to be able to do that without forking.

@agkozak
Copy link
Owner

agkozak commented Jul 8, 2018

@borekb,

Thank you so much for your kind words and encouragement. I am keen to implement the sort of changes that you recommend. First, though, a little history.

The agkozak-zsh-theme was originally merely a rewriting in ZSH code of my pan-POSIX prompt Polyglot, which attempts to provide more or less the same Git prompt in all relevant POSIX shells without using any symbols that could interfere with any terminals or fonts that I might happen to use. I decided to write a ZSH-specific version of the theme because I saw how much simpler and more elegant the script could be (here it is before I introduced any asynchronicity into it!).

Like you, however, I frequently use MSys2 (and, to a lesser extent, Cygwin). You know from experience how uncommonly slow forking is in those environments. I can think and type faster than git status can execute! And like you, I was disappointed that the major asynchronous ZSH prompts simply won't work in MSys2 or Cygwin because they require a working zpty module. It was for that reason that I introduced the three-tiered system of zsh-async with zpty, falling back to a TRAPUSR1-based asynchronous method on MSys2, Cygwin, and even some configurations of Linux and BSD, and falling back only in rare instances to a synchronous method.

I can now see that the three-tiered asynchronous system is useful enough in its own right to justify making the theme transcend the layout choices I imposed on it. @joeleisner was kind enough to contribute the system of color choices you see that it has now. Your suggestions are all worthy of consideration, and I will start working immediately to introduce more variables to effect the look-and-feel customizations that you propose. I shall probably start by creating a branch to experiment in. I will keep you and any other interested parties aware of new customizations as I implement them.

Thank you so very much for contributing to this project.

@borekb
Copy link
Author

borekb commented Jul 9, 2018

That sounds excellent! I also think that it is quite uncommon that a prompt author would be so open to customization :)

I'll just throw an idea around: if my prompt looks like this:

.../some/path User                                       [master*]
$

maybe there could be a mini-language that would allow me to specify the prompt via something like this (inspired by chalk-cli and ES2015 template literals):

path='{green ${promptvars.path.trim(2)}}'
user='{color(240) ${promptvars.user}}'
symbol='${promptvars.exitCode === 0 ? {yellow $} : {red (${promptvars.exitCode}) $}}'
gitInfo='{gray ${promptvars.git.branch}${promptvars.git.status}}'

PROMPT_TEMPLATE='${path} ${user}
${symbol}'

RPROMPT_TEMPLATE='${gitInfo}'

I guess in the end, it's just an attempt to make the built-in syntax more readable so that non-experts like me would be able to customize it. I can imagine you have better ideas though :)

Thanks a lot!

@joeleisner
Copy link
Contributor

joeleisner commented Jul 11, 2018

Hey, everyone!

Just wanted to stop by, as I saw @agkozak 's mention of me (thank you for the kind words, by the way; always glad to contribute). After reading through the thread, I definitely like the idea of making the prompt's structure more configurable.

My initial thought was having a AGKOZAK_TEMPLATE string similar to how GTK handles window button configuration: user_host,path,symbol:git (, delineates different components, while the: separates the left/right of the prompt). This could then be parsed and replaced with the proper components. Not only would this be super readable, but new user's would have a much easier time customizing things.

Just an idea! I'm excited to see what comes of this thread.

@agkozak
Copy link
Owner

agkozak commented Jul 13, 2018

I'm inclined to advocate a simpler system that is closer to how ZSH works natively -- perhaps as a sort of shorthand for the real thing. For example, I've written a mere 33 lines of code that can construct @borekb's prompt expressed as

AGKOZAK_PROMPT=(
    bold fg_red exit_status reset
    bold fg_blue path reset space
    fg_243 git reset newline
    $ space
)

That's a simple array that I can iterate over. An example of the default theme expressed thus can be provided in the documentation as a template. And ultimately, as the user learns more about what ZSH can do, he or she will want to add some native code. For example, @borekb's prompt has no way of indicating if he's a superuser; if he wanted to do so he could change it to

AGKOZAK_PROMPT=(
    bold fg_red exit_status reset
    bold fg_blue path reset space
    fg_243 git reset newline
    zshcode'%(!.#.$)' space
 )

meaning that there's some ZSH code here: If superuser, prompt character is #, otherwise $. If we create a metalanguage capable of expressing a ternary condition in a prompt or any of the other lovely features ZSH provides, it will end up being as complex as ZSH code and less well documented.

In any case, the first thing I'll do is to come up with a simple way to override the default prompt. I'll let you know when that's ready.

@agkozak
Copy link
Owner

agkozak commented Jul 13, 2018

I suppose we could eventually add a feature where the elements that make up the prompt are defined in an additional associative array; that way it would be easy for people to add new elements and redefine default ones. That would allow for maximum configurability without muddling up the environment with hundreds of option variables.

@borekb
Copy link
Author

borekb commented Jul 13, 2018

That looks awesome! You seem to hit a great balance between customizability, simplicity and staying true to zsh. 👍

@agkozak
Copy link
Owner

agkozak commented Jul 13, 2018

Thanks, @borekb! I'll finish off something quickly for us to experiment with. Perhaps I can even use your customizations as an example in the documentation.

@agkozak
Copy link
Owner

agkozak commented Jul 30, 2018

I am making progress on a macro language for describing prompt themes. In the meantime, I thought it would be helpful to provide a simple way to make the sort of changes @borekb described without having to fork the repo.

@borekb, if you check out the develop branch of my prompt, you'll see that I've included two variables for specifying prompt strings to replace the default ones: AGKOZAK_CUSTOM_PROMPT and AGKOZAK_CUSTOM_RPROMPT. I used your specifications in the documentation (see under "Custom Prompts") as an example. If you include the following in your .zshrc

AGKOZAK_CUSTOM_PROMPT='%(?..%B%F{red}(%?%)%f%b )'
AGKOZAK_CUSTOM_PROMPT+='%(!.%S%B.%B%F{green})%n%1v%(!.%b%s.%f%b) '
AGKOZAK_CUSTOM_PROMPT+=$'%B%F{blue}%2v%f%b%(3V.%F{243}%3v%f.)\n'
AGKOZAK_CUSTOM_PROMPT+='$(_agkozak_vi_mode_indicator) '

AGKOZAK_CUSTOM_RPROMPT=''

you should get your theme. Let me know what you think. If you agree that this works, we can call it version 2.1 of the theme, with theme templating to follow in version 3.0.

@borekb
Copy link
Author

borekb commented Jul 30, 2018

That is just great! I needed to update your example a bit, this gives me exactly the same as on screenshots above:

AGKOZAK_CUSTOM_PROMPT=$'\n'
AGKOZAK_CUSTOM_PROMPT+='%(?..%B%F{red}(%?%)%f%b )'
AGKOZAK_CUSTOM_PROMPT+=$'%B%F{blue}%2v%f%b%(3V.%F{243}%3v%f.)\n'
AGKOZAK_CUSTOM_PROMPT+='$(_agkozak_vi_mode_indicator) '

AGKOZAK_CUSTOM_RPROMPT=''

_agkozak_vi_mode_indicator() {
  case $KEYMAP in
    vicmd) print -n ':' ;;
    *) print -n '%(!.#.$)' ;;
  esac
}

Cool that I can get rid of my fork now!

@agkozak
Copy link
Owner

agkozak commented Jul 30, 2018

You've got it! For that matter, you can even change the top lines to

AGKOZAK_BLANK_LINES=1
AGKOZAK_CUSTOM_PROMPT='%(?..%B%F{red}(%?%)%f%b )'

and you'll get the same effect, but without that annoying (to me) initial blank line in every terminal. You'll still get blank lines after that.

In the custom branch I'm already adding features such as the ability to pass the _agkozak_vi_mode_indicator function symbols as parameters to use for vi command mode, vi insert mode, and Emacs mode, but I wouldn't recommend using that branch for right now -- it's bound to change a lot from day to day, and your customizations will break. I'll start introducing features into master when I'm sure they won't have to change in the future.

I think I'm going to rename the project to "The agkozak ZSH Prompt," instead of agkozak-zsh-theme. It's a themable prompt now -- it was never really a theme, right? If I go so far as to rename the repo, Github should handle the redirects sufficiently, I think.

@borekb
Copy link
Author

borekb commented Jul 30, 2018

and you'll get the same effect, but without that annoying (to me) initial blank line in every terminal. You'll still get blank lines after that.

Thanks, that's a good tip – something was a little bit annoying compared to my fork and I didn't know what. Now I know :)

I think I'm going to rename the project to "The agkozak ZSH Prompt," instead of agkozak-zsh-theme. It's a themable prompt now -- it was never really a theme, right? If I go so far as to rename the repo, Github should handle the redirects sufficiently, I think.

Yes, GitHub should redirect everything. I also think renaming this prompt is a very good idea, just didn't dare to suggest it :) I'd probably go even further and gave it some short and sweet name, it also affects how the variables look (typically). As an inspiration, I think that Pure is a beautiful name for a prompt. Naming is hard though...

@agkozak
Copy link
Owner

agkozak commented Jul 30, 2018

Perhaps I'll think of a more marketable name while I finish the macro language. :) For now, I've just changed everything having to do with "theme" to "prompt." That's been bugging me for months, and soon we will have real themes.

Thanks for the kind words on Twitter, and thanks again for all the encouragement!

@borekb
Copy link
Author

borekb commented Jul 30, 2018

Thanks for all the discussion here, and I'm thrilled that you're creating a fully customizable prompt as a result.

I've updated the OP to point to the new customizability in the developer branch and will close this PR. Feel free to ping me if you want help with testing or anything. Cheers!

@borekb borekb closed this Jul 30, 2018
@agkozak
Copy link
Owner

agkozak commented Jul 30, 2018

Thanks. I just moved the latest updates to the master branch, so everyone should be able to find them.

@joeleisner
Copy link
Contributor

Great work! Excited to try out these changes.

@agkozak
Copy link
Owner

agkozak commented Jul 21, 2019

@borekb I'm putting together a collection of some of the nicer customizations people have constructed with agkozak-zsh-prompt, and I noticed that with recent additions to the prompt, your

AGKOZAK_CUSTOM_PROMPT=$'\n'
AGKOZAK_CUSTOM_PROMPT+='%(?..%B%F{red}(%?%)%f%b )'
AGKOZAK_CUSTOM_PROMPT+=$'%B%F{blue}%2v%f%b%(3V.%F{243}%3v%f.)\n'
AGKOZAK_CUSTOM_PROMPT+='$(_agkozak_vi_mode_indicator) '

AGKOZAK_CUSTOM_RPROMPT=''

_agkozak_vi_mode_indicator() {
  case $KEYMAP in
    vicmd) print -n ':' ;;
    *) print -n '%(!.#.$)' ;;
  esac
}

can now be expressed as simply as

AGKOZAK_COLORS_BRANCH_STATUS=243
AGKOZAK_BLANK_LINES=1
AGKOZAK_LEFT_PROMPT_ONLY=1
AGKOZAK_PROMPT_CHAR=( '$' '#' ':' )
AGKOZAK_USER_HOST_DISPLAY=0

Progress!

@borekb
Copy link
Author

borekb commented Jul 21, 2019

Very nice!

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.

3 participants