zsh-users
 help / color / mirror / code / Atom feed
* How to add a 'non-escaped' tilde to the completion list
@ 2014-11-10 11:07 Death Jester
  2014-11-10 11:31 ` Peter Stephenson
  0 siblings, 1 reply; 11+ messages in thread
From: Death Jester @ 2014-11-10 11:07 UTC (permalink / raw)
  To: zsh-users

Hi *,
I have the following completion function:

  function _term_list(){
    local -a w

    for SESSION in $(pidof  zsh); do
      PA=$(readlink -n /proc/${SESSION}/cwd)
      case ${PA} in
        ${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;
        *) w+=${PA} ;;
      esac
    done

    compadd -a w
  }

  zle -C term_list complete-word _generic
  bindkey "^v" term_list
  zstyle ':completion:term_list:*' completer _term_list

It provides a list of paths in which other zsh sessions are in. I want
to substitute my home folder with a tilde (~). But unfortunately the
line '${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;' does not work
as intended. The tilde is always "escaped". So the output looks like:
  \~
  \~/folder

How can I remove the backslash.

Thank you in advance.

Cheers,
Jester




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 11:07 How to add a 'non-escaped' tilde to the completion list Death Jester
@ 2014-11-10 11:31 ` Peter Stephenson
  2014-11-10 12:18   ` Peter Stephenson
  2014-11-10 12:54   ` Death Jester
  0 siblings, 2 replies; 11+ messages in thread
From: Peter Stephenson @ 2014-11-10 11:31 UTC (permalink / raw)
  To: zsh-users

On Mon, 10 Nov 2014 12:07:29 +0100
Death Jester <d3ath.jest3r@gmail.com> wrote:

> Hi *,
> I have the following completion function:
> 
>   function _term_list(){
>     local -a w
> 
>     for SESSION in $(pidof  zsh); do
>       PA=$(readlink -n /proc/${SESSION}/cwd)
>       case ${PA} in
>         ${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;
>         *) w+=${PA} ;;
>       esac
>     done
> 
>     compadd -a w
>   }
> 
>   zle -C term_list complete-word _generic
>   bindkey "^v" term_list
>   zstyle ':completion:term_list:*' completer _term_list

You can replace the whole case with:

w+=(${(D)PA})

which does the substitution you're after --- it substitues all named
directories, in fact, not just $HOME, but presumably that's OK.

Note you do need the parentheses when you're adding array elements,

> But unfortunately the
> line '${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;' does not work
> as intended. The tilde is always "escaped". So the output looks like:
>   \~
>   \~/folder
> 
> How can I remove the backslash.

I presume you mean it's escaped when it's inserted on the command line.

The short answer is you need to add the -Q flag to the compadd at the
end of the function so that the name doesn't get quoted.  However, you
need to be a bit careful since that implies that you've already quoted
the rest of the name (having spaces is the most common cause of grief).

I'm sure there's some prior art on this in the completion system that
others will remember better than me.

pws


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 11:31 ` Peter Stephenson
@ 2014-11-10 12:18   ` Peter Stephenson
  2014-11-10 13:21     ` Death Jester
  2014-11-10 12:54   ` Death Jester
  1 sibling, 1 reply; 11+ messages in thread
From: Peter Stephenson @ 2014-11-10 12:18 UTC (permalink / raw)
  To: zsh-users

On Mon, 10 Nov 2014 11:31:36 +0000
Peter Stephenson <p.stephenson@samsung.com> wrote:
> 
> > But unfortunately the
> > line '${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;' does not work
> > as intended. The tilde is always "escaped". So the output looks like:
> >   \~
> >   \~/folder
> > 
> > How can I remove the backslash.
> 
> I presume you mean it's escaped when it's inserted on the command line.
> 
> The short answer is you need to add the -Q flag to the compadd at the
> end of the function so that the name doesn't get quoted.

Ah, it's coming back a bit...  Try adding -f instead of -Q.  That tells
the system it's a file name, and I think that's good enough that it
knows tildes are special.

