romkatv / zsh4humans

A turnkey configuration for Zsh
MIT License
1.81k stars 116 forks source link

Feedback #35

Closed maximbaz closed 2 years ago

maximbaz commented 4 years ago

Hey @romkatv! I'm giving z4h/v3 a spin, and would like to share some ideas and ask some questions at the same time πŸ™‚

  1. Tab completion: traversing hidden folders

You mentioned it is possible to add an option to traverse hidden folders as well when glob_dots is set, could you please add it or give me a hint how to do this locally?

Turns out I edit files in hidden folders too often, it would be helpful if fzf included everything.

  1. Tab completion: ignoring some patterns

The standard completion system respects ignored-patterns.

This was a great hint, just as one idea it allows to ignore .zwc files, for example with zstyle ':completion:*:*:kak:*:*' ignored-patterns '*.zwc' opening .p10k.zsh in editor is simpler, as kak .p<Tab> now has only one match instead of two, so fzf doesn't show up at all and I go straight to .p10k.zsh.

Currently recursive directory listing doesn't respect it but it's on my TODO list to fix this.

Would be awesome! Could you please suggest what would be a proper zstyle syntax that you want to support for ignoring folders for cd? Say for example I wanted to ignore ~/.cache/ and ~/.docker/ and everything underneath them.

  1. Tab completion: do not require space to search different dirs

Suppose I just cloned zsh4humans, I press <Alt-Down> and I want to navigate to zsh4humans/fn. Typing z fn will find it, but typing zfn will not. I am used to just typing in fzf without having to think where I should put spaces... Could we at least have an option, if the current behavior is something you prefer?

By the way, while <Alt-Down> shows

zsh4humans
zsh4humans/fn

But cd <Tab> shows

zsh4humans
./zsh4humans/fn

Both work, but the latter is less aesthetic :)

  1. Tab completion: fzf-tab continuous-trigger

Am I right that it will become unnecessary when everything will be traversed? If so, this could be cleaned up I presume:

https://github.com/romkatv/zsh4humans/blob/6af0bfc8727b5e5ed72643ce5c457e9cbc513afb/.zshrc#L56-L58

  1. Tab completion: multiple selection doesn't seem to work

Or I'm doing something wrong :) What I expected to work is to type $ cp .zsh<Tab> and press Ctrl+Space to select more than one entry

  1. Tab completion: add grouping and multiple coloring

Have you considered adding groups and using different colors to fzf completion? I have some half-broken leftovers from prezto, but they will suffice to show a difference:

zstyle ':completion:*:*:*:*:*' menu select
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:options' description 'yes'
zstyle ':completion:*:options' auto-description '%d'
zstyle ':completion:*:corrections' format ' %F{green}-- %d (errors: %e) --%f'
zstyle ':completion:*:descriptions' format ' %F{yellow}-- %d --%f'
zstyle ':completion:*:messages' format ' %F{purple} -- %d --%f'
zstyle ':completion:*:warnings' format ' %F{red}-- no matches found --%f'
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' format ' %F{yellow}-- %d --%f'
zstyle ':completion:*' group-name ''
zstyle ':completion:*' verbose yes

Current style:

image

With grouping and coloring:

image

I don't care about group names too much, we could just hide them, but I do think coloring different types of autocomplete is useful and nice.

  1. "Additional Zsh startup files" in README

I would suggest to rephrase this a little, let me give you an example when editing those files makes sense: it is a nice and easy way to start GUI. Here's how I do it:

Let me know if this makes sense. Right now I simply put all my variables on top of .zshenv generated by z4h, but I'm wondering if the README needs to be adjusted to relax the bold phrase a bit, maybe just say that everything that z4h generates must be preserved without modifications?

  1. Avoid exporting XDG_CACHE_HOME

I would suggest to drop this line:

https://github.com/romkatv/zsh4humans/blob/6af0bfc8727b5e5ed72643ce5c457e9cbc513afb/.zshenv#L11

I believe every software knows how to fallback to $HOME/.cache in the absence of that variable, and it should be a very conscious user decision to export all those XDG_* variables, let's not do it for them.

  1. Add TIMEFMT='user=%U system=%S cpu=%P total=%*E' to z4h

First saw it in your dotfiles, and instantly fell in love. I believe it's exactly one of those things that makes zsh for humans and should be done for everyone πŸ™‚

  1. Terminal title to contain timestamp

