1+ # kv module
2+ #
3+ # use std-rfc/kv *
4+ #
5+ # Easily store and retrieve key-value pairs
6+ # in a pipeline.
7+ #
8+ # A common request is to be able to assign a
9+ # pipeline result to a variable. While it's
10+ # not currently possible to use a "let" statement
11+ # within a pipeline, this module provides an
12+ # alternative. Think of each key as a variable
13+ # that can be set and retrieved.
14+
15+ # Stores the pipeline value for later use
16+ #
17+ # If the key already exists, it is updated
18+ # to the new value provided.
19+ #
20+ # Usage:
21+ # <input> | kv set <key> <value?>
22+ #
23+ # Example:
24+ # ls ~ | kv set "home snapshot"
25+ # kv set foo 5
26+ export def "kv set" [key : string , value ?: any ] {
27+ # Pipeline input is preferred, but prioritize
28+ # parameter if present. This allows $in to be
29+ # used in the parameter if needed.
30+ let input = $in
31+ let value = $value | default $input
32+
33+ # Store values as nuons for type-integrity
34+ let kv_pair = {
35+ key : $key
36+ value : ($value | to nuon )
37+ }
38+
39+ # Create the table if it doesn't exist
40+ try {
41+ stor create - t kv_mod_store - c {key : str , value: str } | ignore
42+ }
43+
44+ # Does the key exist yet?
45+ let key_exists = ( $key in (stor open | $in.kv_mod_store ?.key? ))
46+
47+ # If so, we need an update rather than an insert
48+ let stor_action = match $key_exists {
49+ true => {{stor update - t kv_mod_store -- where-clause $" key = '($key )'" }}
50+ false => {{stor insert - t kv_mod_store }}
51+ }
52+
53+ # Execute the update-or-insert action
54+ $kv_pair | do $stor_action
55+
56+ # Returns the kv table itself in case it's
57+ # useful in the pipeline
58+ kv list
59+ }
60+
61+ def kv_key_completions [] {
62+ try {
63+ stor open
64+ # Hack to turn a SQLiteDatabase into a table
65+ | $in.kv_mod_store | wrap temp | get temp
66+ | get key?
67+ } catch {
68+ # Return no completions
69+ []
70+ }
71+
72+ }
73+
74+ # Retrieves a stored value by key
75+ #
76+ # Counterpart of "kv set". Returns null
77+ # if the key is not found.
78+ #
79+ # Usage:
80+ # kv get <key> | <pipeline>
81+ export def "kv get" [
82+ key : string @kv_key_completions # Key of the kv-pair to retrieve
83+ ] {
84+ try {
85+ stor create - t kv_mod_store - c {key : str , value: str } | ignore
86+ }
87+
88+ stor open
89+ # Hack to turn a SQLiteDatabase into a table
90+ | $in.kv_mod_store | wrap temp | get temp
91+ | where key == $key
92+ # Should only be one occurence of each key in the stor
93+ | get - i value | first
94+ | match $in {
95+ # Key not found
96+ null => null
97+ # Key found
98+ _ => { from nuon }
99+ }
100+ }
101+
102+ # List the currently stored key-value pairs
103+ #
104+ # Returns results as the Nushell value rather
105+ # than the stored nuon.
106+ export def "kv list" [] {
107+ # Create the table if it doesn't exist
108+ try {
109+ stor create - t kv_mod_store - c {key : str , value: str } | ignore
110+ }
111+
112+ stor open | $in.kv_mod_store | each {|kv_pair |
113+ {
114+ key : $kv_pair.key
115+ value : ($kv_pair.value | from nuon )
116+ }
117+ }
118+ }
119+
120+ # Returns and removes a key-value pair
121+ export def "kv drop" [
122+ key : string @kv_key_completions # Key of the kv-pair to drop
123+ ] {
124+ # Create the table if it doesn't exist
125+ try {
126+ stor create - t kv_mod_store - c {key : str , value: str } | ignore
127+ }
128+
129+ try {
130+ stor open
131+ # Hack to turn a SQLiteDatabase into a table
132+ | $in.kv_mod_store | wrap temp | get temp
133+ | where key == $key
134+ # Should only be one occurence of each key in the stor
135+ | get - i value | first
136+ | match $in {
137+ # Key not found
138+ null => null
139+
140+ # Key found
141+ _ => {
142+ let value = $in
143+ stor delete -- table-name kv_mod_store -- where-clause $" key = '($key )'"
144+ $value | from nuon
145+ }
146+ }
147+
148+ } catch {
149+ # If value not found or other error, don't return anything
150+ null
151+ }
152+ }
0 commit comments