brandon-fryslie / rad-shell

Ultra fast, feature filled Zsh installation
MIT License
37 stars 7 forks source link

Zgenom #11

Open jandamm opened 3 years ago

jandamm commented 3 years ago

Hi @brandon-fryslie,

I've created a maintained fork of zgen called zgenom.

It comes with a few improvements like:

I'd be happy if you have a look.

Cheers Jan

brandon-fryslie commented 1 year ago

Hi @jandamm I really appreciate you reaching out! I don't check this repository often because the plugins are in a different repository.

I did a pursal of your docs for zgenom and it looks fantastic.

So I'm curious - have you used rad-shell in any way? It's basically a "quick start" for zgen and prezto. The original motivation behind it was that I was working at a company using oh-my-zsh and each terminal took 5+ seconds to load. It was also in a private repo and I knew I wouldn't be there forever. So I just reimplemented it first with antigen, and then with zgen.

If you're still interested in this whatsoever, I would love to get your opinion and talk about this more.

With rad-shell you'll have a file (~/.rad-plugins) that looks something like this (this is my exact file excluding a few private plugins):

# Load Homebrew near the top
brandon-fryslie/rad-plugins homebrew

# Load some dotfile aliases
brandon-fryslie/rad-plugins dotfiles

# 3rd Party plugins
ohmyzsh/ohmyzsh plugins/docker

# Enhanced fork of zaw
brandon-fryslie/zaw
zsh-users/zsh-autosuggestions / develop
zsh-users/zsh-completions

brandon-fryslie/rad-plugins zaw
brandon-fryslie/rad-plugins docker
brandon-fryslie/rad-plugins git
brandon-fryslie/rad-plugins golang
brandon-fryslie/rad-plugins iterm
brandon-fryslie/rad-plugins nvm-lazy-load
brandon-fryslie/rad-plugins sdkman
brandon-fryslie/rad-plugins shell-tools
brandon-fryslie/rad-plugins rad-dev
apachler/zsh-aws / main

...

This initializes the plugins when you open a shell:

  # Here is where we load plugins from $HOME/.rad-plugins
  while read -r line; do
    if [[ ! $line =~ '^#' ]] && [[ ! $line == '' ]]; then
      echo "Loading plugin: $line"
      eval "zgen load $line"
    fi
  done < $HOME/.rad-plugins

this is the entire init file: https://github.com/brandon-fryslie/rad-shell/blob/master/rad-init.zsh#L44

This allows your ~/.zshrc file to look something like this:

# Init rad-shell
source ~/.rad-shell/rad-init.zsh

# Add customizations below.  Set options in plugins, functions, whatever else

# Theme configuration
export ENABLE_DOCKER_PROMPT=true
export LAZY_NODE_PROMPT=true

# Configures plugins
export PROJECTS_DIR="$HOME/code"
export DOTFILES_DIR="$HOME/code/dotfiles"

...
brandon-fryslie commented 1 year ago

The reason I asked whether you have used rad-shell or not is go get an idea of whether that functionality would be useful for zgenom, and how you would expect things to integrate. If you're still interested, I'd be happy to support zgenom.

zgenom sound like a drop-in replacement and should be trivial to test.

Thanks for reaching out!

brandon-fryslie commented 1 year ago

I'm joined the mastodon server so maybe when that's approved I'll be able to have a brief chat / exchange of ideas. Here are the motivations behind rad-shell

There is also kind of a "help system" but it's still not discoverable by most users. I use keyboard shortcuts for everything and many users aren't quite there yet.

My todo list would be something like this:

brandon-fryslie commented 1 year ago

It's actually been quite a while since I thought of these things. Thanks for reminding me, even if it was a few years ago :) Hopefully you haven't lost interest

jandamm commented 1 year ago

Hey @brandon-fryslie, that's a long answer 😅

No I haven't tested rad she'll. Back in the day I did a simple search for the most common usage patterns of zgen (mostly zgen load) and notified the repos with more than 1 or 2 stars that there is a maintained fork of zgen.

Yes if you source zgen.zsh instead of the default zgenom.zsh it'll define the zgen command. In case zgenom will deviate more from zgen in the future sourcing zgen.zsh will make sure everything still works.

Using only basic zgenom will improve the loading speed by compiling the plugins. Also you don't have to define the main branch anymore.

The while read -r line block could easily be implemented as an extension to zgenom. Something like zgenom load-file path/to/plugin/file.

Another thing that could be extracted for tighter integration with zgenom would be zgenom rad-plugins ... which would do basically the same as the zgenom ohmyzsh ... command.

jandamm commented 1 year ago

In case you haven't seen the extension part in the readme.

It's an easy way to add additional commands to zgenom. It allows for full lazy loading of the command, adds completion and help entry. There is also zgenom api which is a stable way to get some needed internal values from zgenom to allow a nice api in the extension.

There are for example extensions to download and install GitHub releases or create plugins by evaluating a string.

Using extensions quite easy too. Just use zgenom load username/extension-repo and then the extension is ready to use.

brandon-fryslie commented 1 year ago

Thanks @jandamm! I had a chance to look at the zgenom docs more closely and seems like it would be trivial to switch over.

Back in the day I did a simple search for the most common usage patterns of zgen (mostly zgen load) and notified the repos with more than 1 or 2 stars that there is a maintained fork of zgen.

Ah good thinking!

It's an easy way to add additional commands to zgenom.

Thanks, that's a cool feature and I'll look into it further. rad-shell itself is pretty simple. It's main purpose is to configure zgen/zgenom, a very minimal set of base zsh plugins, and load user plugins from a separate plugins file. A ~/.zshrc file with fully configured zgen or zgenom looks like this:

# Init rad-shell
source ~/.rad-shell/rad-init.zsh

# Add customizations below.  Set options in plugins, functions, whatever else

# Configure some plugins
export PROJECTS_DIR="$HOME/code"
export DOTFILES_DIR="$HOME/code/dotfiles"
...

It allows you to keep a separate file containing the list of zsh plugins to use, rather than keeping them in your ~/.zshrc file inside blocks of logic. It loads a very minimal set of zsh plugins that are mostly required to run other common plugins without issues, and defines a few prefixed internal functions for usage by plugins.

Then your plugins file looks like this:

# 3rd Party plugins
ohmyzsh/ohmyzsh plugins/docker
zsh-users/zsh-autosuggestions / develop
zsh-users/zsh-completions
...

These are passed directly to zgen/zgenom, so any method of defining plugins that is compatible with zgenom would automatically be supported.

If I wanted to detect whether zgenom is already present on a system, what's the best way to do that? I think rad-shell could be useful for any users of zgen or zgenom. I'd like to make sure it properly handles existing installations so I can get more feedback. Thanks again

jandamm commented 1 year ago

There's no direct way of checking whether zgenom is installed. If it is already used you can check ZGEN_SOURCE or ZGEN_DIR which is where zgenom is installed and where plugins should be installed. ZGEN_DIR might be overridden by the user and therefore be set before rad-shell is used but I advise against modifying the variable.

One downside of the plugin file is that it only supports zgen load.

A feature you could add is zgenom autouodate it'll periodically check for updates of plugins and zgenom. But it does it in the background so you won't be bothered by it. Just get a log once in a while. You might be able to use it to update rad-shell as well.

Another feature you could use is "reset on file change" it watches for changes in a file and will then reset zgenom and download new plugins automatically. Currently this feature is exactly how it has been in zgen but I have a proof of concept to make fast enough to not notice it.

jandamm commented 1 year ago

Thanks, that's a cool feature and I'll look into it further. rad-shell itself is pretty simple.