Because transient prompt (often) removes the timestamp of when a command was started, you once recommended me to add the time to the terminal title instead, to be able to see how long the command is already running. I still think it was a great idea, might be worth adding directly to z4h? Time is only needed for when a command is running (not when title shows current dir), and maybe only when transient prompt is enabled (but I'd probably just show the time always when command is running). What do you think?

  1. Support moooooore LS_COLORS

Have you seen this project? https://github.com/trapd00r/LS_COLORS

I think it would be very cool to tap into their work and have an integration with it, just like you do with zsh-syntax-highlight and others. Currently I can source their file and it will affect my ls, but I don't think tab completion respects this variable, maybe because colors are set immediately after a built-in LS_COLORS is defined?

https://github.com/romkatv/zsh4humans/blob/6af0bfc8727b5e5ed72643ce5c457e9cbc513afb/fn/-z4h-init#L392

  1. Various small ideas

I have had a few small snippets taken from here and there that I use quite frequently, want to show them and see if you would want to take anything directly in z4h:

typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off
p10k-on-pre-prompt()  { p10k display '1'=show }
p10k-on-post-prompt() { p10k display '1'=hide }
my-pound-toggle() {
    if [[ "$BUFFER" = '#'* ]]; then
        if [[ $CURSOR != $#BUFFER ]]; then
            (( CURSOR -= 1 ))
        fi
        BUFFER="${BUFFER:1}"
    else
        BUFFER="#$BUFFER"
        (( CURSOR += 1 ))
    fi
}
zle -N my-pound-toggle
autoload -Uz edit-command-line
zle -N edit-command-line
my-ctrl-z() {
    if [[ $#BUFFER -eq 0 ]]; then
        BUFFER="fg"
        zle accept-line -w
    else
        zle push-input -w
        zle clear-screen -w
    fi
}
zle -N my-ctrl-z

That's enough for now πŸ˜„

UPDATE: OK, one more 😁 Have you considered to add these options to the list of default options in z4h?

romkatv commented 4 years ago

Can you debug this a little bit? What's the simplest command that produces the error? How can you change the command to get rid of the error? Does replacing /bin/cat with cat do the trick? What's the output of echo $SHELL; $SHELL --version on the router?

romkatv commented 4 years ago

Never mind. I've found http://demo2.mt.lv/webfig/#Terminal.

The login shell on RouterOS isn't a shell at all. The fallback in z4h still requires a shell on the remote host, it just won't attempt to teleport z4h environment to it if it cannot be done (e.g., missing necessary POSIX tools, unsupported architecture, etc.).

You'll need to use zstyle ':z4h:ssh:router' passthrough yes, at least for now.

romkatv commented 4 years ago

The original zsh-syntax-highlighting highlights foobar in green on the last line. My fork highlights it in red. I'll find a way to fix this.

This is fixed.

cyrinux commented 4 years ago

Never mind. I've found http://demo2.mt.lv/webfig/#Terminal.

The login shell on RouterOS isn't a shell at all. The fallback in z4h still requires a shell on the remote host, it just won't attempt to teleport z4h environment to it if it cannot be done (e.g., missing necessary POSIX tools, unsupported architecture, etc.).

You'll need to use zstyle ':z4h:ssh:router' passthrough yes, at least for now.

You find quickly ;) Ok we will reput passthrough yes so ;) Thanks πŸ‘πŸ»

maximbaz commented 4 years ago

I keep stumbling upon this annoyance so I thought it would be interesting to bring it up and hear your thoughts:

In a new dir create some files: touch changelog-{1.0.0,1.1.0,1.2.0}.txt

Say I want to open changelog-1.0.0.txt, in my head the thought process is going like this:

  1. Type vim ch<Tab> to see if I am right and there are indeed changelogs in this folder
  2. I get a visual confirmation that yes, changelog files are here, so I continue typing the version 100<Enter>.

In my head this is logical, because I know I typed ch and I know that 100 will only resolve to one of them, so this should have opened the file.

What happens instead is that after typing vim ch<Tab> fzf is already prefilled with common prefix changelog-1., but I dont realize it because I'm not looking at fzf prompt, and so adding 100 to that prefix will result in no match!

image

I propose therefore that after vim ch<Tab> in fzf prompt we only get ch typed, not the full common prefix.

romkatv commented 4 years ago

Yep, this is currently broken and I need to fix it.

The fix you propose will work well in some cases but might be confusing in others. Consider:

mkdir -p /tmp/foo/{bar,baz}/q
ls /tmp/foo/b/qux<TAB>

image

What should be prefilled in the fzf query?

I think empty is the best choice here. ba is bad for the reasons you've mentioned, but so is b. Neither matches what the user is typing currently (the cursor is after /q). If we go with empty here, does consistency and predictability warrant empty query in all cases? Or maybe the simple case (the one from your comment) deserves special casing? I don't know.

I also have a TODO to add an option that specifies what happens when all completion candidates share a prefix. Currently fzf opens. I want to allow at least one more behavior:

In your example the first Tab would insert changelog-1. into the command line. In my example the first Tab would insert ba. The second Tab would open fzf in both examples.

Perhaps in this mode the problem we are discussing becomes less pressing? It also might make fzf more palatable to folks who currently don't like it. I'm still trying to figure out why some people don't like fzf completions and I think the fact that it opens fzf on the first press of Tab has something to do with it.

To summarize: I also don't like the current behavior and want it changed. However, I haven't thought very hard about what it should be changed to, so it's currently on the backburner.

maximbaz commented 4 years ago

Thank you for the interesting answer.

I think empty is the best choice here. ba is bad for the reasons you've mentioned, but so is b.

Agree that empty sounds best.

If we go with empty here, does consistency and predictability warrant empty query in all cases? Or maybe the simple case (the one from your comment) deserves special casing? I don't know.

Unless I'm missing something, I think in my example having fzf pre-filled with ch and having it empty would result in exactly the same pattern and search, because the candidates are already pre-filtered with ch prefix, so putting ch filter in fzf would be a noop anyway. If so, I would go for consistency and leave fzf filter empty.

I also have a TODO to add an option that specifies what happens when all completion candidates share a prefix. Currently fzf opens. I want to allow at least one more behavior:

The prefix is inserted automatically. A second Tab is necessary to open fzf.

Right, I remember this, I initially was in favor of this alternative behavior, but I now realize that was mainly because I didnt know about <Alt+Enter>, now I actually appreciate the current behavior and wouldn't turn it off. Not saying that you shouldn't implement the alternative approach, just sharing feedback on why folks might not like fzf and the fact that maybe <Alt+Enter> should be better advertised :)

romkatv commented 4 years ago

Unless I'm missing something, I think in my example having fzf pre-filled with ch and having it empty would result in exactly the same pattern and search

Not exactly the same but fairly close. It's easier to see with --exact although in fuzzy search mode it should also be visible. If ch is pre-filled and you type a, you'll get all entries that contain cha. However, with an empty initial query you'll get everything containing a -- a superset of the above.

I also have a TODO to add an option that specifies what happens when all completion candidates share a prefix. Currently fzf opens. I want to allow at least one more behavior: The prefix is inserted automatically. A second Tab is necessary to open fzf.

Right, I remember this, I initially was in favor of this alternative behavior, but I now realize that was mainly because I didnt know about <Alt+Enter>, now I actually appreciate the current behavior and wouldn't turn it off. Not saying that you shouldn't implement the alternative approach, just sharing feedback on why folks might not like fzf and the fact that maybe <Alt+Enter> should be better advertised :)

I want the defaults to work without my having to educate users. There should also be options yielding higher productivity for users who can change their configs and habits (the vast majority of zsh users cannot do either). Right now using completions essentially requires knowing about Alt+Enter. This is bad.

My current plan is as follows:

  1. Add options that would make completion system behave in a way that's more aligned with how most bash, fish and zsh users expect it to behave.
  2. Enable these options for myself and live with them for some time.
  3. Figure out which knobs should exist for controlling completions and expose them through the default .zshrc.
  4. Write a wizard that would walk users through the common options, explain what they do and allow them to choose what they want.

I won't release v3 until 1-3 from the above list are done. This might take quite some time because my schedule for the foreseeable future doesn't have any free time that I can dedicate to z4h development.

klooj commented 4 years ago

Hey fellas, I've followed this conversation from where it started in the fzf-tab repo issues. I am leagues behind you in terms of zsh knowledge, but today I discovered a shell parameter in the zsh8-guide called "fignore".

image

I do not know where file name generation ends and completion begins in the hand off to fzf, but this seems beneficial for suppressing (i.e.) .zwc files while allowing for an easy override.

romkatv commented 4 years ago

fignore is from the compctl days. It’s no longer relevant now that we have ignored-patterns style.

romkatv commented 4 years ago

Folks, there is a large update to zsh4humans. You might recall that I wanted to change the way completions work and then release (and essentially freeze) v3. When I got around to it, I realized that it can be inconvenient for the existing v3 users because my update would break them. Even though v3 is "beta" and has no compatibility guarantees, it's been stable for a long time in practice, so it wouldn't be nice to introduce backward-incompatible changes now. So I've created a v4, which I'm planning to release as soon as I fix all newly introduces bugs. I encourage you to upgrade from v3 to v4, try it out and complain about anything that's not 100% awesome.

There are two ways for you to migrate. You can either install v4 from scratch and then modify ~/.zshrc and ~/.zshenv, or replace v3 with v4 in the existing ~/.zshenv and run exec zsh. The latter is easier. You'll still need to make a few changes where backward compatibility broke.

Here are the changes

z4h-expand-or-complete is now called z4h-fzf-complete. If you have a manual binding for the former, you'll need to update it.


z4h chsh command is gone. There is something similar and automatic in its place. If you are invoking z4h chsh from ~/.zshrc, simply remove that call.


The installer now comes with a tiny wizard similar in spirit to p10k configure.


Completions no longer use fzf-tab. Instead, there is a brand new implementation that's very different. It should work very much like the standard zsh completion (as configured in Oh My Zsh or Prezto, for example) except that it uses fzf instead of the menu.


zstyle :fzf-tab: continuous-trigger is no longer recognized because z4h doesn't use fzf-tab anymore. Instead, you can define bindings within fzf like this:

zstyle ':z4h:fzf-complete' fzf-bindings 'tab:repeat' 'ctrl-a:toggle-all'

Possible key:action pairs can be found in man fzf. Action repeat is an extra addition by z4h -- this is the "continuous trigger". You can use context :z4h:fzf-history to define bindings for Ctrl+R, a.k.a. z4h-fzf-history.


You can define extra fzf flags or override the default flags like this:

zstyle ':z4h:fzf-complete' fzf-flags --no-exact
zstyle ':z4h:fzf-history' fzf-flags --no-preview

Flags can be found in man fzf.


You can override the top-level fzf command:

zstyle ':z4h:fzf-history' fzf-command my-fzf

function my-fzf() { fzf "${@}" }

You can do this if you want to transform fzf arguments in a non-trivial way. For example, remove the anchor from --query. Parsing should be easy because all flags are guaranteed to be in the form --name=value. However, before resorting to this nuclear option, please let me know what you want to customize that cannot be done with fzf-flags and fzf-bindings.


cd-key zstyle is gone. You now have to define bindings manually:

z4h bindkey z4h-cd-back    Alt+Left   # cd into the previous directory
z4h bindkey z4h-cd-forward Alt+Right  # cd into the next directory
z4h bindkey z4h-cd-up      Alt+Up     # cd into the parent directory
z4h bindkey z4h-cd-down    Alt+Down   # cd into a child directory

z4h bindkey can now be configured to be mac-like.

# Keyboard type: 'mac' or 'pc'.
zstyle ':z4h:bindkey' keyboard 'mac'

With this setting Delete in z4h bindkey ... Delete means ^? while Fn+Delete is what a PC user would call Delete. You can also use Option instead of Alt.


z4h will refuse to perform some actions if you are root but $HOME doesn't belong to root. This is meant to avoid creating root-owned files in a regular user's home directory that cannot be deleted by the user. The list of restricted actions includes z4h update and z4h ssh.


I might have forgotten about some changes. If you bump into something else, please post a note here.

maximbaz commented 4 years ago

Thanks @romkatv, great stuff!

I have upgraded, on the first glance everything looks good, I will let you know if I stumble upon something weird.

I'm very happy to see fzf improvements, such as anchored prefix and Ctrl+Space going down πŸ‘

Personally, of the things that were mentioned in this thread, the biggest problems for me are all related to completions:

I'm keeping a patch that implements two and a half of these features (which I will rebase on v4 branch now), but I hope these could become part of z4h itself at some point 🀞

As a final note, can we choose a different color instead of this very bright pink? πŸ˜„

image


UPDATE:

Discovered that these are not working in cd-down, only if I cd <Tab>:

zstyle ':z4h:fzf-complete' fzf-flags --no-exact
zstyle ':z4h:fzf-complete' fzf-bindings 'tab:repeat' 'ctrl-a:toggle-all'
romkatv commented 4 years ago

I'm very happy to see fzf improvements, such as anchored prefix [...]

The biggest change (and most important IMO) is not that the prefix is anchored but that the query in fzf always mirrors what you have on the command line. Here's an example:

mkdir -p /tmp/foo{1,2}/bar
ls /tmp/f/bar<TAB>

Here's what happens when you hit Tab.

  1. Cursor moves after /tmp/f and oo gets inserted. The cursor stays after foo.
  2. If auto_menu is unset, nothing else happens; you need to hit another Tab to go to the next step. With auto_menu you go there automatically.
  3. fzf opens with two items: foo1 and foo2. The query is set to ^foo.

Personally, of the things that were mentioned in this thread, the biggest problems for me are all related to completions:

  • ~disabling --exact fzf match~ realized this is now possible via zstyle ':z4h:fzf-complete', thanks!

Yep, I remember this. This is the reason I chose this example to demonstrate how you can override fzf flags:

zstyle ':z4h:(fzf-complete|fzf-history|cd-down)' fzf-flags --no-exact
  • recursing into hidden dirs
  • ability to specify which dirs to not recurse

These are still pending. Sorry.

As a final note, can we choose a different color instead of this very bright pink?

I'm glad you noticed it :P

I chose this color to make sure highlighting of search terms is visible with all sensible terminal color themes. The default green was invisible on executable files with some themes. You can change it like this:

zstyle ':z4h:(fzf-complete|fzf-history|cd-down)' fzf-flags --color=hl:201,hl+:201

See man fzf for syntax.

Discovered that these are not working in cd-down, only if I cd <Tab>:

You are too fast! I just committed a fix for this.

zstyle ':z4h:fzf-complete' fzf-bindings 'tab:repeat' 'ctrl-a:toggle-all'

Note: ctrl-a:toggle-all is the default. No need to rebind it.

maximbaz commented 4 years ago

Awesome stuff πŸ‘

I have an issue with z4h update, I know @cyrinux has it too and it started to happen at least a few days ago (so even on v3), I tried to do some initial investigation, could you give me a hint how to gather more useful data? I tried to add set -x to -z4h-cmd-update, it will be below.

Steps to reproduce:

$ rm -rf -- ~/.cache/zsh4humans
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/romkatv/zsh4humans/v4/install)"
---- Press `q`
$ exec zsh
$ z4h update
z4h: fetching z4h.zsh
curl: (22) The requested URL returned error: 403 Forbidden

