-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathza-pull-handler
More file actions
executable file
·178 lines (158 loc) · 6.98 KB
/
Copy pathza-pull-handler
File metadata and controls
executable file
·178 lines (158 loc) · 6.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env zsh
# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# Copyright (c) 2022 Sebastian Gniazdowski
# Set the base and typically useful options
emulate -LR zsh
setopt extendedglob warncreateglobal typesetsilent noshortloops rcquotes ${${options[xtrace]:#off}:+xtrace}
typeset -gA Plugins
# Default pull url used to pull from when not given
: ${ZINIT[pull-def-url]:=https://github.com/zdharma-continuum/zinit/wiki/Github-Binary-Recipes}
# A support for running the function as script, ./za-pull-handler pull {url} {object id}
if [[ $0 != za-pull-handler || -n $ZSH_SCRIPT ]]; then
# Handle $0 according to the Zsh Plugin Standard:
# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
0=${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}
0=${${(M)0##/*}:-$PWD/$0}
Plugins[PULL_DIR]=${0:h}
fi
# Such global variable is expected to be typeset'd -g in the plugin.zsh
# file. Here it's restored in case of the function being run as a script.
Plugins[PULL_TMP]=$(mktemp)
local url=$2 obj
typeset -F3 SECONDS=0
local tmp=$Plugins[PULL_TMP] line
local -a lines
# Skip the "pull" command word from argument list
shift 1
# Handle default URL – the "Github Binary Recipes" wiki page
if [[ $url != ((http|ftp)(s|)|ssh|file)://* ]]; then
url=$ZINIT[pull-def-url]
+zinit-message "Using {ehi}GitHub Binary Recipes{rst} wiki page ({url}$url{rst}) as no other URL given"
else
shift 1
fi
# Handle default object query – *
if (( $# == 0 )); then
+zinit-message "Grepping for {ehi}all{rst} objects as no object pattern given"
set -- "*"
fi
# Download the file using wget, curl, etc.
# using function from zinit-install.zsh
#wget $url -O $tmp &>/dev/null
source $ZINIT[BIN_DIR]/zinit-install.zsh
.zinit-download-file-stdout $url >! $tmp
# Strip tags, etc.
local file=$(<$tmp)
# Most time consuming part – replaced with `sed`
#local -A map=( "<" "<" ">" ">" )
#print -r -- ${file//(<[^>]#>|\<\;|\>\;)/$map[$match[1]]} >! $tmp-
tr '\n' '\f' < $tmp | sed -r -e 's/<[^>]*>//gi' -e 's/\&\s*lt\s*\;\s*/</gi' -e 's/\&\s*gt\;\s*/>/gi' -e 's/\&\s*quot\s*;/"/gi' -e "s/&\s*amp\s*;/'/gi" | \
tr '\f' '\n' > $tmp-
+zinit-message "{auto}Preprocessing finished after: ${SECONDS}s"
lines=( ${(f@)"$(<$tmp-)"} )
integer next
local bit exts="${(j:|:)${(@)${(@Akons:|:)${ZINIT_EXTS[ice-mods]//\'\'/}}/(#s)<->-/}}"
local -a selected reply
.pull-add-object() {
local id=$1 line=$2
id=${id//\//---}
#print $line >! $ZINIT[OBJECTS_DIR]/$id
print -- \\n$line >> ~/.zshrc
+zinit-message "{auto}Object $id successfully added"
}
# Swipes all input lines with patterns that detect `for`-syntax and
# zinit light/load/snippet/ice commands and return the `for` syntax
# command that uniformly loads all found objects with their ices,
# global and private ones
.pull-get-object-with-ices-from-lines() {
local -a prevmatch
local searched=$1 line realline prevline ices
shift
reply=()
searched=${searched//\*/[[:alnum:].,:_\\+/@-]#}
for line; do
line=${(j+ +)${${(Z+Cn+@)line}//(#m)([$' \t'])/$'\ua0'}}
realline+=${line%%\\##}
# TODO: recognize quoting
if [[ $line == *\\ || $line == *\' && ( $line[1,-2] == [^\']#\'[^\']#\'[^\']# || $line[1,-2] == [^\']#\'[^\']#\'[^\']#\'[^\']#\'[^\']# || $line[1,-2] == [^\']## ) ]]; then
continue
fi
# An interesting trick is being utilized – use
# of the secondary, doubling negation of Zsh patterns,
# which are being groundbreaking yet unknown extension
# to regular expressions – after the token, the one
# marked with unneded "*", there is the "repel" negation:
# "~((${ZINIT[..." which repels, blocks all values
# specified in it, allowing to prevent the parenthesis
# from matching *local* ices of the object (snippet or
# plugin).
if [[ $realline = ([[:space:]]##|(#s))(#b)(zi(#B)(|nit)[$' \t']##((--|)(${~ZINIT[ice-list]}${~exts})([^$' \t']#)[$' \t']##)#)\
for(#B)([$' \t']##((--|)(${~ZINIT[ice-list]}${~exts})([^$' \t']#)[$' \t']##)#\
([^$' \t'*]##~((${~ZINIT[ice-list]}${~exts})([^$' \t']#))))#\
([$' \t']##(#b)((#B)((--|)(${~ZINIT[ice-list]}${~exts})([^$' \t']#)[$' \t']##)##)\
(#b)($~searched))(#B)([$' \t']##((--|)(${~ZINIT[ice-list]}${~exts})[^$' \t']#[$' \t']##)#\
[^$' \t']##)#* ]]; then
# 1. Trim leading and trailing whitespace
# 2. Restore proper spaces over the non-breaking ones
match=( "${(@)${(@)${(@)${match[@]%%[$' \t']##}##[$' \t']##}//$'\ua0'/ }//\\[[:space:]]#(#e)}" )
reply+=( "$match[1] $match[2] for $match[3]" "$match[3]")
elif [[ $realline == ([[:space:]]##|(#s))(#b)zi(|nit)[[:space:]]##\
(load|light|snippet)[[:space:]]##($~searched)(\#*|) ]]; then
match=( "${(@)${(@)${(@)${match[@]%%[$' \t']##}##[$' \t']##}//$'\ua0'/ }//\\[[:space:]]#(#e)}" )
prevmatch=( $match )
ices=
if [[ $prevline == ([[:space:]]##|(#s))(#b)zi(|nit)[[:space:]]##\
ice[[:space:]]##(*) ]]; then
match=( "${(@)${(@)${(@)${match[@]%%[$' \t']##}##[$' \t']##}//$'\ua0'/ }//\\[[:space:]]#(#e)}" )
ices=$match[2]
fi
# Ensure snippet, if needed
if [[ $prevmatch[2] == snippet ]]; then
if [[ $prevmatch[3] != (((http|ftp)(s|)|ssh|file)://|OMZ[A-Z]#:|PZT[A-Z]#:)* ]]; then
ices+=${ices:+ }is-snippet
fi
# Or, ensure plugin, if needed
else
if [[ $prevmatch[3] == (((http|ftp)(s|)|ssh|file)://|OMZ[A-Z]#:|PZT[A-Z]#:)* ]]; then
ices+=${ices:+ }is-plugin
fi
fi
# Save result
reply+=( "zinit $ices${ices:+ }for $prevmatch[3]" "$prevmatch[3]" )
fi
# Handle previous line variable - store it
if [[ $realline == ([[:space:]]##|(#s))zi(nit)[[:space:]]##ice[[:space:]]##* ]]; then
prevline=$realline
fi
# Or clear it, if needed
if [[ $realline == ([[:space:]]##|(#s))zi(nit)[[:space:]]##(load|light|snippet)[[:space:]]##* ]]; then
prevline=
fi
# Clearing of realline
realline=
done
}
SECONDS=0
integer count
local answer id
# For every object query swipe all input lines looking for it,
# and ask question whether the found object should be addded
# to zshrc
for obj; do
.pull-get-object-with-ices-from-lines $obj $lines
+zinit-message "{auto}Swipe finished in ${SECONDS}s"
selected=( $reply )
+zinit-message "Found {num}$(($#reply/2)) {rst}objects{ehi}:"
for line id in $selected; do
(( count ++ ))
+zinit-message "{nl}{auto}Object $id ($count): $line"
+zinit-message "Add ($count) to the load configuration? (y/n)"
read -qs answer
if [[ $answer == y ]]; then
.pull-add-object $id $line
fi
done
done
# Final timing message
+zinit-message "{auto}Operation finished in ${SECONDS}s"
# vim:ft=zsh:tw=80:sw=4:sts=4:et:foldmarker=[[[,]]]