Skip to content

Commit 1f5c1a2

Browse files
committed
Major updates in functionality
1 parent 167b164 commit 1f5c1a2

File tree

1 file changed

+100
-69
lines changed
  • stdlib-candidate/std-rfc/kv

1 file changed

+100
-69
lines changed

stdlib-candidate/std-rfc/kv/mod.nu

Lines changed: 100 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ export def "kv set" [
2727
key: string
2828
value_or_closure?: any
2929
--return (-r): string # Whether and what to return to the pipeline output
30+
--universal (-u)
3031
] {
3132
# Pipeline input is preferred, but prioritize
3233
# parameter if present. This allows $in to be
3334
# used in the parameter if needed.
3435
let input = $in
3536

37+
# If passed a closure, execute it
3638
let arg_type = ($value_or_closure | describe)
3739
let value = match $arg_type {
3840
closure => { $input | do $value_or_closure }
@@ -41,63 +43,56 @@ export def "kv set" [
4143

4244
# Store values as nuons for type-integrity
4345
let kv_pair = {
46+
session: '' # Placeholder
4447
key: $key
4548
value: ($value | to nuon)
4649
}
4750

48-
# Create the table if it doesn't exist
51+
let db_open = (db_setup --universal=$universal)
4952
try {
50-
stor create -t std_kv_store -c {key: str, value: str} | ignore
53+
# Delete the existing key if it does exist
54+
do $db_open | query db $"DELETE FROM std_kv_store WHERE key = '($key)'"
5155
}
5256

53-
# Does the key exist yet?
54-
let key_exists = ( $key in (stor open | $in.std_kv_store?.key?))
55-
56-
# If so, we need an update rather than an insert
57-
let stor_action = match $key_exists {
58-
true => {{stor update -t std_kv_store --where-clause $"key = '($key)'"}}
59-
false => {{stor insert -t std_kv_store}}
57+
match $universal {
58+
true => { $kv_pair | into sqlite (universal_db_path) -t std_kv_store }
59+
false => { $kv_pair | stor insert -t std_kv_store }
6060
}
6161

62-
# Execute the update-or-insert action
63-
$kv_pair | do $stor_action
64-
65-
# Returns the kv table itself in case it's
66-
# useful in the pipeline
67-
match ($return | default 'value') {
68-
'all' => (kv list)
69-
'a' => (kv list)
62+
# The value that should be returned from `kv set`
63+
# By default, this is the input to `kv set`, even if
64+
# overridden by a positional parameter.
65+
# This can also be:
66+
# input: (Default) The pipeline input to `kv set`, even if
67+
# overridden by a positional parameter. `null` if no
68+
# pipeline input was used.
69+
# ---
70+
# value: If a positional parameter was used for the value, then
71+
# return it, otherwise return the input (whatever was set).
72+
# If the positional was a closure, return the result of the
73+
# closure on the pipeline input.
74+
# ---
75+
# all: The entire contents of the existing kv table are returned
76+
match ($return | default 'input') {
77+
'all' => (kv list --universal=$universal)
78+
'a' => (kv list --universal=$universal)
7079
'value' => $value
7180
'v' => $value
7281
'input' => $input
7382
'in' => $input
74-
'ignore' => null
75-
'i' => null
83+
'i' => $input
7684
_ => {
7785
error make {
7886
msg: "Invalid --return option"
7987
label: {
80-
text: "Must be 'all'/'a', 'value'/'v', 'input'/'in', or 'ignore'/'i'"
88+
text: "Must be 'all'/'a', 'value'/'v', or 'input'/'in'/'i'"
8189
span: (metadata $return).span
8290
}
8391
}
8492
}
8593
}
8694
}
8795

88-
def kv_key_completions [] {
89-
try {
90-
stor open
91-
# Hack to turn a SQLiteDatabase into a table
92-
| $in.std_kv_store | wrap temp | get temp
93-
| get key?
94-
} catch {
95-
# Return no completions
96-
[]
97-
}
98-
99-
}
100-
10196
# Retrieves a stored value by key
10297
#
10398
# Counterpart of "kv set". Returns null
@@ -106,18 +101,16 @@ def kv_key_completions [] {
106101
# Usage:
107102
# kv get <key> | <pipeline>
108103
export def "kv get" [
109-
key: string@kv_key_completions # Key of the kv-pair to retrieve
104+
key: string # Key of the kv-pair to retrieve
105+
--universal (-u)
110106
] {
111-
try {
112-
stor create -t std_kv_store -c {key: str, value: str} | ignore
113-
}
114-
115-
stor open
107+
let db_open = (db_setup --universal=$universal)
108+
do $db_open
116109
# Hack to turn a SQLiteDatabase into a table
117110
| $in.std_kv_store | wrap temp | get temp
118111
| where key == $key
119112
# Should only be one occurence of each key in the stor
120-
| get -i value | first
113+
| get -i value.0
121114
| match $in {
122115
# Key not found
123116
null => null
@@ -130,13 +123,12 @@ export def "kv get" [
130123
#
131124
# Returns results as the Nushell value rather
132125
# than the stored nuon.
133-
export def "kv list" [] {
134-
# Create the table if it doesn't exist
135-
try {
136-
stor create -t std_kv_store -c {key: str, value: str} | ignore
137-
}
126+
export def "kv list" [
127+
--universal (-u)
128+
] {
129+
let db_open = (db_setup --universal=$universal)
138130

139-
stor open | $in.std_kv_store | each {|kv_pair|
131+
do $db_open | $in.std_kv_store? | each {|kv_pair|
140132
{
141133
key: $kv_pair.key
142134
value: ($kv_pair.value | from nuon )
@@ -145,35 +137,74 @@ export def "kv list" [] {
145137
}
146138

147139
# Returns and removes a key-value pair
148-
export def "kv drop" [
149-
key: string@kv_key_completions # Key of the kv-pair to drop
140+
export def --env "kv drop" [
141+
key: string # Key of the kv-pair to drop
142+
--universal (-u)
150143
] {
151-
# Create the table if it doesn't exist
144+
let db_open = (db_setup --universal=$universal)
145+
146+
let value = (kv get --universal=$universal $key)
147+
152148
try {
153-
stor create -t std_kv_store -c {key: str, value: str} | ignore
149+
do $db_open
150+
# Hack to turn a SQLiteDatabase into a table
151+
| query db $"DELETE FROM std_kv_store WHERE key = '($key)'"
152+
}
153+
154+
if $universal and $env.NU_KV_UNIVERSALS? {
155+
hide-env $key
154156
}
155157

158+
$value
159+
}
160+
161+
def universal_db_path [] {
162+
$env.NU_UNIVERSAL_KV_PATH?
163+
| default (
164+
$nu.data-dir | path join "std_kv_variables.sqlite3"
165+
)
166+
}
167+
168+
def db_setup [
169+
--universal
170+
] : nothing -> closure {
156171
try {
157-
stor open
158-
# Hack to turn a SQLiteDatabase into a table
159-
| $in.std_kv_store | wrap temp | get temp
160-
| where key == $key
161-
# Should only be one occurrence of each key in the stor
162-
| get -i value | first
163-
| match $in {
164-
# Key not found
165-
null => null
166-
167-
# Key found
168-
_ => {
169-
let value = $in
170-
stor delete --table-name std_kv_store --where-clause $"key = '($key)'"
171-
$value | from nuon
172+
match $universal {
173+
true => {
174+
# Ensure universal sqlite db and table exists
175+
let uuid = (random uuid)
176+
let dummy_record = {
177+
session: ''
178+
key: $uuid
179+
value: ''
172180
}
181+
$dummy_record | into sqlite (universal_db_path) -t std_kv_store
182+
open (universal_db_path) | query db $"DELETE FROM std_kv_store WHERE key = '($uuid)'"
183+
}
184+
false => {
185+
# Create the stor table if it doesn't exist
186+
stor create -t std_kv_store -c {session: str, key: str, value: str} | ignore
187+
}
173188
}
189+
}
174190

175-
} catch {
176-
# If value not found or other error, don't return anything
177-
null
191+
# Return the correct closure for opening on-disk vs. in-memory
192+
match $universal {
193+
true => {|| {|| open (universal_db_path)}}
194+
false => {|| {|| stor open}}
178195
}
179-
}
196+
}
197+
198+
# This hook can be added to $env.config.hooks.pre_execution to enable
199+
# "universal variables" similar to the Fish shell. Adding, changing, or
200+
# removing a universal variable will immediately update the corresponding
201+
# environment variable in all running Nushell sessions.
202+
export def "kv universal-variable-hook" [] {
203+
{||
204+
kv list --universal
205+
| transpose -dr
206+
| load-env
207+
208+
$env.NU_KV_UNIVERSALS = true
209+
}
210+
}

0 commit comments

Comments
 (0)