From 912421f1cb61fca530fb501b9e6a904dc21e44d6 Mon Sep 17 00:00:00 2001
From: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Thu, 5 Sep 2019 22:40:31 -0500
Subject: [PATCH] Switch away from `awk` for `__fish_print_hostnames`

By not manipulating each line or even each file at a time, we can go
back to `string` and piece together a pipeline that will execute
significantly faster than shelling out to `awk` will. This also removes
one of the few dependencies on `awk` in the codebase.

With this change, `__fish_print_hostnames` now finishes ~80% faster than
it used to a few commits back.
---
 share/functions/__fish_print_hostnames.fish | 27 +++++++++------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/share/functions/__fish_print_hostnames.fish b/share/functions/__fish_print_hostnames.fish
index c9a269b46..1034b49a5 100644
--- a/share/functions/__fish_print_hostnames.fish
+++ b/share/functions/__fish_print_hostnames.fish
@@ -121,22 +121,17 @@ function __fish_print_hostnames -d "Print a list of known hostnames"
             read -z <$file
         end
     end |
-        # Ignore hosts that are hashed, commented or @-marked and strip the key.
-        awk '$1 !~ /[|#@]/ {
-          n=split($1, entries, ",")
-          for (i=1; i<=n; i++) {
-            # Ignore negated/wildcarded hosts.
-            if (!match(entry=entries[i], "[!*?]")) {
-              # Extract hosts with custom port.
-              if (substr(entry, 1, 1) == "[") {
-                if (pos=match(entry, "]:.*$")) {
-                  entry=substr(entry, 2, pos-2)
-                }
-              }
-              print entry
-            }
-          }
-        }'
+        # Ignore hosts that are hashed, commented or @-marked and strip the key
+        # Handle multiple comma-separated hostnames sharing a key, too.
+        #
+        # This one regex does everything we need, finding all matches including comma-separated
+        # values, but fish does not let us print only a capturing group without the entire match,
+        # and we can't use `string replace` instead (because CSV then fails).
+        # string match -ar "(?:^|,)(?![@|*!])\[?([^ ,:\]]+)\]?"
+        #
+        # Instead, manually piece together the regular expressions
+        string match -v -r '^\s*[!*|@#]' | string replace -r '^\s*(\S+) .*' '$1' |
+            string split ',' | string replace -r '\[?([^:\]]+).*' '$1'
 
     return 0
 end