Skip to content

Instantly share code, notes, and snippets.

@toomasv
Last active September 25, 2020 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toomasv/4b4d46eb90eb2814bc79e7bb4084f04f to your computer and use it in GitHub Desktop.
Save toomasv/4b4d46eb90eb2814bc79e7bb4084f04f to your computer and use it in GitHub Desktop.
`replace` extended with `/only` refinement
Red [
Description: "`replace` extended with `/only` refinement"
Date: 24-Sep-2020
]
replace: func ["Replaces values in a series, in place"
series [series!] "The series to be modified"
pattern "Specific value or parse rule pattern to match"
value "New value, replaces pattern in the series"
/all "Replace all occurrences, not just the first"
/deep "Replace pattern in all sub-lists as well"
/case "Case-sensitive replacement"
/only "Pattern is replaced with value as single series"
/local p rule s e many? len pos do-parse do-find do-change do-change2 do-insert
][
do-parse: pick [parse/case parse] case
do-insert: pick [insert/only insert] only
do-change: pick [change/part/only change/part] only
if system/words/all [deep any-list? series] [
pattern: to block! either word? pattern [to lit-word! pattern] [pattern]
do compose/deep [
(do-parse) series rule: [
some [
s: pattern e: (
to-paren compose [
s: (do-change) s value e
unless all [return series]
]
) :s
| ahead any-list! into rule | skip
]
]
]
return series
]
if system/words/all [
any [not any-string? :pattern tag? :pattern]
any-string? series
not block? :pattern
not bitset? :pattern
] [
pattern: form pattern
]
either system/words/all [any-string? :series block? :pattern] [
do-change2: pick [[change only][change]] only
p: compose [to pattern (do-change2) pattern (quote (value))]
do compose [(do-parse) series either all [[some p]] [p]]
] [
many?: any [
system/words/all [series? :pattern any-string? series]
binary? series
system/words/all [any-list? series any-list? :pattern]
]
len: either many? [length? pattern] [1]
do-find: pick [find/case find] case
either all [
pos: series
either many? [
while [pos: do compose [(do-find) pos pattern]] [
pos: do compose [(do-change) pos value len]
]
] [
while [pos: do compose [(do-find) pos :pattern]] [
pos: do compose [(do-insert) remove pos value]
]
]
] [
if pos: do compose [(do-find) series :pattern] [
do compose [(do-change) pos value len]
]
]
]
series
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment