zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <okiddle@yahoo.co.uk>
To: zsh workers <zsh-workers@zsh.org>
Subject: Re: PATCH: _ps1234, _date_formats: Complete strftime formats for %D{}
Date: Thu, 09 Jul 2015 14:17:57 +0200	[thread overview]
Message-ID: <21764.1436444277@thecus.kiddle.eu> (raw)
In-Reply-To: <CAHYJk3R267MFUk0qqh3ftQ_1U3=c0Ekqztk5_CCcqD5mttfo+w@mail.gmail.com>

Mikael Magnusson wrote:
> 
> I've also just noticed that completion after %D\{%\# and \^ doesn't
> work, but single-quoted is fine.

That's the fault of _ps1234.

It's best to use compset -P and get to a point where _date_formats is
called with $PREFIX only containing date formats and no prompt stuff.

I finally worked out that the point of calling _default from _ps1234 is
for print -P. That's _print's job to do that.

This patch also fixes and improves other things like the positioning of
numeric arguments for ternary expressions.

> >>  Completion/Unix/Type/_ps1234       | 14 +++++--
> > Shouldn't this be in Completion/Zsh/Type?
> Possibly, but I figured we could use it for _date too?

I meant _ps1234 not _date_formats. I'll move it when applying this
patch.

Oliver

diff --git a/Completion/Unix/Type/_ps1234 b/Completion/Unix/Type/_ps1234
index b9e5166..8d3c5d8 100644
--- a/Completion/Unix/Type/_ps1234
+++ b/Completion/Unix/Type/_ps1234
@@ -1,82 +1,58 @@
 #compdef -value-,PROMPT,-default- -value-,PROMPT2,-default- -value-,PROMPT3,-default- -value-,PROMPT4,-default- -value-,RPROMPT,-default- -value-,RPROMPT2,-default- -value-,PS1,-default- -value-,PS2,-default- -value-,PS3,-default- -value-,PS4,-default- -value-,RPS1,-default- -value-,RPS2,-default- -value-,SPROMPT,-default-
 
 local -a specs
-local expl bs
+local expl bs suf pre changed=1 ret=1
 
 if [[ -z $compstate[quote] ]]; then
-  bs='\'
+  bs='\' # in patterns we use (\\|) widely as print -P handles backslashes first
 fi
 
