From fa0628d5c66d8df2d996cc2b68f882a19ab1a6e8 Mon Sep 17 00:00:00 2001
From: John Poth <poth.john@gmail.com>
Date: Fri, 4 Oct 2019 16:31:16 +0200
Subject: [PATCH] Add search filter when displaying namespaces Fixes #15 and
 #49

---
 lib/ui/namespaces.js | 110 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/lib/ui/namespaces.js b/lib/ui/namespaces.js
index cb0970f..1184960 100644
--- a/lib/ui/namespaces.js
+++ b/lib/ui/namespaces.js
@@ -32,6 +32,114 @@ function namespaces_list(screen) {
     }
   });
 
+  const search = blessed.textbox({
+    parent       : namespaces_list,
+    label        : 'Search',
+    content      : '',
+    border       : 'line',
+    width        : '30%',
+    height       : 3,
+    right        : 2,
+    top          : -1,
+    keys         : true,
+    mouse        : true,
+    hidden       : true,
+    inputOnFocus : true,
+    style : {
+      fg       : 'white',
+      label    : { bold: true },
+      border   : { fg: 'white' },
+      selected : { bg: 'blue' },
+    }
+  });
+
+  search.__oolistener = search._listener;
+  search._listener = function(ch, key) {
+    const word = ['up', 'down','enter'];    
+    if (word.includes(key.name)) {
+        return namespaces_list.emit('keypress', ch, key);
+    }
+    const ret = this.__oolistener(ch, key);
+    let i = 0;
+    namespaces_list.items.forEach((element, pos) => {
+        if (!element.getContent().includes(search.value)){
+            element.position.top = 0;
+            element.hidden = true;
+        } else {
+            element.position.top = i;
+            element.hidden = false;
+            if (i===0) {
+                namespaces_list.selected = pos;
+            }
+            i++;
+        }
+    });
+    namespaces_list.scrollTo(0);
+    screen.render();
+    return ret;
+  };
+  namespaces_list.on('keypress', (ch, key) => {
+    const keys = ['escape', 'up', 'down', 'enter', 'q'];
+    if (keys.includes(key.name) || !search.hidden) {
+        return;
+    } else {
+        search.hidden = false;
+        screen.saveFocus();
+        namespaces_list.append(search);
+        search.focus();
+        search.readInput();
+        search._listener(ch,key);
+        screen.render();
+    } 
+  });
+
+  search.key('escape', (ch, key) => {
+    search.detach();
+    search.value = '';
+    search.hidden = true;
+    screen.restoreFocus();
+    namespaces_list.items.forEach((element, pos) => {
+        element.position.top = pos;
+        element.hidden = false;
+    });
+    namespaces_list.select(0);
+    screen.render();
+  });
+
+  namespaces_list.up = function(offset) {
+    if (namespaces_list.items[namespaces_list.selected].hidden)
+        return;
+    let i = namespaces_list.selected -(offset || 1);
+    const len = namespaces_list.items.length;
+    for(i = mod(i,len); i < len && i >= 0; i = mod(i-1,len)) {
+        if(!namespaces_list.items[i].hidden) { 
+            namespaces_list.selected = i;
+            namespaces_list.scrollTo(namespaces_list.items[i].position.top);
+            screen.render();
+            return;
+        }
+    }
+  };
+  
+  namespaces_list.down = function(offset) {
+    if (namespaces_list.items[namespaces_list.selected].hidden)
+        return;
+    let i = namespaces_list.selected +(offset || 1);
+    const len = namespaces_list.items.length;
+    for(i = mod(i,len); i < len && i >= 0 ; i = mod(i+1,len)){
+        if(!namespaces_list.items[i].hidden) { 
+            namespaces_list.selected = i;
+            namespaces_list.scrollTo(namespaces_list.items[i].position.top);
+            screen.render();
+            return;
+        }
+    }
+  };
+
+  function mod(a , b){
+    return (((a)%b)+b)%b;
+  }
+
   return namespaces_list;
 }
 
@@ -133,7 +241,7 @@ function prompt(screen, client, { current_namespace, promptAfterRequest } = { pr
 
     list.on('select', (item, i) => {
       close_namespaces_list();
-      if (item) {
+      if (item && !item.hidden) {
         const namespace = namespaces.items[i].metadata.name;
         fulfill(namespace);
       } else {