zsh-users
 help / color / mirror / code / Atom feed
* Calling a zle widget from a function
@ 2007-06-12 14:44 Angel Olivera
  2007-06-12 15:14 ` Peter Stephenson
  0 siblings, 1 reply; 8+ messages in thread
From: Angel Olivera @ 2007-06-12 14:44 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 929 bytes --]

Hello.

I am trying to write a function that clears the screen every so many 
seconds. I asked for some help in #zsh, and thanks to curalton and ft I 
came up with:

precmd() {
	...
	TMOUT=60
}

TRAPALRM() {
	print "Clearing screen..."
	clear
	unset TMOUT
}

This works, but clear(1) is too obtrusive to be useful, as it will clear
anything that I've got on my command line.

So I would love to be able to call zle's clear-screen widget from the function.

redondos@refinery ~ % zle clear-screen
zle: widgets can only be called when ZLE is active

I am not fully aware of how zle works, and how (if possible) I would make it
active. It looks like the zle builtin only accepts a widget if it is called
from within another widget, and not on the command line.

Any workarounds for this, or any other way of clearing the screen more
efficient and unobtrusively?

Thanks in advance.

-- 
redondos

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: Calling a zle widget from a function
  2007-06-12 14:44 Calling a zle widget from a function Angel Olivera
@ 2007-06-12 15:14 ` Peter Stephenson
  2007-06-12 16:23   ` Frank Terbeck
  2007-06-12 17:32   ` Angel Olivera
  0 siblings, 2 replies; 8+ messages in thread
From: Peter Stephenson @ 2007-06-12 15:14 UTC (permalink / raw)
  To: zsh-users

Angel Olivera wrote:
> So I would love to be able to call zle's clear-screen widget from the
> function.
> 
> redondos@refinery ~ % zle clear-screen
> zle: widgets can only be called when ZLE is active

If you have version 4.3.4 the sched mechanism will call functions
asynchronously within zle, if that's running.  So something like

  clear-zle-screen() {
    zle && zle clear-screen
    sched +60 clear-zle-screen
  }
  sched +60 clear-zle-screen

does the basics.  However, it will attempt to clear the screen *every*
60 seconds, not just after 60 seconds of idleness.  One possible way
around that is to look at the modification time for the terminal and compare
it with the current time:

  clear-zle-screen() {
    zmodload -i zsh/stat
    zmodload -i zsh/datetime
    local -a mtime
    integer diff

    stat -A mtime +mtime $TTY
    (( diff = EPOCHSECONDS - ${mtime} ))
    if (( diff > 60 )); then
      zle && zle clear-screen
      sched +60 clear-zle-screen
    else
      sched +$(( 60 - diff )) clear-zle-screen
    fi
  }

(I needed to use $TTY, not /dev/tty, on the Fedora Core 6 system I have
here since they don't seem to be kept in sync.)

This doesn't work with 4.2 where sched is only run synchronously and
never from zle.  I think you'd have to do it in two steps: have the
timeout set a flag, and have some zle hook look at the timeout.  But
hooking into zle at that depth is quite painful.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php

To get further information regarding CSR, please visit our Investor Relations page at http://ir.csr.com/csr/about/overview


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

* Re: Calling a zle widget from a function
  2007-06-12 15:14 ` Peter Stephenson
@ 2007-06-12 16:23   ` Frank Terbeck
  2007-06-12 16:53     ` Peter Stephenson
  2007-06-12 17:32   ` Angel Olivera
  1 sibling, 1 reply; 8+ messages in thread
From: Frank Terbeck @ 2007-06-12 16:23 UTC (permalink / raw)
  To: zsh-users

Peter Stephenson <pws@csr.com>:
> Angel Olivera wrote:
> > So I would love to be able to call zle's clear-screen widget from the
> > function.
> > 
> > redondos@refinery ~ % zle clear-screen
> > zle: widgets can only be called when ZLE is active
[...]
> This doesn't work with 4.2 where sched is only run synchronously and
> never from zle.  I think you'd have to do it in two steps: have the
> timeout set a flag, and have some zle hook look at the timeout.  But
> hooking into zle at that depth is quite painful.

So, that means that (no matter if using v4.2 or v4.3) you cannot call
widgets from the commandline, right?

And how would you 'hook' into zle? I don't know what you meant by
that.

Regards, Frank

-- 
In protocol design, perfection has been reached not when there is
nothing left to add, but when there is nothing left to take away.
                                                  -- RFC 1925


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

* Re: Calling a zle widget from a function
  2007-06-12 16:23   ` Frank Terbeck
@ 2007-06-12 16:53     ` Peter Stephenson
  2007-06-12 17:38       ` Frank Terbeck
  0 siblings, 1 reply; 8+ messages in thread
From: Peter Stephenson @ 2007-06-12 16:53 UTC (permalink / raw)
  To: zsh-users

Frank Terbeck wrote:
> So, that means that (no matter if using v4.2 or v4.3) you cannot call
> widgets from the commandline, right?

>From the *command line* you can: type Esc x and enter the name of the
widget (or bind it with bindkey).  From something executed as an
ordinary piece of shell code from the command line, and in particular
from a trap, you can't.

> And how would you 'hook' into zle? I don't know what you meant by
> that.

You can redefine any standard widget to get it to execute your own code
as well as its normal function.  This is sometimes done with
accept-line:

  accept-line() {
    my-code
    zle .accept-line
  }
  zle -N accept-line

However, I don't think there's anything you can intercept when zle is
idle.  You can "kick" zle with "zle -I" from outside it to cause it to
redisplay, but as far as I can see that doesn't go through any
user-redefinable widgets.  So that doesn't seem to help either.

There are a limited number of "real" hooks (zle-line-init and
zle-keymap-select), although I called them "special widgets" which
wasn't a particular clever name, but neither of them helps here either.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php

To get further information regarding CSR, please visit our Investor Relations page at http://ir.csr.com/csr/about/overview


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

* Re: Calling a zle widget from a function
  2007-06-12 15:14 ` Peter Stephenson
  2007-06-12 16:23   ` Frank Terbeck
@ 2007-06-12 17:32   ` Angel Olivera
  2007-06-12 17:51     ` Peter Stephenson
  1 sibling, 1 reply; 8+ messages in thread
From: Angel Olivera @ 2007-06-12 17:32 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

On Tue 12.Jun.07 16:14, Peter Stephenson wrote:
>If you have version 4.3.4 the sched mechanism will call functions
>asynchronously within zle, if that's running.  So something like
>
>  clear-zle-screen() {
>    zle && zle clear-screen
>    sched +60 clear-zle-screen
>  }
>  sched +60 clear-zle-screen
>
>does the basics.  However, it will attempt to clear the screen *every*
>60 seconds, not just after 60 seconds of idleness.  One possible way
>around that is to look at the modification time for the terminal and compare
>it with the current time:
>
>  clear-zle-screen() {
>    zmodload -i zsh/stat
>    zmodload -i zsh/datetime
>    local -a mtime
>    integer diff
>
>    stat -A mtime +mtime $TTY
>    (( diff = EPOCHSECONDS - ${mtime} ))
>    if (( diff > 60 )); then
>      zle && zle clear-screen
>      sched +60 clear-zle-screen
>    else
>      sched +$(( 60 - diff )) clear-zle-screen
>    fi
>  }

Amazing, thanks a lot, Peter!

Here's the (maybe) final setup:

## $fpath[1]/clear-zle-screen
zmodload -i zsh/stat
zmodload -i zsh/datetime

clear-zle-screen() {
    local -a mtime
    integer diff

    stat -A mtime +mtime $TTY
    (( diff = EPOCHSECONDS - ${mtime} ))
    if (( diff >= CLRTMOUT )); then
	zle && zle clear-screen
    # function called from precmd(), to avoid multiple clearouts
    #    sched +$CLRTMOUT clear-zle-screen
    else
	sched +$(( CLRTMOUT - diff )) clear-zle-screen
    fi
}

functions[precmd]+="; sched +$CLRTMOUT clear-zle-screen"
clear-zle-screen

## zshrc
## Clear the screen after CLRTMOUT seconds of inactivity
if [[ $ZSH_VERSION == 4.3.<4-> ]]; then
    CLRTMOUT=3600
    autoload clear-zle-screen
    clear-zle-screen
fi

Now, for every prompt that is printed I get a new sched job queued. This might 
get as big as 3600 or more. Do you think that is going to be a serious 
performance penalty on my daily zsh routine?

Cheers; and, again, thank you.

-- 
redondos

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: Calling a zle widget from a function
  2007-06-12 16:53     ` Peter Stephenson
@ 2007-06-12 17:38       ` Frank Terbeck
  0 siblings, 0 replies; 8+ messages in thread
From: Frank Terbeck @ 2007-06-12 17:38 UTC (permalink / raw)
  To: zsh-users

Peter Stephenson <pws@csr.com>:
> Frank Terbeck wrote:
> > So, that means that (no matter if using v4.2 or v4.3) you cannot call
> > widgets from the commandline, right?
> 
> From the *command line* you can: type Esc x and enter the name of the
> widget (or bind it with bindkey).  From something executed as an
> ordinary piece of shell code from the command line, and in particular
> from a trap, you can't.

Yes, I knew 'execute-named-cmd'. I meant the latter. Thanks for
clarifying.

> > And how would you 'hook' into zle? I don't know what you meant by
> > that.
> 
> You can redefine any standard widget to get it to execute your own code
> as well as its normal function.  This is sometimes done with
> accept-line:
> 
>   accept-line() {
>     my-code
>     zle .accept-line
>   }
>   zle -N accept-line

So, .widgetname always calls the original widget. That is really
helpful. Thanks for mentioning it. :-)
I always created some differently named widget and rebound the original
key, which is kind of a PITA, if you don't know to which key the
original widget may have been bound to.

> However, I don't think there's anything you can intercept when zle is
> idle.  You can "kick" zle with "zle -I" from outside it to cause it to
> redisplay, but as far as I can see that doesn't go through any
> user-redefinable widgets.  So that doesn't seem to help either.

Okay.

> There are a limited number of "real" hooks (zle-line-init and
> zle-keymap-select), although I called them "special widgets" which
> wasn't a particular clever name, but neither of them helps here either.

Again, something new (for me). I'll look into these.

Regards, Frank

-- 
In protocol design, perfection has been reached not when there is
nothing left to add, but when there is nothing left to take away.
                                                  -- RFC 1925


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

* Re: Calling a zle widget from a function
  2007-06-12 17:32   ` Angel Olivera
@ 2007-06-12 17:51     ` Peter Stephenson
  2007-06-12 19:18       ` Angel Olivera
  0 siblings, 1 reply; 8+ messages in thread
From: Peter Stephenson @ 2007-06-12 17:51 UTC (permalink / raw)
  To: zsh-users

Angel Olivera wrote:
> Now, for every prompt that is printed I get a new sched job queued.
> This might get as big as 3600 or more. Do you think that is going to
> be a serious performance penalty on my daily zsh routine?

That's because you're running the "sched" unconditionally to schedule
a new task, even if the function is called from precmd.  It would
definitely be better to avoid that.  You can delete any existing
scheduled job with something like:

sched | while read line; do
  if [[ $line = *clear-zle-screen* ]]; then
    sched -${line%% *}
  fi
done

(It would be nice if sched provided an array to access scheduled events
but it doesn't.  That's an easy tweak I may look at.)

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php

To get further information regarding CSR, please visit our Investor Relations page at http://ir.csr.com/csr/about/overview


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

* Re: Calling a zle widget from a function
  2007-06-12 17:51     ` Peter Stephenson
@ 2007-06-12 19:18       ` Angel Olivera
  0 siblings, 0 replies; 8+ messages in thread
From: Angel Olivera @ 2007-06-12 19:18 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 634 bytes --]

On Tue 12.Jun.07 18:51, Peter Stephenson wrote:
>You can delete any existing scheduled job with something like:
>
>sched | while read line; do
>  if [[ $line = *clear-zle-screen* ]]; then
>    sched -${line%% *}
>  fi
>done

Great, doing this in precmd works as expected.

>(It would be nice if sched provided an array to access scheduled events
>but it doesn't.  That's an easy tweak I may look at.)

Sure, that'd be nice to make the above code look much cleaner. I'm sure 
there'd be plenty of other uses for this array than just removing 
elements, too.

Thank you very much once again. Cheers.

-- 
redondos

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2007-06-12 19:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-12 14:44 Calling a zle widget from a function Angel Olivera
2007-06-12 15:14 ` Peter Stephenson
2007-06-12 16:23   ` Frank Terbeck
2007-06-12 16:53     ` Peter Stephenson
2007-06-12 17:38       ` Frank Terbeck
2007-06-12 17:32   ` Angel Olivera
2007-06-12 17:51     ` Peter Stephenson
2007-06-12 19:18       ` Angel Olivera

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).