An extension would be rather a way to make code of rad-shell usable with zgenom alone while still being able to use it in rad-shell. (I'm mainly talking about loading plugins from a file)

jandamm commented 1 year ago

Don't mind the extension for loading the plugin file.

  # Here is where we load plugins from $HOME/.rad-plugins
  while read -r line; do
    if [[ ! $line =~ '^#' ]] && [[ ! $line == '' ]]; then
      echo "Loading plugin: $line"
      eval "zgen load $line"
    fi
  done < $HOME/.rad-plugins

could be replaced with

zgenom loadall < $HOME/.rad-plugins

(Even with zgen)

brandon-fryslie commented 1 year ago

Another feature you could use is "reset on file change" it watches for changes in a file and will then reset zgenom and download new plugins automatically.

This is how rad-shell works

zgenom loadall < $HOME/.rad-plugins

Nice! The more I'm thinking about it, the more I think you could probably build rad-shell functionality into zgenom itself. Here is the core rad-shell functionality:

I can't easily build this functionality into zgenom, because the point of rad-shell is that I don't really need to care it's zgen or zgenom or antigen or anything under the hood. I have a single line install, and I have a single source line in my .zshrc and it's done. I can use a few env vars to configure the loading process

If you had a ~/.zgenom-plugins file, a one line install, and the ability to install a "pluginset" from a URL I could keep in git, I don't think anyone would need rad-shell itself (maybe this exists already). Everything else is just a standard zsh plugin. This is what my plugin file looks like

# Load Homebrew near the top
brandon-fryslie/rad-plugins homebrew

# Load some dotfile aliases
brandon-fryslie/rad-plugins dotfiles

# 3rd Party plugins
ohmyzsh/ohmyzsh plugins/docker

# Enhanced fork of zaw
brandon-fryslie/zaw
zsh-users/zsh-autosuggestions / develop
zsh-users/zsh-completions

brandon-fryslie/rad-plugins zaw
brandon-fryslie/rad-plugins docker
brandon-fryslie/rad-plugins git
brandon-fryslie/rad-plugins golang
brandon-fryslie/rad-plugins iterm
brandon-fryslie/rad-plugins nvm-lazy-load
brandon-fryslie/rad-plugins sdkman
brandon-fryslie/rad-plugins shell-tools
brandon-fryslie/rad-plugins rad-dev
apachler/zsh-aws / main

# Private work plugins plugins
git@github.private.net:brandon-fryslie/rad-team1-plugin.git
git@github.private.net:brandon-fryslie/rad-team2-devops-plugin.git

### Themes
brandon-fryslie/rad-plugins git-taculous-theme/git-taculous
# denysdovhan/spaceship-prompt
### / Themes

# Load these last
brandon-fryslie/zsh-syntax-highlighting
brandon-fryslie/rad-plugins shell-customize
jandamm commented 1 year ago

This is how rad-shell works

Does it use its own code for that?

The more I'm thinking about it, the more I think you could probably build rad-shell functionality into zgenom itself.

This is actually a non-goal. Zgenom doesn't make any assumptions what kind of plugins you like. There won't be any default plugins installed. That's also the reason why extensions exist. The scope of zgenom is to download, source and update plugins the user specifies. And it tries to do that as smooth as possible. Downloading binary files or creating plugins via heredoc is not part of that scope so they only exist as extensions.

While I like the idea of a plugin file I couldn't express my usage of zgenom in only a plugin file. Also I don't consider the usage of zgenom complicated. Yes it's more than one line but you can get along with 3-4 lines (depending on automatic updates) plus one line per plugin (but you have those lines in the plugin file otherwise).


I think rad-shell could benefit from using zgenom simply by migrating. On top of that it could also utilize the automatic updates from zgenom.

Merging the two doesn't make much sense since the scope is different. rad-shell provides an easy to use zsh environment by making some assumptions what the user would want. zgenom provides tools to clone and update git repos and source the plugin files

brandon-fryslie commented 1 year ago

Does it use its own code for that?

No, it sets the standard ZGEN_RESET_ON_CHANGE variable.

This is the entirety of what rad-shell does when you start a shell:

https://github.com/brandon-fryslie/rad-shell/blob/master/rad-init.zsh

The install process merely sets up some conventions and files. There's an env var that controls whether it will add the default list of plugins or not.

Zgenom doesn't make any assumptions what kind of plugins you like. There won't be any default plugins installed. That's also the reason why extensions exist.

Totally get that. That wasn't the functionality I was talking about. Really the only functionality I care about is:

The default list of plugins is just to help new/less experienced users get started by providing sensible defaults and is not actually part of rad-shell at all. I'm planning on removing the automatically loaded 'base' plugins (because more advanced zsh users don't want anything loaded by default), but they're required to load standard oh-my-zsh plugins and themes so it's a bit of a challenge I'll have to think about. It's a tradeoff between ease of use for newbies, and supporting advanced users who already know what they're doing.

While I like the idea of a plugin file I couldn't express my usage of zgenom in only a plugin file.

Cool, would you mind providing an example? Just for my own curiosity. I'd like to understand if there's some functionality I'm not taking advantage of. I can always source an additional file in the