z4h: update failed

See error messages above to identify the culprit.

z4h update with set -x set is below, but I don't see curl invocation, so it must be hidden somewhere else...?

$ z4h update
+-z4h-cmd-update:2> eval $'emulate -L zsh &&\n  setopt typeset_silent pipe_fail extended_glob prompt_percent no_prompt_subst &&\n  setopt no_prompt_bang no_bg_nice no_aliases'
+(eval):1> emulate -L zsh
+(eval):2> setopt typeset_silent pipe_fail extended_glob prompt_percent no_prompt_subst
+(eval):3> setopt no_prompt_bang no_bg_nice no_aliases
+-z4h-cmd-update:3> -z4h-check-core-params
+-z4h-check-core-params:1> [[ $'ZDOTDIR=/home/maximbaz\C-@Z4H=/home/maximbaz/.cache/zsh4humans\C-@Z4H_URL=https://raw.githubusercontent.com/romkatv/zsh4humans/v4' == ZDOTDIR=/home/maximbazZ4H=/home/maximbaz/.cache/zsh4humansZ4H_URL=https://raw.githubusercontent.com/romkatv/zsh4humans/v4 ]]
+-z4h-cmd-update:5> ((  ARGC  ))
+-z4h-cmd-update:10> ((  _z4h_dangerous_root  ))
+-z4h-cmd-update:15> local old=/home/maximbaz/.cache/zsh4humans.old.1867571
+-z4h-cmd-update:16> local new=/home/maximbaz/.cache/zsh4humans.new.1867571
+-z4h-cmd-update:19> zf_rm -rf -- /home/maximbaz/.cache/zsh4humans.old.1867571 /home/maximbaz/.cache/zsh4humans.new.1867571
+-z4h-cmd-update:20> zf_mkdir -p -- /home/maximbaz/.cache/zsh4humans.new.1867571
+-z4h-cmd-update:21> print -n
+-z4h-cmd-update:23> Z4H=/home/maximbaz/.cache/zsh4humans.new.1867571 Z4H_UPDATING=/home/maximbaz/.cache/zsh4humans.new.1867571 /usr/bin/zsh -ic $'\n    (( $? )) && "exit" "1"\n    "builtin" "emulate" "zsh" "-o" "no_aliases"\n    [[ $Z4H == /home/maximbaz/.cache/zsh4humans.new.1867571 ]] || exit 0\n    print -n >$Z4H/tmp/update-successful'
z4h: fetching z4h.zsh
curl: (22) The requested URL returned error: 403 Forbidden
+-z4h-cmd-update:27> return
+-z4h-cmd-update:52> ((  1  ))
+-z4h-cmd-update:53> -z4h-error-command update
+-z4h-error-command:1> local home=/home/maximbaz
+-z4h-error-command:2> local zdotdir='~'
+-z4h-error-command:3> local z4h='~/.cache/zsh4humans'
+-z4h-error-command:4> print -Pru2 -- ''

+-z4h-error-command:5> print -Pru2 -- '%F{3}z4h%f: %Bupdate%b %F{1}failed%f'
z4h: update failed
+-z4h-error-command:6> print -Pru2 -- ''

+-z4h-error-command:7> print -Pru2 -- 'See error messages above to identify the culprit.'
See error messages above to identify the culprit.
+-z4h-error-command:8> print -Pru2 -- ''

+-z4h-error-command:9> print -Pru2 -- 'Edit Zsh configuration:'
Edit Zsh configuration:
+-z4h-error-command:10> print -Pru2 -- ''

+-z4h-error-command:11> print -Pru2 -- '  %F{2}kak%f %U~/.zshrc%u'
  kak ~/.zshrc
+-z4h-error-command:12> [[ update != update ]]
+-z4h-error-command:18> print -Pru2 -- ''

+-z4h-error-command:19> print -Pru2 -- 'If nothing helps and you are about to give up:'
If nothing helps and you are about to give up:
+-z4h-error-command:20> print -Pru2 -- ''

+-z4h-error-command:21> print -Pru2 -- '  %F{5}# nuke the entire site from orbit'
  # nuke the entire site from orbit
+-z4h-error-command:22> print -Pru2 -- '  %F{2}%Usudo%u rm%f -rf -- %U~/.cache/zsh4humans%u'
  sudo rm -rf -- ~/.cache/zsh4humans
+-z4h-error-command:23> ((  1  ))
+-z4h-error-command:24> print -Pru2 -- ''

+-z4h-error-command:25> print -Pru2 -- 'Give up and start over:'
Give up and start over:
+-z4h-error-command:26> print -Pru2 -- ''

+-z4h-error-command:27> print -Pru2 -- '  %F{2}sh%f -c %F{3}"%f$(%F{2}curl%f -fsSL %Uhttps://raw.githubusercontent.com/romkatv/zsh4humans/v4/install%u)%F{3}"%f'
  sh -c "$(curl -fsSL https://raw.githubusercontent.com/romkatv/zsh4humans/v4/install)"
+-z4h-error-command:28> print -Pru2 -- ''

+-z4h-cmd-update:55> zf_rm -rf -- /home/maximbaz/.cache/zsh4humans.old.1867571 /home/maximbaz/.cache/zsh4humans.new.1867571
romkatv commented 4 years ago

z4h: fetching z4h.zsh curl: (22) The requested URL returned error: 403 Forbidden

This is done by your ~/.zshenv. Take a look at it. It looks like you've earned a ban from github. Can you try it from a different IP to see if helps?

Do you have any visibility into GitHub division? Can you figure out why you are getting the 403 treatment?

romkatv commented 4 years ago

To clarify, you should be able to reproduce the 403 with this command:

curl -fsSL -- https://raw.githubusercontent.com/romkatv/zsh4humans/v4/z4h.zsh

This command is executed by your ~/.zshenv.

maximbaz commented 4 years ago

Mystery solved, thanks @romkatv πŸ‘ It was caused.... by a combination of me having alias curl=curlie and using .zwc file πŸ€•

I cannot explain this, because curlie -fsSL -- https://raw.githubusercontent.com/romkatv/zsh4humans/v4/z4h.zsh works perfectly well, but observe:

$ which curl
curl: aliased to curlie

$ z4h update
z4h: fetching z4h.zsh
curl: (22) The requested URL returned error: 403 Forbidden

z4h: update failed

See error messages above to identify the culprit.

Edit Zsh configuration:

  kak ~/.zshrc

If nothing helps and you are about to give up:

  # nuke the entire site from orbit
  sudo rm -rf -- ~/.cache/zsh4humans/v4

Give up and start over:

  sh -c "$(curl -fsSL https://raw.githubusercontent.com/romkatv/zsh4humans/v4/install)"

$ rm -rf .zshenv.zwc

$ z4h update
z4h: fetching z4h.zsh
z4h: updating zsh4humans
z4h: updating romkatv/archive
z4h: updating zsh-autosuggestions
z4h: updating zsh-completions
z4h: updating zsh-syntax-highlighting
z4h: updating fzf
z4h: updating fzf binary
z4h: updating powerlevel10k
z4h: updating gitstatus binary
z4h: initializing zsh
z4h: update successful
z4h: restarting zsh

In any case, to not have to bother with such edge-cases, perhaps consider doing this:

--- a/.zshenv
+++ b/.zshenv
@@ -19,9 +19,9 @@ if [ ! -e "$Z4H"/z4h.zsh ]; then
     mkdir -p -- "$Z4H" || return
     printf >&2 '\033[33mz4h\033[0m: fetching \033[4mz4h.zsh\033[0m\n'
     if command -v curl > /dev/null 2>&1; then
-        curl -fsSL -- "$Z4H_URL"/z4h.zsh > "$Z4H"/z4h.zsh.$$ || return
+        command curl -fsSL -- "$Z4H_URL"/z4h.zsh > "$Z4H"/z4h.zsh.$$ || return
     elif command -v wget > /dev/null 2>&1; then
-        wget -O- -- "$Z4H_URL"/z4h.zsh > "$Z4H"/z4h.zsh.$$ || return
+        command wget -O- -- "$Z4H_URL"/z4h.zsh > "$Z4H"/z4h.zsh.$$ || return
     else
         printf >&2 '\033[33mz4h\033[0m: please install \033[32mcurl\033[0m or \033[32mwget\033[0m\n'
         return 1
romkatv commented 4 years ago

zwc files are tricky. The most common failure mode is when you mv the original source. mv preserves mtime, so you can easily end up with a zwc looking "newer" than the source when logically it should be the other way around. I highly recommend removing all zwc files that you might have and not using z4h source -c or z4h compile anywhere. zsh4humans internally compiles files but it does it in a safe way that's very difficult to achieve by normal means.

As far as the alias goes and the suggestion to replace curl with command curl in ~/.zshenv, I'm not sure this is the right diagnosis. Do you really define that alias before ~/.zshenv is sourced? In which file do you do that?

maximbaz commented 4 years ago

In the end of .zshrc, but I thought maybe that alias is being propagated to z4h update call because I execute that command already in my initialized shell πŸ€”

I removed compilation of files, and as you say the bug is not reproducing anymore, not sure if we should spend more time on it, unless you are just curious πŸ˜‰

romkatv commented 4 years ago

In the end of .zshrc, but I thought maybe that alias is being propagated to z4h update call because I execute that command already in my initialized shell πŸ€”

The alias is a red herring then. When you do z4h update it essentially does Z4H=$Z4H.tmp zsh -ic '' and then replaces $Z4H with $Z4H.tmp if zsh succeeds in its initialization. You can try this yourself to see how it works:

Z4H=/tmp/z4h zsh -ic ''

There are no shenanigans with manual sourcing of rc files. Update goes through the same (well, almost) sequence as the initial bootstrap.

I removed compilation of files, and as you say the bug is not reproducing anymore, not sure if we should spend more time on it, unless you are just curious πŸ˜‰

This is quite mysterious. My only guess is that you did in fact get a temporary ban by GitHub but it got lifted. The timing might have been a coincidence although it's suspicious.

Anyway, I'm glad it's resolved. If it happens again, please debug deeper. It's not worth your time doing it now.

romkatv commented 4 years ago

I know @cyrinux has it too and it started to happen at least a few days ago

Maybe this will give us some clue? Do you share a public IP? Has the problem been resolved for both of you? Did it coincide with file changes on both accounts?

maximbaz commented 4 years ago

We are in different countries, but use very similar dotfiles (so both have alias curl=curlie), do not share a public IP, and yes, the problem was fixed for both of us, originally was fixed by removing the alias, removing .zshenv.zwc and letting it be recreated; but now that we removed compilation from our .zshrc altogether, this is not an issue anymore. I agree that it's quite mysterious πŸ€·β€β™‚οΈ

maximbaz commented 4 years ago

I've realized that anchored match in fzf actually forces exact match, so even though I have --no-exact, in some cases I will lose fuzzy match. I understand that if I remove ^ from the query I might get some wrong candidates in fzf, but I will try to use it like this anyway, as already after a couple of hours of usage I stumbled upon the case where having ^ in fzf query prevented me from completing a file which my muscle memory expected to match...

romkatv commented 4 years ago

I've realized that anchored match in fzf actually forces exact match [...]

Indeed, but only for that one term. Other terms (separated with a space from the first) are matched fuzzily if you have fuzzy matching enabled.

I understand that if I remove ^ from the query [...]

You can do it like this:

zstyle ':z4h:fzf-complete' fzf-command my-fzf

function my-fzf() {
  emulate -L zsh
  # Replace all arguments that start with "--query=^" with "--query=".
  fzf "${@/#--query=^/--query=}"
}

[...] I might get some wrong candidates in fzf, but I will try to use it like this anyway, as already after a couple of hours of usage I stumbled upon the case where having ^ in fzf query prevented me from completing a file which my muscle memory expected to match...

Or you can hit space to separate your fuzzy term from the prefix.

FWIW, it took me some time to change the muscle memory when I switched from fuzzy matching by default to exact by default but it was absolutely worth it. The cost of typing extra spaces between terms is well worth the gain in much better and more predictable matching. Note that you can still get fuzzy matching with 'term (that's a single quote followed by a term) when you have exact match enabled by default, although I almost never use it nowadays.

maximbaz commented 4 years ago

Indeed, but only for that one term. Other terms (separated with a space from the first) are matched fuzzily if you have fuzzy matching enabled. ... Or you can hit space to separate your fuzzy term from the prefix.

Good to know! So if I want to always use fuzzy match, I can actually benefit from having an anchored prefix search if I always append a space to the query, like so (simpler syntax wanted):

my-fzf() {
    emulate -L zsh

    args=("$@")
    for ((i = 0; i < $#args; i++)); do
        [[ "${args[$i]}" == "--query="* ]] && args[i]+=' '
    done

    fzf "${args[@]}"
}

FWIW, it took me some time to change the muscle memory when I switched from fuzzy matching by default to exact by default but it was absolutely worth it

Good point, I will give it a try...

romkatv commented 4 years ago
my-fzf() {
    emulate -L zsh

    args=("$@")
    for ((i = 0; i < $#args; i++)); do
        [[ "${args[$i]}" == "--query="* ]] && args[i]+=' '
    done

    fzf "${args[@]}"
}

The same thing with a few bug fixes:

function my-fzf () {
  emulate -L zsh -o extended_glob
  local MATCH MBEGIN MEND
  # Add a space after every non-empty --query.
  print -lr -- "${@:/(#m)--query=?*/$MATCH }"
}
romkatv commented 4 years ago
  • recursing into hidden dirs
  • ability to specify which dirs to not recurse

These are still pending. Sorry.

I've added a customization point for this.

zstyle :z4h:fzf-complete find-flags ...

The default value is -name '.*' -prune -print -o -print, which has the following meaning:

Your patch is equivalent to the following declaration:

zstyle :z4h:fzf-complete find-flags -name '.git' -prune -print -o -print

Here's a more advanced example:

zstyle -e :z4h:fzf-complete find-flags my-find-flags

function my-find-flags() {
  emulate -L zsh -o extended_glob
  local match mbegin mend
  reply=()

  # Ignore *.zwc files when completing `cat`.
  if [[ $curcontext == :complete:cat:* ]]; then
    reply+=(-name '*.zwc' -prune -o)
  fi

  # Never recurse ~/foo/bar.
  if [[ ~/foo/bar == (#b)$PWD/(*) ]]; then
    reply+=(-path ./${(b)match[1]} -prune -print -o)
  fi

  # Do recurse ~/.cache.
  if [[ ~/.cache == (#b)$PWD/(*) ]]; then
    reply+=(-path ./${(b)match[1]} -print -o)
  fi

  # Don't recurse dot directories. ~/.cache will still be recursed
  # because it's handled above and matching is done in order.
  reply+=(-name '.*' -prune -print -o)

  # Recurse everything else.
  reply+=(-print)
}

In the future I'll probably add something automatic to the effect of "ignore *.zwc files when completing cat".

romkatv commented 4 years ago

FYI: I've released v4. Announcement on r/zsh: https://www.reddit.com/r/zsh/comments/jfid44/ann_zsh_for_humans_v4_released/. There should be no breaking changes to v4 from now on. Once I decide to make a breaking change, I'll branch off into v5, which will be the last version (no more breaking changes from then on).

You might have noticed that the announcement is fairly low key. This is intentional. I believe z4h is already in a decent state and could be useful to a lot of folks if they discovered it. However, I don't want it to become accidentally popular (the way powerlevel10k has become) because it'll be difficult to create a backward-incompatible v5 in the future. I'd like to have another round at figuring out the perfect shell setup before committing to long-term never-breaking-your-shell support.

If you have friends/colleagues/family who are at least as half as reasonable as you are, please do recommend z4h to them. Feedback from intelligent users is what drives product-level progress. Avoid mass advertisement though.

maximbaz commented 4 years ago

Thanks for all the above!

Just found a small issue with ssh completion, could you please try if you can reproduce it on your end?

Add this to your ~/.ssh/config:

Host vm1-03.loc.dc3.example.com
Host vm1-04.loc.dc3.example.com
Host vm2-03.loc.dc4.example.com
Host vm2-01.loc.dc4.example.com

Then try ssh vm<Tab>, for me it looks like this:

image

romkatv commented 4 years ago

Just found a small issue with ssh completion, could you please try if you can reproduce it on your end?

Thanks for the report. Once again, you've done most of the work for me, so it was easy to fix. Done.

cyrinux commented 4 years ago

Hmm guys, a little weirdness, we loose tab completion for files completion on "c" but not "e".

$ which e
e: aliased to /usr/bin/kak

$ which c
c: aliased to bat -p

Any idea?

romkatv commented 4 years ago

What does "loose tab completion" mean? What do you do, what do you observe and what do you expect?

cyrinux commented 4 years ago

I press c ~/.ssh<TAB><TAB> and expect to got .ssh files list and i got nothing, nothing happen. If i cat ~/.ssh<TAB><TAB> or bat ~/.ssh<TAB><TAB> it's good but not bat -p ~/.ssh<TAB><TAB>.

"c" is declared like this here: https://github.com/maximbaz/dotfiles/blob/41f75a60843c37ff801c7325d813c0a7dc0665e8/.zsh-aliases#L9

romkatv commented 4 years ago

I cannot reproduce this with the stock z4h config with an extra alias c='bat -c'.

Do you get completions if you type bat -p ~/.ssh/<TAB> ?

romkatv commented 4 years ago

What's the output of print -r $_comps[bat]?

cyrinux commented 4 years ago

I cannot reproduce this with the stock z4h config with an extra alias c='bat -c'.

Do you get completions if you type bat -p ~/.ssh/<TAB> ?

Adding a new aliases alias bla="bat -p" works. bat -p ~/.ssh/<TAB> works too.

cyrinux commented 4 years ago

What's the output of print -r $_comps[bat]?

$ print -r $_comps[bat]
_bat
romkatv commented 4 years ago

Apparently that completion function is broken. Where does it come from? This will tell you:

autoload +X -Uz _bat && print -r -- $functions_source[_bat]
cyrinux commented 4 years ago
```shell
autoload +X -Uz _bat && print -r -- $functions_source[_bat]

Completion come from

/usr/share/zsh/site-functions/_bat

Ok i understood, so completion for -p is broken but not -c.

romkatv commented 4 years ago

So that file has a bug. You can look inside to try to find it. Then you can patch it, and perhaps send the patch upstream.

romkatv commented 4 years ago

To clarify, this isn't specific to zsh4humans. This is a local completion file on your machine and it has a bug. You can reproduce this problem by running zsh -f and typing the following:

fpath+=(/usr/share/zsh/site-functions)
autoload -Uz compinit && compinit
bat -p ~/.ssh/<TAB>
cyrinux commented 4 years ago

Thanks @romkatv using the last bat.zsh expanded from the git source work. So will just wait the next release and i manually fix while ;)

Syphdias commented 4 years ago

Hey @romkatv,

just upgraded to v4 and I have to say no_auto_menu feels great! And of course I have notes on some stuff and I also remembered some general stuff so I'll added it to the end :wink:

v4 Stuff

Various (non v4)

romkatv commented 4 years ago

I have to say no_auto_menu feels great!

I'm really glad to hear that!

  • While in fzf Ctrl-J seems to move the selection one entry down Ctrl-K does not move down (tested for history and completion, not cd menu) I guess I can manually bind it with zstyle ':z4h:(fzf-complete|fzf-history|cd-down)' fzf-bindings 'ctrl-k:up' but I think it's a bug.

Ctrl+K is a standard emacs binding for deleting everything to the right of the cursor (it's very useful btw, especially when editing commands retrieved from history). It works in bash and zsh by default. For this reason I've retained it in z4h, too. Ideally, I'd like all cursor movement and text editing commands in fzf to be identical to zle in z4h. This is, unfortunately, not possible but I'm trying to get as close as I can. Thus Ctrl+K deletes everything to the right of the cursor in fzf.

In other words, I think the default behavior of Ctrl+K in fzf is sensible. It's fine to rebind it in your own config. I expect bindings to be one of the most common thing people customize. There are really no right or wrong bindings (there is value in consistency though).

  • A comment in the .zshenv file states to only edit certain parts. It doesn't include the umask setting. Can I change it here or should I add it to my .zshrc?

Yes, you can change it in .zshenv. What do you want to change it to if you don't mind my asking? g-w,o-w? Why?

  • I think I lost some ability to complete if the file name does not start with the first letter. This is what v3 of ls /etc/ash<tab>: image

Indeed, I've disabled substring matching because it was giving me trouble in the new completion frontend. Sometimes "unambigous" completion would insert something that cannot be completed further. Another downside of substring matching is that it makes completions twice as slow when there is no match.

Perhaps I should revisit this. How important is this to you? What are some real-life examples where you rely on this feature?

  • If I understand this line correctly (zstyle ':z4h:ssh:some-host' passthrough 'yes') it is a blacklist for hosts right?

Correct. If you read it left to right without punctuation: z4h ssh some-host passthrough yes. Or as a full sentence: z4h ssh some-host should pass through [to plain ssh some-host].

I assume this would make turn it into whitelist?

zstyle ':z4h:ssh:*' passthrough 'yes'
zstyle ':z4h:ssh:(some-host1|some-other-host2)' passthrough 'no'

Correct.

Is this something you want? Can you provide some context why you want it?

The passthrough yes as "don't copy over z4h/zsh stuff" is a bit confusing to be. I assume this syntax to bypasses functions?

Good point, it looks confusing. What would be a better name for this style?

  • This is not something that z4hv4 introduced but it might be something it could change I guess. If I type cd ..<tab> I would like it to complete to cd ../. This can work with zstyle ':completion:*' special-dirs true but it changes more behaviors. For example now .. and also . are being suggested by complete which leads to stuff like cd /etc/./

Good idea. I've added this to the list of potential future improvements.

  • It would be nice if the auto update would lock or could be sent to the background. I usually say yes to the update and then open a new terminal to do the stuff I initially opened the termianl for. The second terminal asks again if I want to update – I answer no of course in the second terminal. It lead to some bugs when I accidentally updated in two terminal windows once. Maybe something that could be improved with a temporary lock file or some sort of "cool down".

Indeed, update safety is currently lacking if you have multiple shells running simultaneously (it's safe if you have just one shell). In addition to what you've described, you can run into trouble if you open two shells, run z4h update in other of them, and then use the other shell. Because of lazy autoloading, that other terminal will use a mix of functions from two versions of z4h which can have unpredictable consequences.

A proper fix is possible but requires a lot of work. The biggest problem is that flock always succeeds on WSL1, so a natural solution would not only fail to protect from concurrent updates on WSL1 but would exaggerate the problem there. The fix would also require changes in ~/.zshenv, so it can be done only in v5.

In the meantime I've changed the auto-update logic to make your use-case a bit less painful. If you open a terminal, agree to auto update and then open another tab while the update is running, you won't be asked to auto-update. You might run into issues I've described above (the second tab will use a random blend of two z4h versions) but in practice you'll rarely be affected by them.

Thanks for the feedback!

romkatv commented 4 years ago

@Aloxaf has shown me a new and super cool feature in fzf-tab: https://github.com/Aloxaf/fzf-tab/pull/130. This fixes the major downside of using fzf for completions and history -- namely, that fzf can push command line upwards when it opens. As you can see in the demo, fzf-tab can render fzf above the cursor.

One major downside of this is that it requires you to run zsh inside tmux. And not just any tmux but version 3.2 or above. This is bleeding edge.

Based on the same idea I've hacked something up. Here's the first proof of concept:

sudo docker run -e TERM -e COLORTERM -w /root -it --rm alpine sh -uec '
  apk add zsh tmux
  wget https://raw.githubusercontent.com/romkatv/zsh4humans/v5/.zshenv
  wget https://raw.githubusercontent.com/romkatv/zsh4humans/v5/.zshrc
  echo "POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)" >>~/.p10k-8color.zsh
  echo "POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=()"   >>~/.p10k-8color.zsh
  exec tmux -u new-session -- /bin/zsh'

When prompt appears, try completing ls --. If there is not enough room for fzf below the cursor, it'll open above. The line with the cursor never gets pushed around. This logic is used by z4h automatically when it sees that you are in tmux. Any version of tmux will do. In this case it's 3.1b but even older is fine.

If you are very brave, you can try it locally. Replace v4 with v5 in ~/.zshenv and run exec zsh. Then run tmux (any version). Within tmux you'll have this new completion goodness. Outside of tmux it should be just as before.


Here's another demo:

sudo docker run -e TERM -e COLORTERM -w /root -it --rm alpine sh -uec '
  apk add autoconf gcc make musl-dev automake libevent-dev ncurses-dev zsh bison git
  wget https://raw.githubusercontent.com/romkatv/zsh4humans/v5/.zshenv
  wget https://raw.githubusercontent.com/romkatv/zsh4humans/v5/.zshrc
  echo "POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir)" >>~/.p10k.zsh
  echo "POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=()"   >>~/.p10k.zsh
  git clone --depth=1 -b no-collapse https://github.com/romkatv/tmux.git
  cd tmux
  sh ./autogen.sh
  ./configure --prefix ~/tmux-screen --exec-prefix ~/tmux-screen
  make install
  exec zsh'

Here completions work the same way -- fzf can open above the cursor.

Unlike the first demo, which starts tmux, this one starts plain zsh. However, there is a patched tmux available in ~/tmux-screen/bin/tmux. This is a magic location. z4h will automatically enter tmux through this binary in a way that's almost invisible. There is no TMUX environment variable, no tmux key bindings, you aren't in the alternate screen, native scrollback still works, etc. You'll notice that screen clears when tmux starts. This is unavoidable but in the future this also will be invisible because tmux will start when you open a tab in a local terminal. It won't start when you ssh.

I've a few ideas how to make progress here:

  1. I can send a PR to tmux that conditionally does what my patch does if tmux is launched with the alternate screen disabled. This way I won't have to maintain a custom build of tmux forever.
  2. Independently from (1), I can build my forked tmux statically and install it through zsh4humans the same way how it installs everything else (zsh, gitstatusd, fzf, etc.). Note that it won't be necessary to install tmux over ssh because I can use the tmux on the local host to display fzf in a popup.
  3. I can make "auto tmux" configurable. I'm thinking of 3 modes:
    • Do not start tmux automatically.
    • If there is no tmux, start the transparent one automatically. This will probably be the default.
    • If there is no tmux, start a normal tmux (honoring normal system and user configs) automatically. This is for users who actually like tmux.

Let me know what you think. If you try it, leave a note saying whether it worked or not.

Props to @Aloxaf for alerting me to this great idea!

Syphdias commented 4 years ago

In other words, I think the default behavior of Ctrl+K in fzf is sensible. It's fine to rebind it in your own config. I expect bindings to be one of the most common thing people customize. There are really no right or wrong bindings (there is value in consistency though).

I regularly use it on the commad line and I didn't think of it while using one of the fzf cases. I guess you overwrote every fzf default keybinding related to line editing for consistency. I wonder when I would have noticed :thinking:. I'll rebind it for my config and will find out.

Yes, you can change it in .zshenv. What do you want to change it to if you don't mind my asking? g-w,o-w? Why?

I usually set it to 027 even on my personal workstation out of best-practice/paranoia/habit (take a pic). But while working on a terminal server I added o+x on my home directory to share some scripts which makes it necessary to remove more permissions.

Indeed, I've disabled substring matching because it was giving me trouble in the new completion frontend. Sometimes "unambigous" completion would insert something that cannot be completed further. Another downside of substring matching is that it makes completions twice as slow when there is no match.

Is this something that can be reenabled via a setopt?

Perhaps I should revisit this. How important is this to you? What are some real-life examples where you rely on this feature?

"Rely" is a strong word but I'll describe some use-case I have for it. I have a projects directory with multiple subdirectories with the same prefix but it is not uniq:

❯ ls
ceph  ceph-ansible  ceph-scripts  ceph-setup-amazon  ceph-setup-apple  ceph-setup-google  ceph-setup-microsoft  ceph-source  other-stuff

(I picked a few tech companys as examples) So the following worked quite nicely: cd ama<TAB> -> cd ceph-setup-amazon While now I need to go though typing or tab completing ceph-setup-. A workaround would be: cd <TAB>ama<TAB> which would be one key stroke more and might has the downside of also matching subdirectories in the wrong folders depending on how the results are soreted.

Is this something you want? Can you provide some context why you want it?

Yes, currently I use a rather funky function to grep for #z4h in my ssh config files to find matching hosts. So I totally love that option. But I'd rather not copy z4h to work related hosts and the number of private hosts is far fewer so enabling z4h ssh by default is not an option for me.
Well, and if this works as a "default off" it is already exactly what I needed.

Good point, it looks confusing. What would be a better name for this style?

After I understood it bypasses the function it made sense. But maybe zstyle ':z4h:ssh:*' enable 'yes' is more descriptive? This would invert the meaning of the boolean though. On the other side it might be misleading because it does not enable anything if there is not a function to make it work. (Side note: why a function and not an alias?)

In the meantime I've changed the auto-update logic to make your use-case a bit less painful. If you open a terminal, agree to auto update and then open another tab while the update is running, you won't be asked to auto-update. You might run into issues I've described above (the second tab will use a random blend of two z4h versions) but in practice you'll rarely be affected by them.

This didn't happen to me yet. I'll keep it in mind!

Thanks for the feedback!

Happy to provide it :) Thanks for being so open to it!

romkatv commented 4 years ago

I usually set it to 027 even on my personal workstation out of best-practice/paranoia/habit (take a pic). But while working on a terminal server I added o+x on my home directory to share some scripts which makes it necessary to remove more permissions.

Makes sense. It's totally fine to change umask in .zshenv or to even remove it. It's there because .zshenv creates $Z4H directory.

Is this something that can be reenabled via a setopt?

You can add this below z4h init:

zstyle ':completion:*' matcher-list "m:{a-z}={A-Z}" "l:|=* r:|=*"

This may break some completions but mostly should work fine. I still need to debug why sometimes things break.

"Rely" is a strong word but I'll describe some use-case I have for it. I have a projects directory with multiple subdirectories with the same prefix but it is not uniq:

❯ ls
ceph  ceph-ansible  ceph-scripts  ceph-setup-amazon  ceph-setup-apple  ceph-setup-google  ceph-setup-microsoft  ceph-source  other-stuff

(I picked a few tech companys as examples) So the following worked quite nicely: cd ama<TAB> -> cd ceph-setup-amazon While now I need to go though typing or tab completing ceph-setup-. A workaround would be: cd <TAB>ama<TAB> which would be one key stroke more and might has the downside of also matching subdirectories in the wrong folders depending on how the results are soreted.

Makes sense. FWIW, I'd use cd <TAB>ama<TAB> (or in this case it would be Alt+Down followed by ama). While it's more key presses for this completion but it fails more gracefully if nothing matches. Once you delete the query from fzf (Ctrl+U or Alt+J) you could see what possible matches are there. If you type cd <TAB>ama<TAB> and get no matches, it's worse.

Overall, I think substring matches are mildly useful. I'd like to re-enable them once I figure out why my code sometimes misbehaves. I don't think I'll be able to solve the slowdown problem though. It's too deep within zsh.

Yes, currently I use a rather funky function to grep for #z4h in my ssh config files to find matching hosts. So I totally love that option. But I'd rather not copy z4h to work related hosts and the number of private hosts is far fewer so enabling z4h ssh by default is not an option for me.

Do I understand it correctly that z4h ssh works with all hosts but you just don't want to use it when connecting to machines owned by your employer?

After I understood it bypasses the function it made sense. But maybe zstyle ':z4h:ssh:*' enable 'yes' is more descriptive? This would invert the meaning of the boolean though. On the other side it might be misleading because it does not enable anything if there is not a function to make it work. (Side note: why a function and not an alias?)

I like zstyle ':z4h:ssh:*' enable 'yes'. I can even make no the default and put this override in the stock .zshrc.

romkatv commented 4 years ago

Side note: why [is ssh] a function and not an alias?

So that completions for ssh work. If there were completions for z4h, alias ssh='z4h ssh would work just as well as a function.

maximbaz commented 4 years ago

@Aloxaf has shown me a new and super cool feature in fzf-tab: Aloxaf/fzf-tab#130.

WOW! When I thought nothing could surprise me anymore in zsh config, you guys pull off yet another trick up your sleeve! Thanks to you and to @Aloxaf!

There is no TMUX environment variable, no tmux key bindings, you aren't in the alternate screen, native scrollback still works, etc.

When I first noticed the word tmux I was prepared to be disappointed, but your second demo is just awesome, and everything you mention here is very important for me.

If you are very brave, you can try it locally. Replace v4 with v5 in ~/.zshenv and run exec zsh

Well we are here in this thread not because we are afraid of investigating some bugs :wink:

I switched to v5 and compiled & installed your fork of tmux as per instructions from your second demo. Will will keep using it and as usual report back if I find any inconveniences or bugs.

My only immediate feedback is this: I generally prefer the "natural order" layout of fzf where things are ordered from top to bottom, so I have export FZF_DEFAULT_OPTS="--reverse --multi"

But in this specific case, when there is not enough space below and z4h needs to place fzf on top, then and only then it makes sense to have the layout in reverse order, from bottom to top. I can see you add --layout=reverse in some places, could you just add --layout=default when it makes most sense to have such layout?

I've a few ideas how to make progress here...

Agree with all three :+1:

romkatv commented 4 years ago

When I first noticed the word tmux I was prepared to be disappointed

That makes two of us πŸ˜…

but your second demo is just awesome, and everything you mention here is very important for me.

Thanks! I'll keep working on it then. It's good to know I'm not the only one excited about this feature.

I switched to v5 and compiled & installed your fork of tmux as per instructions from your second demo. Will will keep using it and as usual report back if I find any inconveniences or bugs.

Awesome! In turn, I'll keep you updated on the changes I make to v5.

I should mention that currently fzf opens in a wrong place when you are editing a multi-line command and hit Tab while the cursor is not on the last line. I'll fix it when I figure out which behavior I want in this case.

My only immediate feedback is this: I generally prefer the "natural order" layout of fzf where things are ordered from top to bottom, so I have export FZF_DEFAULT_OPTS="--reverse --multi"

But in this specific case, when there is not enough space below and z4h needs to place fzf on top, then and only then it makes sense to have the layout in reverse order, from bottom to top. I can see you add --layout=reverse in some places, could you just add --layout=default when it makes most sense to have such layout?

Interesting. I was just about to add --reverse everywhere. In theory it sounds like the default layout should work better when opening fzf above the cursor because it places the query line and the best match close to where you are already looking. This works OK for history but is rather confusing with command completions. First, it makes the list of completion candidates appear in the reverse sorting order. Second, using Ctrl+Space to select a subset of items feels weird because after the first press it'll wrap around (because the selection is originally on the bottom-most item).

There is also --layout=reverse-list but I don't like it as it puts the query and the selector far apart from each other.

For the sake of experiment I've now done two things:

  1. Added --layout=default when fzf opens above the cursor (as you've suggested).
  2. Changed the Ctrl+Space binding from toggle+down to toggle-out. This effectively turns it into toggle+up when --layout=default is in effect.

Give it a try and let me know how you feel about it.