120 lines
4.0 KiB
Python
120 lines
4.0 KiB
Python
import bz2
|
|
import textwrap
|
|
import re
|
|
import argparse
|
|
import sqlite3
|
|
import os
|
|
import glob
|
|
|
|
# SGR color constants
|
|
# rene-d 2018
|
|
|
|
|
|
# https://gist.githubusercontent.com/rene-d/9e584a7dd2935d0f461904b9f2950007/raw/e2e58ccf955475d8066338a4e538c52debc06a06/colors.py
|
|
class Colors:
|
|
"""ANSI color codes"""
|
|
|
|
BLACK = "\033[0;30m"
|
|
RED = "\033[0;31m"
|
|
GREEN = "\033[0;32m"
|
|
BROWN = "\033[0;33m"
|
|
BLUE = "\033[0;34m"
|
|
PURPLE = "\033[0;35m"
|
|
CYAN = "\033[0;36m"
|
|
LIGHT_GRAY = "\033[0;37m"
|
|
DARK_GRAY = "\033[1;30m"
|
|
LIGHT_RED = "\033[1;31m"
|
|
LIGHT_GREEN = "\033[1;32m"
|
|
YELLOW = "\033[1;33m"
|
|
LIGHT_BLUE = "\033[1;34m"
|
|
LIGHT_PURPLE = "\033[1;35m"
|
|
LIGHT_CYAN = "\033[1;36m"
|
|
LIGHT_WHITE = "\033[1;37m"
|
|
BOLD = "\033[1m"
|
|
FAINT = "\033[2m"
|
|
ITALIC = "\033[3m"
|
|
UNDERLINE = "\033[4m"
|
|
BLINK = "\033[5m"
|
|
NEGATIVE = "\033[7m"
|
|
CROSSED = "\033[9m"
|
|
END = "\033[0m"
|
|
# cancel SGR codes if we don't write to a terminal
|
|
if not __import__("sys").stdout.isatty():
|
|
for _ in dir():
|
|
if isinstance(_, str) and _[0] != "_":
|
|
locals()[_] = ""
|
|
else:
|
|
# set Windows console in VT mode
|
|
if __import__("platform").system() == "Windows":
|
|
kernel32 = __import__("ctypes").windll.kernel32
|
|
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
|
del kernel32
|
|
|
|
def clean(s: str) -> str:
|
|
for i in dir(Colors):
|
|
if i[0:1] != "_" and i != "clean":
|
|
s = s.replace(getattr(Colors, i), "")
|
|
return s
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Search in RFCs")
|
|
parser.add_argument("terms", metavar="T", type=str, nargs="+", help="search terms")
|
|
|
|
args = parser.parse_args()
|
|
terms = args.terms
|
|
|
|
file_path = os.path.dirname(os.path.realpath(__file__))
|
|
files = list(
|
|
glob.glob(
|
|
"**/*.txt.bz2", root_dir=file_path, recursive=True, include_hidden=False
|
|
)
|
|
)
|
|
db = sqlite3.connect(":memory:")
|
|
cur = db.cursor()
|
|
cur.execute(
|
|
'create virtual table rfc using fts5(title, content, tokenize="porter unicode61");'
|
|
)
|
|
cur.executemany(
|
|
"insert into rfc (title, content) values (?,?);",
|
|
(
|
|
(f, bz2.decompress(open(f, "rb").read()).decode(errors="replace"))
|
|
for f in files
|
|
),
|
|
)
|
|
db.commit()
|
|
"""
|
|
╭───────────────────────────╮
|
|
│ Third example in │
|
|
│ a series of boxes. │
|
|
────────╮ ╰──╮
|
|
┃ This box │ ◉◉ ┝━┓
|
|
┃ is in the╰────────────────╯ ┃
|
|
┃ background, but still happ
|
|
"""
|
|
|
|
for res in cur.execute(
|
|
f"""select title, snippet(rfc, 1, '{Colors.GREEN}{Colors.BOLD}', '{Colors.END}{Colors.ITALIC}', '', 36), rank from rfc where title MATCH '{terms[0]}' OR content MATCH '{terms[0]}' order by rank;"""
|
|
).fetchall():
|
|
title = res[0].strip()
|
|
print(
|
|
"Path:",
|
|
title,
|
|
)
|
|
content = re.sub("\n\n\n\n*", "\n", res[1].strip())
|
|
content = re.sub("\t", "", content)
|
|
print(Colors.ITALIC, end="", sep="")
|
|
max_len = max(len(Colors.clean(line.strip())) for line in content.splitlines())
|
|
total_len = len("╭") + len("─" * (max_len + 1)) + len("╮")
|
|
title_len = len(title[:45] + "...")
|
|
print(f"╭", "─" * (title_len + 2), "╮", sep="")
|
|
print(f"│ {title[:45]}...{' '*(title_len-total_len)}│", sep="")
|
|
print("├", "─" * (max_len + 2), "╮", sep="")
|
|
for line in content.splitlines():
|
|
if len(Colors.clean(re.sub("\s*", "", line.strip()))) == 0:
|
|
continue
|
|
l = 1 + total_len - len(Colors.clean(line.strip())) - len("│ ") * 2
|
|
print("│ ", line.strip(), " " * l, " │", sep="")
|
|
print("╰", "─" * (max_len + 2), "╯", sep="")
|
|
print(Colors.END)
|