lucc / khard

Console vcard client
https://khard.readthedocs.io/en/latest/
GNU General Public License v3.0
600 stars 65 forks source link

Patching input prompt flushing to redirect `khard show` to a highlighter #333

Open tkapias opened 8 months ago

tkapias commented 8 months ago

Introduction

Khard being console oriented is nice, but I miss some coloration, at least in khard show. For that purpose I use hl, it colorizes any output according to a simple configuration based on regular expressions.

But, when piping khard show to hl there is an issue that I described in hl's repo, here.

I did open it at hl first, because piping to cat did not show the same issue, but I later wrote a patch for Khard which I'd like to share and, I think, also enhance the output format.

Issue

In short, the user input prompt string is not flushed before the user answer, but after, when redirected to hl, and without a newline.

image

See like the index number inputed is above the prompt, which appear later on the same line as the pretty vcard first line.

Solution

Normally python should flush every print with a newline. I suspected that piping to hl breaks this behaviour, so I tried to force it by using flush=True in different places in interactive.select, but it does not change the result.

image image

I find this result more pleasing, even without hl.

diff --git a/khard/helpers/interactive.py b/khard/helpers/interactive.py
index 79db461..db36141 100644
--- a/khard/helpers/interactive.py
+++ b/khard/helpers/interactive.py
@@ -91,7 +91,7 @@ def select(items: Sequence[T], include_none: bool = False) -> Optional[T]:
     :returns: None or the selected item
     :raises Canceled: when the user canceled the selection process
     """
-    prompt = "Enter Index ({}q to quit): ".format("0 for None, "
+    prompt = "Enter Index ({}q to quit):\n".format("0 for None, "
                                                   if include_none else "")
     while True:
         try:
@@ -103,6 +103,8 @@ def select(items: Sequence[T], include_none: bool = False) -> Optional[T]:
             if include_none and index == 0:
                 return None
             if index > 0:
+                print("\033[1A" + "\033[K" + "\033[1A" + "\033[K" + "Selected Index: ", end="")
+                print(index, end="\n\n")
                 return items[index - 1]
         except (EOFError, IndexError, ValueError):
             pass

Extra

For those interested, I use the combo khard show/hl in a bash function:

contacts () { 
    echo
    khard show $@ | hl --khard
    echo
}

And my hl configuration for khard is currently this (~/.config/hl/config.d/hl_khal.cfg):

khard            :
     -e
     -3w '^[ ]{4}?[a-zA-Z][a-zA-Z -]{1,12}:'
     -3g '^Address book: (.*)$'
     -3y '^Index.*$'
     -1y '^[0-9]+'
     -2c 'Nickname:'
     -1w '[ ]{4}([a-zA-Z]+:)'
     -3r ': (\+?\(?[0-9]{1,3}\)?[0-9 -]{8,13}[0-9])'
     -3b '([^ ]+)@[^ ]+\.[^ ]+'
     -2b '[^ ]+(@[^ ]+\.[^ ]+)'

You may need to export some path for the hl config files, like this:

export HL_CONF=$HOME/.config/hl/config.d:/etc/hl/config.d

lucc commented 8 months ago

Thanks for your report. I can confirm what you describe but I think the underlying problem is thus:

I do not really like the code changes you propose for these reasons: