about summary refs log tree commit diff
path: root/users
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2023-01-20T16·04-0800
committerclbot <clbot@tvl.fyi>2023-01-20T16·09+0000
commit9df188ad0320fac33c57065eb1d166e8c7713158 (patch)
tree538e038e1fb3dd6b8342735c6bab132418191e8c /users
parent259faea2b229edd8f2e31d0903b5fd185036b4a4 (diff)
feat(wpcarro/slx): Support numeric comparisons r/5710
I was (and still ~am) a bit leery of supporting this (scope creep?), but I need
it in two of my personal projects all within the first O(days) of using this. So
I'm thinking that if this tool is going to be a workhorse, I'll need to
sacrifice some purity for practicality. Future me will find out the real
answer...

Change-Id: Ia71a8cf6627062440476b638d2c194c2c9ac97c4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7878
Autosubmit: wpcarro <wpcarro@gmail.com>
Reviewed-by: wpcarro <wpcarro@gmail.com>
Tested-by: BuildkiteCI
Diffstat (limited to 'users')
-rw-r--r--users/wpcarro/slx.js/index.js68
1 files changed, 67 insertions, 1 deletions
diff --git a/users/wpcarro/slx.js/index.js b/users/wpcarro/slx.js/index.js
index 9f2ed675f7..44f2f3643f 100644
--- a/users/wpcarro/slx.js/index.js
+++ b/users/wpcarro/slx.js/index.js
@@ -49,6 +49,19 @@ function compile(ast, config) {
             };
         }
     }
+    if (ast.type === 'COMPARE_SELECTION') {
+        const f = compile(ast.val, config);
+
+        let compare = null;
+        if (ast.operator === 'LT') { compare = (x, y) => x < y; }
+        if (ast.operator === 'GT') { compare = (x, y) => x > y; }
+        if (ast.operator === 'LTE') { compare = (x, y) => x <= y; }
+        if (ast.operator === 'GTE') { compare = (x, y) => x >= y; }
+
+        return function(row) {
+            return ast.negate ? !compare(row[ast.key], ast.val) : compare(row[ast.key], ast.val);
+        };
+    }
     if (ast.type === 'SELECTION') {
         const f = compile(ast.val, config);
         return function(row) {
@@ -116,6 +129,17 @@ function tokenize(x) {
             i += 1;
             continue;
         }
+        // Tokenize numbers (i.e. integers, floats).
+        if (/[0-9]/.test(x[i])) {
+            let curr = x[i];
+            i += 1;
+            while (i < x.length && /[0-9]/.test(x[i])) {
+                curr += x[i];
+                i += 1;
+            }
+            result.push(['NUMBER', parseFloat(curr)]);
+            continue;
+        }
         if (ATOM_REGEX.test(x[i])) {
             let curr = x[i];
             i += 1;
@@ -126,6 +150,26 @@ function tokenize(x) {
             result.push(['ATOM', curr]);
             continue;
         }
+        if (x[i] === '<' && i + 1 < x.length && x[i + 1] === '=') {
+            result.push(['COMPARE', 'LTE']);
+            i += 1;
+            continue;
+        }
+        if (x[i] === '<') {
+            result.push(['COMPARE', 'LT']);
+            i += 1;
+            continue;
+        }
+        if (x[i] === '>' && i + i < x.length && x[i + 1] === '=') {
+            result.push(['COMPARE', 'GTE']);
+            i += 1;
+            continue;
+        }
+        if (x[i] === '>') {
+            result.push(['COMPARE', 'GT']);
+            i += 1;
+            continue;
+        }
         if (x[i] === ':') {
             result.push(['COLON', null]);
             i += 1;
@@ -297,7 +341,29 @@ function selection(p, config) {
                 val,
             };
         }
-    } else {
+    }
+    // column<value OR -column<value
+    else if ((peekType(0, p) === 'ATOM' && peekType(1, p) === 'COMPARE') ||
+             (peekType(0, p) === 'NEGATE' && peekType(1, p) === 'ATOM' && peekType(2, p) === 'COMPARE')) {
+        let negate = false;
+        if (p.tokens[p.i][0] === 'NEGATE') {
+            negate = true;
+            p.i += 1;
+        }
+
+        const key = match((type, _) => type === 'ATOM', 'a column label', p);
+        const operator = match((type, _) => type === 'COMPARE', 'a comparison operator (i.e. "<", ">", "<=", ">=")', p);
+        const val = match((type, _) => type === 'NUMBER', 'a number', p);
+
+        return {
+            type: 'COMPARE_SELECTION',
+            operator,
+            negate,
+            key,
+            val,
+        };
+    }
+    else {
         return matchAll(p, config);
     }
 }