pws


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 11:31 ` Peter Stephenson
  2014-11-10 12:18   ` Peter Stephenson
@ 2014-11-10 12:54   ` Death Jester
  1 sibling, 0 replies; 11+ messages in thread
From: Death Jester @ 2014-11-10 12:54 UTC (permalink / raw)
  To: zsh-users

Awesome, thank you Peter! Now it works. I extended my function in the
following way:

  function _term_list(){
    local -a w

    for SESSION in $(pidof  zsh); do
      PA=$(readlink -n /proc/${SESSION}/cwd)
      w+=(${(D)PA})
    done

    compadd -aQ w
  }

And btw, also spaces are recognized correctly and are terminated with a
backslash in front of it, when inserted on the commandline.

Cheers,
Jester


On Mon, 2014-11-10 at 11:31 +0000, Peter Stephenson wrote:
> On Mon, 10 Nov 2014 12:07:29 +0100
> Death Jester <d3ath.jest3r@gmail.com> wrote:
> 
> > Hi *,
> > I have the following completion function:
> > 
> >   function _term_list(){
> >     local -a w
> > 
> >     for SESSION in $(pidof  zsh); do
> >       PA=$(readlink -n /proc/${SESSION}/cwd)
> >       case ${PA} in
> >         ${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;
> >         *) w+=${PA} ;;
> >       esac
> >     done
> > 
> >     compadd -a w
> >   }
> > 
> >   zle -C term_list complete-word _generic
> >   bindkey "^v" term_list
> >   zstyle ':completion:term_list:*' completer _term_list
> 
> You can replace the whole case with:
> 
> w+=(${(D)PA})
> 
> which does the substitution you're after --- it substitues all named
> directories, in fact, not just $HOME, but presumably that's OK.
> 
> Note you do need the parentheses when you're adding array elements,
> 
> > But unfortunately the
> > line '${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;' does not work
> > as intended. The tilde is always "escaped". So the output looks like:
> >   \~
> >   \~/folder
> > 
> > How can I remove the backslash.
> 
> I presume you mean it's escaped when it's inserted on the command line.
> 
> The short answer is you need to add the -Q flag to the compadd at the
> end of the function so that the name doesn't get quoted.  However, you
> need to be a bit careful since that implies that you've already quoted
> the rest of the name (having spaces is the most common cause of grief).
> 
> I'm sure there's some prior art on this in the completion system that
> others will remember better than me.
> 
> pws



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 12:18   ` Peter Stephenson
@ 2014-11-10 13:21     ` Death Jester
  2014-11-10 13:42       ` Peter Stephenson
  2014-11-10 13:57       ` Oliver Kiddle
  0 siblings, 2 replies; 11+ messages in thread
From: Death Jester @ 2014-11-10 13:21 UTC (permalink / raw)
  To: zsh-users

Hi.
ok. I thought it works and the substitution now actually works as
intended, either with '-f' or '-Q'. But now I have another issue xD

When I hit my shortcut 'CTRL+v', the completion system adds a '~'
character to the command line instead of showing me the list of
available directories. When I hit 'CTRL+v' again, I get an other '~' and
the list. So now it looks like:

  cd ~~
  ~/foler1
  ~/folder2

and when I select a folder from the list, I have now '~~/folder2' on the
commandline. How do I get rid of the first tilde? The code now looks
like:

  function _term_list(){
    local -a w

    for SESSION in $(pidof  zsh); do
      PA=$(readlink -n /proc/${SESSION}/cwd)
      w+=(${(D)PA})
    done

    compadd -af w
  }

  zle -C term_list complete-word _generic
  bindkey "^v" term_list
  zstyle ':completion:term_list:*' completer _term_list

Thank you again.

Cheers,
Jester

On Mon, 2014-11-10 at 12:18 +0000, Peter Stephenson wrote:
> On Mon, 10 Nov 2014 11:31:36 +0000
> Peter Stephenson <p.stephenson@samsung.com> wrote:
> > 
> > > But unfortunately the
> > > line '${HOME}*) w+=$(echo ${PA} | sed s"|${HOME}|~|") ;;' does not work
> > > as intended. The tilde is always "escaped". So the output looks like:
> > >   \~
> > >   \~/folder
> > > 
> > > How can I remove the backslash.
> > 
> > I presume you mean it's escaped when it's inserted on the command line.
> > 
> > The short answer is you need to add the -Q flag to the compadd at the
> > end of the function so that the name doesn't get quoted.
> 
> Ah, it's coming back a bit...  Try adding -f instead of -Q.  That tells
> the system it's a file name, and I think that's good enough that it
> knows tildes are special.
> 
> pws



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 13:21     ` Death Jester
@ 2014-11-10 13:42       ` Peter Stephenson
  2014-11-10 13:57       ` Oliver Kiddle
  1 sibling, 0 replies; 11+ messages in thread
From: Peter Stephenson @ 2014-11-10 13:42 UTC (permalink / raw)
  To: zsh-users

On Mon, 10 Nov 2014 14:21:06 +0100
Death Jester <d3ath.jest3r@gmail.com> wrote:
> ok. I thought it works and the substitution now actually works as
> intended, either with '-f' or '-Q'. But now I have another issue xD
> 
> When I hit my shortcut 'CTRL+v', the completion system adds a '~'
> character to the command line instead of showing me the list of
> available directories. When I hit 'CTRL+v' again, I get an other '~' and
> the list.

I suspect that's CTRL+v rather than the completion system: your
completion function doesn't look problematic in that regard.
CTRL+v is often used to quote the next character and that can be
interpreted somewhere other than in the shell's line editor.

See if you still get this with another binding.

pws


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 13:21     ` Death Jester
  2014-11-10 13:42       ` Peter Stephenson
@ 2014-11-10 13:57       ` Oliver Kiddle
  2014-11-10 15:32         ` Death Jester
  1 sibling, 1 reply; 11+ messages in thread
From: Oliver Kiddle @ 2014-11-10 13:57 UTC (permalink / raw)
  To: Death Jester; +Cc: zsh-users

Death Jester wrote:
>   zle -C term_list complete-word _generic

_generic, or more specifically _main_complete, is the source of some of
the problems with this. Try using _term_list directly.

Very nice idea by the way. If you get it working fully, please post it
so I can steal it for my setup.

