Files
dotfiles/scripts/nav/main.py
Sebastian Moser 3726e3ff6d ...
2023-11-29 09:56:23 +01:00

256 lines
6.7 KiB
Python

import shlex
from pathlib import Path
from os import path
import os
import argparse
import sys, tty, termios
import subprocess
from subprocess import Popen
import signal
DB_FILE = "/home/me/work/config/scripts/nav/db"
def debug(*args, **kargs):
global out
print(*args, **kargs, file=out)
out.flush()
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--mode', help='mode of the program', type=str)
parser.add_argument('-c', '--char', help='mode of the program', type=str)
args = parser.parse_args()
if args.mode == "lf":
pre_cd = None
lf_id = os.environ["id"]
pwd = Path(os.getcwd())
if args.char is not None:
dests = do_nav(args.char, pwd)
if len(dests) == 1:
pre_cd = my_resolve(dests[0], pwd=pwd)
pwd = pre_cd
Popen(["lf", "-remote", f"send {lf_id} echo -- NAV --"])
# for debug
global out
#out = open("/home/me/p1", "w")
#sys.stderr = out
#sys.stdout = out
#debug()
pid_lf = int(os.environ["lf_user_pid"])
pgid = int(os.environ["lf_user_pgid"])
#for debug
#print("pid_lf", pid_lf)
#print("pgid", pgid)
path = f"/proc/{pid_lf}/fd/0"
os.setpgid(os.getpid(), pgid)
file = open(path, "r")
#clear filter
#os.system(f'lf -remote "send $id setfilter"')
#os.system('lf -remote "send $id echo -- NAV --"')
chars = []
while True:
print("-- HIIIIIIIIIII --")
#Popen(["lf", "-remote", f"send {lf_id} echo -- NAV iiiiiiiiiiiiiiii --"])
c = file.read(1)
#debug("-- HIIIIIIIIIII after --")
if pre_cd is not None:
Popen(["lf", "-remote", f"send {lf_id} cd {pre_cd}"])
pre_cd = None
if c == "\x20" or c == "\x1b": # exit nav mode, when space or ESC is pressed
if len(chars) == 0:
pass
Popen(["lf", "-remote", f"send {lf_id} setfilter"])
Popen(["lf", "-remote", f"send {lf_id} echo NAV Done"])
print("NAV Done")
break
if c == "\x03":
chars = chars[0:len(chars)-1]
chars.append(c)
dests = do_nav(chars, pwd)
#for debug
#debug("dests:", dests)
if len(dests) == 1:
path_to_go = my_resolve(dests[0], pwd=pwd)
Popen(["lf", "-remote", f"send {lf_id} setfilter"])
if os.path.isdir(path_to_go):
#for debug
#print("cding to:", path_to_go)
Popen(["lf", "-remote", f"send {lf_id} cd {path_to_go}"])
print("-- NAV --")
#Popen(["lf", "-remote", f"send {lf_id} echo -- NAV --"])
else:
Popen(["lf", "-remote", f"send {lf_id} select {path_to_go}"])
Popen(["lf", "-remote", f"send {lf_id} echo NAV Done"])
break
chars = []
pwd = path_to_go
elif len(dests) == 0:
chars = []
else:
chars_as_string = "".join(chars)
Popen(["lf", "-remote", f"send {lf_id} setfilter {chars_as_string}"])
print("-- NAV --")
#Popen(["lf", "-remote", f"send {lf_id} echo -- NAV --"])
#debug("got:", c, "chars:", chars)
file.close()
# for debug
out.close()
else:
chars = []
while True:
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
c = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
if c == "\x20" or c == "\x1b": # exit nav mode, when space or ESC is pressed
break
if c == "\x03":
chars = chars[0:len(chars)-1]
dests = do_nav(chars, pwd)
if len(dests) == 1:
path_to_go = my_resolve(dests[0], pwd=pwd)
os.system("export")
elif len(dests) == 0:
pass
else:
pass
def do_nav(chars, pwd):
db_matches = get_db_matches(pwd, DB_FILE)
folder_db_matches = get_folder_db_matches(pwd)
folder_items = list_folder(pwd)
# for debug
#print("pwd:", pwd)
#print("chars:", chars)
# first check if the char matches in what is in the main db
# immediatly cd (return list with one el) if found
for (match, dest) in db_matches:
if match == chars[0]:
return [dest]
# next check local db
# but also immediatly cd when found
for (match, dest) in folder_db_matches:
if match == chars[0]:
return [dest]
# then check folder contents
# and return all that start with that char
dests = []
for item in folder_items:
item_chars = item[0:len(chars)]
search_chars = "".join(chars[0:len(chars)])
if item_chars == search_chars:
dests.append(item)
return dests
def get_db_matches(directory, db_file):
matches = []
with open(db_file, "r") as file:
for line in file.readlines():
line = line.strip()
if line == "":
continue
tmp = shlex.split(line)
try:
dir_in = tmp[0]
shortcut = tmp[1]
dest = tmp[2]
except:
eprint("db parse error on:", line)
continue
if dir_in == "*":
matches.append((shortcut, dest))
elif my_resolve(directory) == my_resolve(dir_in):
matches.append((shortcut, dest))
return matches
def list_folder(directory):
matches = []
ls = os.listdir(directory)
"""
for path in ls:
if path[0] == ".":
path_as_list = list(str(path))
path_as_list.pop(0)
path = "".join(path_as_list)
matches.append(path)
"""
return ls
def get_folder_db_matches(directory):
if os.path.exists(directory / ".nav_db"):
return get_db_matches(directory, directory / ".nav_db")
else:
return []
def my_resolve(path, pwd=os.getcwd()):
if path == ".":
return Path(pwd)
elif str(path)[0] == "~":
path_as_list = list(str(path))
path_as_list.pop(0)
return Path(str(Path.home()) + "".join(path_as_list))
elif str(path)[0] == "/":
return Path(path)
else:
return Path(pwd) / Path(path)
if __name__ == "__main__":
main()