diff --git a/internal/p10k.zsh b/internal/p10k.zsh index b3a725e..c0cf237 100644 --- a/internal/p10k.zsh +++ b/internal/p10k.zsh @@ -1,4 +1,4 @@ -if [[ $__p9k_sourced != 2 ]]; then +if [[ $__p9k_sourced != 3 ]]; then >&2 print -P "" >&2 print -P "[%F{1}ERROR%f]: Corrupted powerlevel10k installation." >&2 print -P "" @@ -51,6 +51,7 @@ fi source "${__p9k_root_dir}/internal/configure.zsh" source "${__p9k_root_dir}/internal/worker.zsh" +source "${__p9k_root_dir}/internal/parser.zsh" # For compatibility with Powerlevel9k. It's not recommended to use mnemonic color # names in the configuration except for colors 0-7 as these are standard. @@ -5842,386 +5843,6 @@ _p9k_init_params() { done } -typeset -grA __p9k_pb_cmd_skip=( - '}' 'always' # handled specially - '{' '' - '{' '' - '|' '' - '||' '' - '&' '' - '&&' '' - '|&' '' - '&!' '' - '&|' '' - ')' '' - '(' '' - '()' '' - '!' '' - ';' '' - 'if' '' - 'fi' '' - 'elif' '' - 'else' '' - 'then' '' - 'while' '' - 'until' '' - 'do' '' - 'done' '' - 'esac' '' - 'end' '' - 'coproc' '' - 'nocorrect' '' - 'noglob' '' - 'time' '' - '[[' '\]\]' - '((' '\)\)' - 'case' '\)|esac' - ';;' '\)|esac' - ';&' '\)|esac' - ';|' '\)|esac' - 'foreach' '\(*\)' -) - -typeset -grA __p9k_pb_precommand=( - '-' '' - 'builtin' '' - 'command' '' - 'exec' '-[^a]#[a]' - 'nohup' '' - 'setsid' '' - 'eatmydata' '' - 'catchsegv' '' - 'pkexec' '--user' - 'doas' '-[^aCu]#[acU]' - 'nice' '-[^n]#[n]|--adjustment' - 'stdbuf' '-[^ioe]#[ioe]|--(input|output|error)' - 'sudo' '-[^aghpuUCcrtT]#[aghpuUCcrtT]|--(close-from|group|host|prompt|role|type|other-user|command-timeout|user)' - 'ssh-agent' '-[^aEPt]#[aEPt]' -) - -typeset -grA __p9k_pb_redirect=( - '&>' '' - '>' '' - '>&' '' - '<' '' - '<&' '' - '<>' '' - '&>|' '' - '>|' '' - '&>>' '' - '>>' '' - '>>&' '' - '&>>|' '' - '>>|' '' - '<<<' '' -) - -typeset -grA __p9k_pb_term=( - '|' '' - '||' '' - ';' '' - '&' '' - '&&' '' - '|&' '' - '&!' '' - '&|' '' - ';;' '' - ';&' '' - ';|' '' - '(' '' - ')' '' - '()' '' # handled specially - '}' '' # handled specially -) - -typeset -grA __p9k_pb_term_skip=( - '(' '\)' - ';;' '\)|esac' - ';&' '\)|esac' - ';|' '\)|esac' -) - -# Usage: _p9k_parse_buffer [token-limit] -# -# Parses the specified command line buffer and pupulates array P9K_COMMANDS -# with commands from it. Terminates early and returns 1 if there are more -# tokens than the specified limit. -# -# Broken: -# -# --------------- -# : $(x) -# --------------- -# : `x` -# --------------- -# ${x/} -# --------------- -# - -- x -# --------------- -# command -p -p x -# --------------- -# * -# --------------- -# x=$y; $x -# --------------- -# alias x=y; y -# --------------- -# x < ]] || return 2 - - local rcquotes - [[ -o rcquotes ]] && rcquotes=rcquotes - - eval $__p9k_intro - setopt no_nomatch $rcquotes - - typeset -ga P9K_COMMANDS=() - - local -r id='(<->|[[:alpha:]_][[:IDENT:]]#)' - local -r var="\$$id|\${$id}|\"\$$id\"|\"\${$id}\"" - - local -i e ic c=${2:-'1 << 62'} - local skip n s r state cmd prev - local -a aln alp alf v - - if [[ -o interactive_comments ]]; then - ic=1 - local tokens=(${(Z+C+)1}) - else - local tokens=(${(z)1}) - fi - - { - while (( $#tokens )); do - (( e = $#state )) - - while (( $#tokens == alp[-1] )); do - aln[-1]=() - alp[-1]=() - if (( $#tokens == alf[-1] )); then - alf[-1]=() - (( e = 0 )) - fi - done - - while (( c-- > 0 )) || return; do - token=$tokens[1] - tokens[1]=() - if (( $+galiases[$token] )); then - (( $aln[(eI)p$token] )) && break - s=$galiases[$token] - n=p$token - elif (( e )); then - break - elif (( $+aliases[$token] )); then - (( $aln[(eI)p$token] )) && break - s=$aliases[$token] - n=p$token - elif [[ $token == ?*.?* ]] && (( $+saliases[${token##*.}] )); then - r=${token##*.} - (( $aln[(eI)s$r] )) && break - s=${saliases[$r]%% #} - n=s$r - else - break - fi - aln+=$n - alp+=$#tokens - [[ $s == *' ' ]] && alf+=$#tokens - (( ic )) && tokens[1,0]=(${(Z+C+)s}) || tokens[1,0]=(${(z)s}) - done - - case $token in - '<<'(|-)) - state=h - continue - ;; - *('`'|['<>=$']'(')*) - if [[ $token == ('`'[^'`']##'`'|'"`'[^'`']##'`"'|'$('[^')']##')'|'"$('[^')']##')"'|['<>=']'('[^')']##')') ]]; then - s=${${token##('"'|)(['$<>']|)?}%%?('"'|)} - (( ic )) && tokens+=(';' ${(Z+C+)s}) || tokens+=(';' ${(z)s}) - fi - ;; - esac - - case $state in - *r) - state[-1]= - continue - ;; - a) - if [[ $token == $skip ]]; then - if [[ $token == '{' ]]; then - P9K_COMMANDS+=$cmd - cmd= - state= - else - skip='{' - fi - continue - else - state=t - fi - ;& # fall through - t|p*) - if (( $+__p9k_pb_term[$token] )); then - if [[ $token == '()' ]]; then - state= - else - P9K_COMMANDS+=$cmd - if [[ $token == '}' ]]; then - state=a - skip=always - else - skip=$__p9k_pb_term_skip[$token] - state=${skip:+s} - fi - fi - cmd= - continue - elif [[ $state == t ]]; then - continue - elif [[ $state == *x ]]; then - if (( $+__p9k_pb_redirect[$token] )); then - prev= - state[-1]=r - continue - else - state[-1]= - fi - fi - ;; - s) - if [[ $token == $~skip ]]; then - state= - fi - continue - ;; - h) - while (( $#tokens )); do - (( e = ${tokens[(i)${(Q)token}]} )) - if [[ $tokens[e-1] == ';' && $tokens[e+1] == ';' ]]; then - tokens[1,e]=() - break - else - tokens[1,e]=() - fi - done - while (( $#alp && alp[-1] >= $#tokens )); do - aln[-1]=() - alp[-1]=() - done - state=t - continue - ;; - esac - - if (( $+__p9k_pb_redirect[${token#<0-255>}] )); then - state+=r - continue - fi - - if [[ $token == *'$'* ]]; then - if [[ $token == $~var ]]; then - n=${${token##[^[:IDENT:]]}%%[^[:IDENT:]]} - [[ $token == *'"' ]] && v=("${(P)n}") || v=(${(P)n}) - tokens[1,0]=(${(qq)v}) - continue - fi - fi - - case $state in - '') - if (( $+__p9k_pb_cmd_skip[$token] )); then - skip=$__p9k_pb_cmd_skip[$token] - [[ $token == '}' ]] && state=a || state=${skip:+s} - continue - fi - if [[ $token == *=* ]]; then - v=${(S)token/#(<->|([[:alpha:]_][[:IDENT:]]#(|'['*[^\\](\\\\)#']')))(|'+')=} - if (( $#v < $#token )); then - if [[ $v == '(' ]]; then - state=s - skip='\)' - fi - continue - fi - fi - : ${token::=${(Q)${~token}}} - ;; - p2) - if [[ -n $prev ]]; then - prev= - else - : ${token::=${(Q)${~token}}} - if [[ $token == '{'$~id'}' ]]; then - state=p2x - prev=$token - else - state=p - fi - continue - fi - ;& # fall through - p) - if [[ -n $prev ]]; then - token=$prev - prev= - else - : ${token::=${(Q)${~token}}} - case $token in - '{'$~id'}') prev=$token; state=px; continue;; - [^-]*) ;; - --) state=p1; continue;; - $~skip) state=p2; continue;; - *) continue;; - esac - fi - ;; - p1) - if [[ -n $prev ]]; then - token=$prev - prev= - else - : ${token::=${(Q)${~token}}} - if [[ $token == '{'$~id'}' ]]; then - state=p1x - prev=$token - continue - fi - fi - ;; - esac - - if (( $+__p9k_pb_precommand[$token] )); then - prev= - state=p - skip=$__p9k_pb_precommand[$token] - cmd+=$token$'\0' - else - state=t - [[ $token == ('(('*'))'|'`'*'`'|'$'*|['<>=']'('*')'|*$'\0'*) ]] || cmd+=$token$'\0' - fi - done - } always { - [[ $state == (px|p1x) ]] && cmd+=$prev - P9K_COMMANDS+=$cmd - P9K_COMMANDS=(${(u)P9K_COMMANDS%$'\0'}) - } -} - function _p9k_on_widget_zle-keymap-select() { __p9k_reset_state=2; } function _p9k_on_widget_overwrite-mode() { __p9k_reset_state=2; } function _p9k_on_widget_vi-replace() { __p9k_reset_state=2; } diff --git a/internal/parser.zsh b/internal/parser.zsh new file mode 100644 index 0000000..abaf9e0 --- /dev/null +++ b/internal/parser.zsh @@ -0,0 +1,379 @@ +typeset -grA __p9k_pb_cmd_skip=( + '}' 'always' # handled specially + '{' '' + '{' '' + '|' '' + '||' '' + '&' '' + '&&' '' + '|&' '' + '&!' '' + '&|' '' + ')' '' + '(' '' + '()' '' + '!' '' + ';' '' + 'if' '' + 'fi' '' + 'elif' '' + 'else' '' + 'then' '' + 'while' '' + 'until' '' + 'do' '' + 'done' '' + 'esac' '' + 'end' '' + 'coproc' '' + 'nocorrect' '' + 'noglob' '' + 'time' '' + '[[' '\]\]' + '((' '\)\)' + 'case' '\)|esac' + ';;' '\)|esac' + ';&' '\)|esac' + ';|' '\)|esac' + 'foreach' '\(*\)' +) + +typeset -grA __p9k_pb_precommand=( + '-' '' + 'builtin' '' + 'command' '' + 'exec' '-[^a]#[a]' + 'nohup' '' + 'setsid' '' + 'eatmydata' '' + 'catchsegv' '' + 'pkexec' '--user' + 'doas' '-[^aCu]#[acU]' + 'nice' '-[^n]#[n]|--adjustment' + 'stdbuf' '-[^ioe]#[ioe]|--(input|output|error)' + 'sudo' '-[^aghpuUCcrtT]#[aghpuUCcrtT]|--(close-from|group|host|prompt|role|type|other-user|command-timeout|user)' + 'ssh-agent' '-[^aEPt]#[aEPt]' +) + +typeset -grA __p9k_pb_redirect=( + '&>' '' + '>' '' + '>&' '' + '<' '' + '<&' '' + '<>' '' + '&>|' '' + '>|' '' + '&>>' '' + '>>' '' + '>>&' '' + '&>>|' '' + '>>|' '' + '<<<' '' +) + +typeset -grA __p9k_pb_term=( + '|' '' + '||' '' + ';' '' + '&' '' + '&&' '' + '|&' '' + '&!' '' + '&|' '' + ';;' '' + ';&' '' + ';|' '' + '(' '' + ')' '' + '()' '' # handled specially + '}' '' # handled specially +) + +typeset -grA __p9k_pb_term_skip=( + '(' '\)' + ';;' '\)|esac' + ';&' '\)|esac' + ';|' '\)|esac' +) + +# Usage: _p9k_parse_buffer [token-limit] +# +# Parses the specified command line buffer and pupulates array P9K_COMMANDS +# with commands from it. Terminates early and returns 1 if there are more +# tokens than the specified limit. +# +# Broken: +# +# --------------- +# : $(x) +# --------------- +# : `x` +# --------------- +# ${x/} +# --------------- +# - -- x +# --------------- +# command -p -p x +# --------------- +# * +# --------------- +# x=$y; $x +# --------------- +# alias x=y; y +# --------------- +# x < ]] || return 2 + + local rcquotes + [[ -o rcquotes ]] && rcquotes=rcquotes + + eval $__p9k_intro + setopt no_nomatch $rcquotes + + typeset -ga P9K_COMMANDS=() + + local -r id='(<->|[[:alpha:]_][[:IDENT:]]#)' + local -r var="\$$id|\${$id}|\"\$$id\"|\"\${$id}\"" + + local -i e ic c=${2:-'1 << 62'} + local skip n s r state cmd prev + local -a aln alp alf v + + if [[ -o interactive_comments ]]; then + ic=1 + local tokens=(${(Z+C+)1}) + else + local tokens=(${(z)1}) + fi + + { + while (( $#tokens )); do + (( e = $#state )) + + while (( $#tokens == alp[-1] )); do + aln[-1]=() + alp[-1]=() + if (( $#tokens == alf[-1] )); then + alf[-1]=() + (( e = 0 )) + fi + done + + while (( c-- > 0 )) || return; do + token=$tokens[1] + tokens[1]=() + if (( $+galiases[$token] )); then + (( $aln[(eI)p$token] )) && break + s=$galiases[$token] + n=p$token + elif (( e )); then + break + elif (( $+aliases[$token] )); then + (( $aln[(eI)p$token] )) && break + s=$aliases[$token] + n=p$token + elif [[ $token == ?*.?* ]] && (( $+saliases[${token##*.}] )); then + r=${token##*.} + (( $aln[(eI)s$r] )) && break + s=${saliases[$r]%% #} + n=s$r + else + break + fi + aln+=$n + alp+=$#tokens + [[ $s == *' ' ]] && alf+=$#tokens + (( ic )) && tokens[1,0]=(${(Z+C+)s}) || tokens[1,0]=(${(z)s}) + done + + case $token in + '<<'(|-)) + state=h + continue + ;; + *('`'|['<>=$']'(')*) + if [[ $token == ('`'[^'`']##'`'|'"`'[^'`']##'`"'|'$('[^')']##')'|'"$('[^')']##')"'|['<>=']'('[^')']##')') ]]; then + s=${${token##('"'|)(['$<>']|)?}%%?('"'|)} + (( ic )) && tokens+=(';' ${(Z+C+)s}) || tokens+=(';' ${(z)s}) + fi + ;; + esac + + case $state in + *r) + state[-1]= + continue + ;; + a) + if [[ $token == $skip ]]; then + if [[ $token == '{' ]]; then + P9K_COMMANDS+=$cmd + cmd= + state= + else + skip='{' + fi + continue + else + state=t + fi + ;& # fall through + t|p*) + if (( $+__p9k_pb_term[$token] )); then + if [[ $token == '()' ]]; then + state= + else + P9K_COMMANDS+=$cmd + if [[ $token == '}' ]]; then + state=a + skip=always + else + skip=$__p9k_pb_term_skip[$token] + state=${skip:+s} + fi + fi + cmd= + continue + elif [[ $state == t ]]; then + continue + elif [[ $state == *x ]]; then + if (( $+__p9k_pb_redirect[$token] )); then + prev= + state[-1]=r + continue + else + state[-1]= + fi + fi + ;; + s) + if [[ $token == $~skip ]]; then + state= + fi + continue + ;; + h) + while (( $#tokens )); do + (( e = ${tokens[(i)${(Q)token}]} )) + if [[ $tokens[e-1] == ';' && $tokens[e+1] == ';' ]]; then + tokens[1,e]=() + break + else + tokens[1,e]=() + fi + done + while (( $#alp && alp[-1] >= $#tokens )); do + aln[-1]=() + alp[-1]=() + done + state=t + continue + ;; + esac + + if (( $+__p9k_pb_redirect[${token#<0-255>}] )); then + state+=r + continue + fi + + if [[ $token == *'$'* ]]; then + if [[ $token == $~var ]]; then + n=${${token##[^[:IDENT:]]}%%[^[:IDENT:]]} + [[ $token == *'"' ]] && v=("${(P)n}") || v=(${(P)n}) + tokens[1,0]=(${(qq)v}) + continue + fi + fi + + case $state in + '') + if (( $+__p9k_pb_cmd_skip[$token] )); then + skip=$__p9k_pb_cmd_skip[$token] + [[ $token == '}' ]] && state=a || state=${skip:+s} + continue + fi + if [[ $token == *=* ]]; then + v=${(S)token/#(<->|([[:alpha:]_][[:IDENT:]]#(|'['*[^\\](\\\\)#']')))(|'+')=} + if (( $#v < $#token )); then + if [[ $v == '(' ]]; then + state=s + skip='\)' + fi + continue + fi + fi + : ${token::=${(Q)${~token}}} + ;; + p2) + if [[ -n $prev ]]; then + prev= + else + : ${token::=${(Q)${~token}}} + if [[ $token == '{'$~id'}' ]]; then + state=p2x + prev=$token + else + state=p + fi + continue + fi + ;& # fall through + p) + if [[ -n $prev ]]; then + token=$prev + prev= + else + : ${token::=${(Q)${~token}}} + case $token in + '{'$~id'}') prev=$token; state=px; continue;; + [^-]*) ;; + --) state=p1; continue;; + $~skip) state=p2; continue;; + *) continue;; + esac + fi + ;; + p1) + if [[ -n $prev ]]; then + token=$prev + prev= + else + : ${token::=${(Q)${~token}}} + if [[ $token == '{'$~id'}' ]]; then + state=p1x + prev=$token + continue + fi + fi + ;; + esac + + if (( $+__p9k_pb_precommand[$token] )); then + prev= + state=p + skip=$__p9k_pb_precommand[$token] + cmd+=$token$'\0' + else + state=t + [[ $token == ('(('*'))'|'`'*'`'|'$'*|['<>=']'('*')'|*$'\0'*) ]] || cmd+=$token$'\0' + fi + done + } always { + [[ $state == (px|p1x) ]] && cmd+=$prev + P9K_COMMANDS+=$cmd + P9K_COMMANDS=(${(u)P9K_COMMANDS%$'\0'}) + } +} diff --git a/powerlevel10k.zsh-theme b/powerlevel10k.zsh-theme index 6069543..c81da2f 100644 --- a/powerlevel10k.zsh-theme +++ b/powerlevel10k.zsh-theme @@ -35,10 +35,10 @@ if [[ $__p9k_dump_file != $__p9k_instant_prompt_dump_file ]] && (( ! $+functions[_p9k_preinit] )) && source $__p9k_dump_file 2>/dev/null && (( $+functions[_p9k_preinit] )); then _p9k_preinit fi - typeset -gr __p9k_sourced=2 + typeset -gr __p9k_sourced=3 if [[ -w $__p9k_root_dir && -w $__p9k_root_dir/internal && -w $__p9k_root_dir/gitstatus && ${(%):-%#} == % ]]; then local f - for f in $__p9k_root_dir/{powerlevel9k.zsh-theme,powerlevel10k.zsh-theme,internal/p10k.zsh,internal/icons.zsh,internal/configure.zsh,internal/worker.zsh,gitstatus/gitstatus.plugin.zsh}; do + for f in $__p9k_root_dir/{powerlevel9k.zsh-theme,powerlevel10k.zsh-theme,internal/p10k.zsh,internal/icons.zsh,internal/configure.zsh,internal/worker.zsh,internal/parser.zsh,gitstatus/gitstatus.plugin.zsh}; do [[ $f.zwc -nt $f ]] || zcompile $f done fi