Oliver


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 13:57       ` Oliver Kiddle
@ 2014-11-10 15:32         ` Death Jester
  2014-11-10 21:03           ` Oliver Kiddle
  0 siblings, 1 reply; 11+ messages in thread
From: Death Jester @ 2014-11-10 15:32 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-users

Thank you Oliver, you are right. It was related to the 'zle ...'
command. The binding however was not the problem, but the type of
completion.

Now I fixed it. You can now hit CTRL+v to get the list of folders and
afterwards hit Tab to cycle through the list:

  function _term_list(){
    local -a w

    for SESSION in $(pidof  zsh); do
      w+=${(D)$(readlink -n /proc/${SESSION}/cwd)}
    done

    compadd -aQ w
  }

  zle -C term_list menu-complete _generic
  bindkey "^v" term_list
  zstyle ':completion:term_list:*' completer _term_list

Btw, I'm not sure if "advertisement" is allowed here. I have submitted
the plugin to the oh-my-zsh project. But without any testers, they don't
want to merge it in to the mainline project. So if anybody is interested
you can test it... =)

Cheers,
Jester


On Mon, 2014-11-10 at 14:57 +0100, Oliver Kiddle wrote:
> Death Jester wrote:
> >   zle -C term_list complete-word _generic
> 
> _generic, or more specifically _main_complete, is the source of some of
> the problems with this. Try using _term_list directly.
> 
> Very nice idea by the way. If you get it working fully, please post it
> so I can steal it for my setup.
> 
> Oliver



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 15:32         ` Death Jester
@ 2014-11-10 21:03           ` Oliver Kiddle
  2014-11-11 10:17             ` Death Jester
  2014-11-11 21:40             ` Jan Larres
  0 siblings, 2 replies; 11+ messages in thread
From: Oliver Kiddle @ 2014-11-10 21:03 UTC (permalink / raw)
  To: Death Jester; +Cc: zsh-users

Death Jester wrote:
> The binding however was not the problem, but the type of
> completion.

Using menu completion is an improvement. You'll find that this now works
on an empty word but fails when you have already typed a prefix (or
suffix) of the directory.

The problem with _generic is that _main_complete has special handling for
tildes and equals. _history already works around this: you need to move
the ~ back to $PREFIX from $IPREFIX.

I've attached a fixed function that also has a replacement for the pidof
that will work on Solaris. I think lsof can also be used on other
platforms. Would be nice to support the BSDs. It may also be possible to
better filter the processes: just those with a controlling tty perhaps?

readlink is replaced by zsh's internal :A modifier and the current
process is filtered out. It also enables partial completion for /
and pattern matching so if you know that another shell is in a src
directory, you can type *src and the widget will complete that to the
right directory.

>   zstyle ':completion:term_list:*' completer _term_list

I'd recommend changing that to the more specific
  zstyle ':completion:term_list::::' completer _term_list

In at least my setup a different completer style would otherwise take
precedence.

> Btw, I'm not sure if "advertisement" is allowed here. I have submitted
> the plugin to the oh-my-zsh project. But without any testers, they don't
> want to merge it in to the mainline project. So if anybody is interested
> you can test it... =)

I'd have thought the function itself was something we could include in
the main zsh distribution if people are agreeable? I'm not too sure on
the name but am struggling to offer something better - foreign-pwds,
external-pwds perhaps?

For omz, you might want to consider a different keystroke. Ctrl-V has
an existing purpose that some people might not be pleased to have
replaced.

Oliver

#autoload

local -a expl
local -au dirs

# undo work _main_complete did to remove the tilde
PREFIX="$IPREFIX$PREFIX"
IPREFIX=
SUFFIX="$SUFFIX$ISUFFIX"
ISUFFIX=

[[ -o magicequalsubst ]] && compset -P '*='

case $OSTYPE in
  solaris*) dirs=( ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx)"}:#$$:*}%%/*} ) ;;
  linux*) dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) ;;
esac
dirs=( ${(D)dirs} )

compstate[pattern_match]='*'
_wanted directories expl 'current directory from other shell' \
    compadd -M "r:|/=* r:|=*" -f -a dirs


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 21:03           ` Oliver Kiddle
@ 2014-11-11 10:17             ` Death Jester
  2014-11-11 21:40             ` Jan Larres
  1 sibling, 0 replies; 11+ messages in thread
From: Death Jester @ 2014-11-11 10:17 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-users

On Mon, 2014-11-10 at 22:03 +0100, Oliver Kiddle wrote:
> Death Jester wrote:
> > The binding however was not the problem, but the type of
> > completion.
> 
> Using menu completion is an improvement. You'll find that this now works
> on an empty word but fails when you have already typed a prefix (or
> suffix) of the directory.
> 
> The problem with _generic is that _main_complete has special handling for
> tildes and equals. _history already works around this: you need to move
> the ~ back to $PREFIX from $IPREFIX.
> 
> I've attached a fixed function that also has a replacement for the pidof
> that will work on Solaris. I think lsof can also be used on other
> platforms. Would be nice to support the BSDs. It may also be possible to
> better filter the processes: just those with a controlling tty perhaps?
> 
> readlink is replaced by zsh's internal :A modifier and the current
> process is filtered out. It also enables partial completion for /
> and pattern matching so if you know that another shell is in a src
> directory, you can type *src and the widget will complete that to the
> right directory.
> 
> >   zstyle ':completion:term_list:*' completer _term_list
> 
> I'd recommend changing that to the more specific
>   zstyle ':completion:term_list::::' completer _term_list
> 
> In at least my setup a different completer style would otherwise take
> precedence.
> 
> > Btw, I'm not sure if "advertisement" is allowed here. I have submitted
> > the plugin to the oh-my-zsh project. But without any testers, they don't
> > want to merge it in to the mainline project. So if anybody is interested
> > you can test it... =)
> 
> I'd have thought the function itself was something we could include in
> the main zsh distribution if people are agreeable? I'm not too sure on
> the name but am struggling to offer something better - foreign-pwds,
> external-pwds perhaps?