-if [[ $PREFIX == *%D$bs\{[^($bs\})]# ]]; then
-  _date_formats zsh
-elif [[ $PREFIX == *%(-|)<-># ]]; then
+# first strip off any complete prompt specifications leaving only the
+# current, incomplete, one
+while (( changed )); do
+  changed=0
+  compset -P '%[DFK](\\|){[^}]#}' && changed=1 # formats with arg: %x{...}
+  compset -P '%[0-9-\\]#[^DFK(0-9-<>\\\[]' && changed=1 # normal formats
+  compset -P '%[0-9-\\]#(<[^<]#<|>[^>]#>|\[[^\]]#\])' && changed=1 # truncations
+  compset -P '%[0-9-\\]#(\\|)\(??|[^%]' && changed=1 # start of ternary
+  compset -P '[^%]##' && changed=1 # sundry other characters
+  # %D/%F/%K without a following { ... }
+  [[ $PREFIX = %(-|)<->#[DFK](\\|)[^{\\]* ]] &&
+      compset -P '%[0-9\\-]#[DFK]' && changed=1
+done
+[[ $PREFIX = %(-|)<->[FK](#e) ]] && compset -P '*' # F/K with number
+
+if compset -P '%[FK]'; then
+  # this should use -P but that somehow causes single quotes to be stripped
+  compset -P '(\\|){' || pre=( -p "$bs{" )
+  compset -S '(\\|)}*' || suf=( -S $bs\} )
   specs=(
-    'm:hostname up to first .'
-    '_:status of parser'
-    'd:current working directory'
-    '/:current working directory'
-    '~:current working directory, with ~ replacement'
-    'N:name of current script or shell function'
-    'x:name of file containing code being executed'
-    'c:deprecated'
-    '.:deprecated'
-    'C:deprecated'
-    'F:start using fg color'
-    'K:start using bg color'
-    'G:counts as extra character inside %{...%}'
+    black
+    red
+    green
+    yellow
+    blue
+    magenta
+    cyan
+    white
+    default
   )
-  if [[ $PREFIX == *% ]]; then
-    if [[ $service == -value-,SPROMPT,* ]]; then
-      specs+=(
-      'r:suggested correction'
-      'R:corrected string'
-      )
-    fi
-    specs+=(
-    '%:A %'
-    '):A )'
-    'l:current line (tty) with /dev/tty stripped'
-    'M:full hostname'
-    'n:username'
-    'y:current line (tty)'
-    '#:a # when root, % otherwise'
-    '?:return status of last command'
-    'h:current history event number'
-    '!:current history event number'
-    'i:current line number'
-    'I:current source line number'
-    'j:number of jobs'
-    'L:$SHLVL'
-    'D:date in yy-mm-dd format'
-    'T:current time of day, 24-hour format'
-    't:current time of day, 12-hour am/pm format'
-    '@:current time of day, 12-hour am/pm format'
-    '*:current time of day, 24-hour format with seconds'
-    'w:the date in day-dd format'
-    'W:the date in mm/dd/yy format'
-    'D{:format string like strftime'
-    'B:start bold'
-    'b:stop bold'
-    'E:clear to end of line'
-    'U:start underline'
-    'u:stop underline'
-    'S:start standout'
-    's:stop standout'
-    'f:reset fg color'
-    'k:reset bg color'
-    '{:start literal escape sequence'
-    '}:stop literal escape sequence'
-    'v:value from $psvar array'
-    '(:ternary expression %(x.true-string.false-string)'
-    '<<:truncation from left %len<string<'
-    '>>:truncation from right %len>string>'
-    '[]:truncation from who knows where'
-    )
+  _wanted ansi-colors expl 'ansi color' compadd $suf $pre -a specs && ret=0
+  if (( $#suf )) && compset -P "<->"; then
+    _wanted ansi-colors expl 'closing brace' compadd -S '' \} && ret=0
+  else
+    _message -e terminal-colors "number between 0 and $(( $terminfo[colors] - 1 ))"
   fi
-  compset -P "*"
-  _describe -t prompt-format-specifier 'prompt format specifier' specs -S ''
-  _message -e prompt-format-specifier number
-elif [[ $PREFIX == *%$bs\((-|)<-># ]]; then
+fi
+
+if compset -P '%[0-9-\\]#\(?'; then
+  compset -S '*'
+  _delimiters && ret=0
+elif compset -P '%[0-9-\\]#[<>\]]'; then
+  _message -e replacements 'replacement string'
+elif compset -P '%[0-9-\\]#(\\|)\('; then
+  compset -S '[.:+/-%]*' || suf=( -S . )
+  compset -S '*'
   specs=(
     '!:running with privileges'
     '#:effective uid'
@@ -100,35 +76,82 @@ elif [[ $PREFIX == *%$bs\((-|)<-># ]]; then
     'V:element n of psvar is set and non-empty'
     'w:day of week (Sunday = 0)'
   )
-  compset -P "*"
-  _describe -t ternary-prompt-expression 'ternary prompt format test character' specs -S ''
-  _message -e ternary-prompt-expression number
-elif [[ $PREFIX == *%[FK]$bs\{[0-9a-z]# ]]; then
+  _describe -t ternary-prompt-expressions 'ternary prompt format test character' specs $suf && ret=0
+elif compset -P '%D(\\|){'; then
+  compset -S '(\\|)}*'
+  _date_formats zsh && ret=0
+elif [[ -prefix '%' ]] ||
+      ! zstyle -t ":completion:${curcontext}:prompt-format-specifiers" prefix-needed
+then
   specs=(
-    black
-    red
-    green
-    yellow
-    blue
-    magenta
-    cyan
-    white
-    default
+    'm:hostname up to first .'
+    '_:status of parser'
+    '^:reversed status of parser'
+    'd:current working directory'
+    '/:current working directory'
+    '~:current working directory, with ~ replacement'
+    'N:name of current script or shell function'
+    'x:name of file containing code being executed'
+    'c:deprecated'
+    '.:deprecated'
+    'C:deprecated'
+    'F:start using fg color'
+    'K:start using bg color'
+    'G:counts as extra character inside %{...%}'
+    '(:ternary expression %(x.true-string.false-string)'
   )
-  compset -P "*{"
-  _describe -t ansi-color-name 'ansi color' specs -S $bs\}
-  if compset -P "<->"; then
-    _wanted ansi-color-number expl 'close brace' compadd -S '' \}
-  else
-    _message -e ansi-color-number "number between 0 and $(( $terminfo[colors] - 1 ))"
-  fi
-else
-  _default "$@"
-  specs=(%)
-  if compset -P "*%D"; then
-    specs+=(\{)
-  else
-    compset -P "*"
+  compset -P '%' || pre=( -p '%' )
+  if ! compset -P '(-|)<->'; then
+    if [[ $service == -value-,SPROMPT,* ]]; then
+      specs+=(
+	'r:suggested correction'
+	'R:corrected string'
+      )
+    fi
+    specs+=(
+      '%:A %'
+      '):A )'
+      'l:current line (tty) with /dev/tty stripped'
+      'M:full hostname'
+      'n:username'
+      'y:current line (tty)'
+      '#:a # when root, % otherwise'
+      '?:return status of last command'
+      'h:current history event number'
+      '!:current history event number'
+      'i:current line number'
+      'I:current source line number'
+      'j:number of jobs'
+      'L:$SHLVL'
+      'D:date in yy-mm-dd format'
+      'T:current time of day, 24-hour format'
+      't:current time of day, 12-hour am/pm format'
+      '@:current time of day, 12-hour am/pm format'
+      '*:current time of day, 24-hour format with seconds'
+      'w:the date in day-dd format'
+      'W:the date in mm/dd/yy format'
+      'D{:format string like strftime'
+      'B:start bold'
+      'b:stop bold'
+      'E:clear to end of line'
+      'U:start underline'
+      'u:stop underline'
+      'S:start standout'
+      's:stop standout'
+      'f:reset fg color'
+      'k:reset bg color'
+      '{:start literal escape sequence'
+      '}:stop literal escape sequence'
+      'v:value from $psvar array'
+      '<:truncation from left %len<string<'
+      '>:truncation from right %len>string>'
+      '[:truncation from who knows where'
+    )
   fi
-  _describe -t prompt-format-specifier 'prompt format specifier' specs -S ''
+  _describe -t prompt-format-specifiers 'prompt format specifier' \
+      specs -S '' $pre && ret=0
+  (( ! $#pre )) && [[ -prefix '(-|)<->' ]] &&
+      _message -e prompt-format-specifiers number
 fi
+
+return ret
diff --git a/Completion/Zsh/Command/_print b/Completion/Zsh/Command/_print
index 4053933..1eba13e 100644
--- a/Completion/Zsh/Command/_print
+++ b/Completion/Zsh/Command/_print
@@ -11,7 +11,7 @@ if [[ $service = print ]]; then
     pflag='(-s -u -z)-p[print arguments to input of coprocess]'
 
   if [[ -n ${words[1,CURRENT][(r)-*P*]} ]]; then
-    rest='*: :_ps1234'
+    rest='*: :->prompt'
   else
     rest='*: :_default'
   fi
@@ -48,16 +48,17 @@ if [[ $state = printf ]]; then
 fi
 
 if [[ $state = printfformat ]]; then
-  if [[ ${(Q)PREFIX} = *%((-|)<->|[-#0 +*.])# ]]; then
+  if [[ ${(Q)PREFIX} = *%[0-9\$#\ +*.\'-]# ]]; then
     local -a specs
       specs=(
         '#:alternate form'
-        '0:zeropad to length n'
+        '0:zero pad to length'
         '-:left adjust result'
         ' :leave one space in front of positive number from signed conversion'
         '+:always place sign before a number from signed conversion'
         '*:field width in next argument'
         '.:precision'
+	"':thousand separators"
         'c:print the first character of the argument'
         's:print the argument as a string'
         {d,i}':signed decimal number or with leading " numeric value of following character'
@@ -73,12 +74,16 @@ if [[ $state = printfformat ]]; then
         'q:as %s but shell quote result'
       )
     compset -P "*"
-    _describe -t print-format-specifier 'print format specifier' specs -S ''
-    _message -e print-format-specifier 'number'
+    _describe -t print-format-specifiers 'print format specifier' specs -S ''
+    _message -e print-format-specifiers 'number'
   else
-    _describe -t print-format-specifier 'print format specifier' '(%)' -S ''
+    _wanted print-format-specifiers expl 'print format specifier' compadd -S '' %
   fi
   ret=0
+elif [[ $state = prompt ]]; then
+  _default && ret=0
+  # complete prompt specifiers without interfering too much with default completion
+  (( $#compstate[unambiguous] <= $#PREFIX || ! $#PREFIX )) && _ps1234 && ret=0
 fi
 
 return ret


  reply	other threads:[~2015-07-09 12:24 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-06  0:36 Mikael Magnusson
2015-07-06 11:11 ` Oliver Kiddle
2015-07-06 14:17   ` Mikael Magnusson
2015-07-06 14:56     ` Mikael Magnusson
2015-07-08 14:02   ` Jun T.
2015-07-08 14:42     ` Mikael Magnusson
2015-07-09 12:17       ` Oliver Kiddle [this message]
2015-07-09 13:25         ` Mikael Magnusson
2015-07-09 13:53         ` Mikael Magnusson
2015-07-09 15:20           ` Oliver Kiddle
2015-07-09 23:02             ` Oliver Kiddle
2015-07-09 12:22     ` Oliver Kiddle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21764.1436444277@thecus.kiddle.eu \
    --to=okiddle@yahoo.co.uk \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).