source "${HOME}/.zgen/zgen.zsh"
# if the init scipt doesn't exist
if ! zgen saved; then
...

block.

I'd also love to see an example of your configuration, if that would be possible. I want to keep this project as simple as possible without limiting any of the underlying functionality of zgenom.

I'm surprised I can't find anything else like this project, everything either requires 5 manual steps to install and cluttering your .zshrc with a bunch of logic mixed with a list of plugins, or a ridiculous amount of complexity like https://github.com/unixorn/zsh-quickstart-kit where you cant' even edit your own .zshrc file any more.

jandamm commented 1 year ago

No, it sets the standard ZGEN_RESET_ON_CHANGE variable.

When I find the time I'll improve the performance and make this a function like zgenom reset-on-change file.zsh

I'd also love to see an example of your configuration

Here you go: https://github.com/jandamm/dotfiles/blob/main/zsh/.config/zsh/init.zsh

Would you mind providing an example?


# Install z.lua: First clone then create a plugin from cloned dir
zgenom clone skywind3000/z.lua
zgenom eval "$(lua $(zgenom api clone_dir skywind3000/z.lua)/z.lua --init zsh enhanced)"

Install git-extras: First clone and install completions, then run make and move the created bins into $PATH

zgenom load tj/git-extras etc/git-extras-completion.zsh zgenom run tj/git-extras PREFIX=$ZPFX/git-extras make zgenom bin $ZPFX/git-extras/bin --glob '^git-pr'


As you can see this isn't possible when you don't have access to the `if ! zgenom saved`-block and can just write plugins in `.rad-plugins `. Only when modifying `rad-init.zsh` which would require forking.

> I'm surprised I can't find anything else like this project

I think most don't give a * and just use `ohmyzsh`. With the newer machines and not checking for updates on every new shell it's not that slow anymore.
`ohymzsh` has 161k stars while the most popular zsh plugin manager (`antigen`) has 7.6k stars. I had colleagues who used `ohmyzsh` and `zsh` interchangeably.
brandon-fryslie commented 1 year ago

Definitely appreciate the example! I definitely don't want to limit functionality, only reduce unnecessary complexity.

I think most don't give a * and just use ohmyzsh

Yes of course most people don't give a **** hahahaha. I've never found that a particularly good reason to make design decisions.

I get slightly annoyed when opening a new shell isn't pretty much instant, and find eliminating unnecessary complexity is valuable in itself. That's enough motivation for me.

The reason for the separate plugin file is to enable searching/adding/removing plugins from a native zsh menu without needing to manually edit files. That isn't fully implemented at the moment but just dumping everything right into your .zshrc makes that effectively impossible. Think of it like a requirements.txt file vs putting a bunch of package installation code at the top of your python application.

I absolutely appreciate you sharing your configuration and spending the time to explain your reasoning to me. Being able to look at your dotfiles is an invaluable resource which I'm sure will teach me a lot. Thanks so much for creating/maintaining zgenom as well. I'm looking forward to taking advantage of the new features to improve my workflow even more. I'll leave this issue open until I've fully switched over to zgenom. Take care

brandon-fryslie commented 1 year ago

@jandamm Could I ask a quick question? If you don't know the answer off the top of your head, no worries at all and I can look into it more when I have time.

I have an open PR against zgen here: https://github.com/tarjoilija/zgen/pull/87 For the issue here: https://github.com/tarjoilija/zgen/issues/74 Looks like I tried a few things before coming to a resolution: https://github.com/tarjoilija/zgen/issues/74#issuecomment-270260490

I took a look at zgenom and it looks like you rewrote that logic. Do you think this is likely fixed in zgenom or could it still be a problem? I don't have time right now to try to reproduce it, but if you know that this is no longer an issue then that would simplify things and I won't worry about it.

If it's still issue an I'd be happy to open a PR some time in the future if you think the solution I have in the other PR would be acceptable.

Thanks again for your time and effort

jandamm commented 1 year ago

I did merge most recent PRs when I started with zgenom but it seems I didn't merge this PR (probably because it was already old at that time) - but it looks like an oversight to not fix it.

But it might be fixed since zgenom adds to fpath before sourcing:

So I have hopes it's already fixed. Please create bug if you find this issue to still be present.