That would be awesome! I think a short name for 'external-pwds', like
'ext_pwds' sounds good to me...

> 
> For omz, you might want to consider a different keystroke. Ctrl-V has
> an existing purpose that some people might not be pleased to have
> replaced.

Yes, of course. Unfortunately I don't have an overview what keys are
already bound to something. Ctrl+V seemed to be available. But I'm open
for other suggestions.

> 
> Oliver
> 
> #autoload
> 
> local -a expl
> local -au dirs
> 
> # undo work _main_complete did to remove the tilde
> PREFIX="$IPREFIX$PREFIX"
> IPREFIX=
> SUFFIX="$SUFFIX$ISUFFIX"
> ISUFFIX=
> 
> [[ -o magicequalsubst ]] && compset -P '*='
> 
> case $OSTYPE in
>   solaris*) dirs=( ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx)"}:#$$:*}%%/*} ) ;;
>   linux*) dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) ;;
> esac
> dirs=( ${(D)dirs} )
> 
> compstate[pattern_match]='*'
> _wanted directories expl 'current directory from other shell' \
>     compadd -M "r:|/=* r:|=*" -f -a dirs

I tested your new function on Linux (with version string: 'zsh 5.0.7
(x86_64-pc-linux-gnu)') and it works for me. I have also tested the
cases
1) The list is empty except the current shell (works -> no list only '~'
on commandline)
2) I start to type and then hit the completion button (works -> sublist
appears)

I have replaced the zstyle line as you suggested:

  zle -C term_list menu-complete _generic
  bindkey "^v" term_list
  zstyle ':completion:term_list::::' completer _term_list


I neither have a BSD, nor a Solaris machine, so I can't test it for
Solaris, or implement it for BSD...

Thank you for your awesome help Peter and Oliver.

Cheers,
Julian


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to add a 'non-escaped' tilde to the completion list
  2014-11-10 21:03           ` Oliver Kiddle
  2014-11-11 10:17             ` Death Jester
@ 2014-11-11 21:40             ` Jan Larres
  1 sibling, 0 replies; 11+ messages in thread
From: Jan Larres @ 2014-11-11 21:40 UTC (permalink / raw)
  To: zsh-users

On 11/11/14 10:03, Oliver Kiddle wrote:
> #autoload
>
> local -a expl
> local -au dirs
>
> # undo work _main_complete did to remove the tilde
> PREFIX="$IPREFIX$PREFIX"
> IPREFIX=
> SUFFIX="$SUFFIX$ISUFFIX"
> ISUFFIX=
>
> [[ -o magicequalsubst ]] && compset -P '*='
>
> case $OSTYPE in
>   solaris*) dirs=( ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx)"}:#$$:*}%%/*} ) ;;
>   linux*) dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) ;;
> esac
> dirs=( ${(D)dirs} )
>
> compstate[pattern_match]='*'
> _wanted directories expl 'current directory from other shell' \
>     compadd -M "r:|/=* r:|=*" -f -a dirs

I would suggest this addition to the function:

dirs=( ${dirs//\/proc\/*\/cwd/} )

This removes unexpanded directories from the list. This can happen when
a shell's directory has been removed, which pretty regularly is the case
for me with auto-generated build directories.

-Jan


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-11-11 21:41 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-10 11:07 How to add a 'non-escaped' tilde to the completion list Death Jester
2014-11-10 11:31 ` Peter Stephenson
2014-11-10 12:18   ` Peter Stephenson
2014-11-10 13:21     ` Death Jester
2014-11-10 13:42       ` Peter Stephenson
2014-11-10 13:57       ` Oliver Kiddle
2014-11-10 15:32         ` Death Jester
2014-11-10 21:03           ` Oliver Kiddle
2014-11-11 10:17             ` Death Jester
2014-11-11 21:40             ` Jan Larres
2014-11-10 12:54   ` Death Jester

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).