dotfiles/i3/scripts/dmenu/init.py

146 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sqlite3
import json
import argparse
import sys
import os
from modules import Application, MPC
from Dmenu import Dmenu
del sys.path[0]
sys.path.insert(0, os.path.dirname(sys.argv[0]))
# CONFIG
loadModules = [Application(), MPC()]
con = sqlite3.connect(os.path.dirname(sys.argv[0]) + "/database.sqlite")
# ARGUMENTS PARSER
parser = argparse.ArgumentParser(description="Smart Dropdown Launcher for AwesomeWM")
parser.add_argument(
"--create",
dest="FLAG_CREATE",
action="store_const",
const=True,
default=False,
help="Force TABLE \
CREATION",
)
parser.add_argument(
"--build",
dest="FLAG_BUILD",
action="store_const",
const=True,
default=False,
help="Force Build \
the Database",
)
parser.add_argument(
"--truncate",
dest="FLAG_TRUNCATE",
action="store_const",
const=True,
default=False,
help="Truncate\
Database during build",
)
args = parser.parse_args()
# Helper functions
def create_db():
command = "CREATE TABLE entries(`ID` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, `Name` TEXT, `json` TEXT, `hits` INTEGER NOT NULL DEFAULT 0, `disabled` INTEGER NOT NULL DEFAULT 0, `type` TEXT NOT NULL DEFAULT 'file', `file` TEXT);"
with con:
cur = con.cursor()
cur.execute(command)
con.commit()
def retrieve_db():
rows = []
with con:
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("SELECT * FROM entries;")
ro = cur.fetchall()
for r in ro:
r = dict(r)
r["json"] = json.loads(r["json"])
rows.append(r)
return rows
def build_db():
entries = {}
for mod in loadModules:
entries.update(mod.build_db())
for k, v in entries.items():
if "Exec" in v["json"]:
with con:
con.cursor().execute(
"INSERT INTO entries(Name, json, file, type, disabled) VALUES(?, ?, ?, ?, ?)",
(k, json.dumps(v["json"]), v["file"], v["type"], v["disabled"]),
)
def build_menu():
entries = []
db = retrieve_db()
for mod in loadModules:
entries += mod.build_menu([x for x in db if x["type"] == mod.db_type])
# sort by hits
return sorted(entries, key=lambda i: i[2], reverse=True)
def run_program(data):
with con:
cur = con.cursor()
cur.execute("UPDATE entries SET hits=? WHERE ID=?", (data[2] + 1, data[0]))
cur.execute("SELECT type FROM entries WHERE ID=?", (data[0],))
con.commit()
typ = dict(cur.fetchone())["type"]
for mod in loadModules:
if mod.db_type == typ:
mod.call(data[1])
if args.FLAG_CREATE:
with con:
con.cursor().execute("DROP TABLE IF EXISTS entries;")
create_db()
# set BUILD flag so the database gets rebuilt too
args.FLAG_BUILD = True
if args.FLAG_BUILD:
if args.FLAG_TRUNCATE:
with con:
con.cursor().execute("DELETE FROM entries")
con.cursor().execute("DELETE FROM sqlite_sequence WHERE name='entries'")
con.commit()
build_db()
entries = build_menu()
p1 = Dmenu([x[1] for x in entries]).run()
if p1[0] != 0:
# error on escape
exit(1)
selected = list(filter(lambda x: p1[1].strip().startswith(x[1]), entries))
if selected == []:
# -> terminal module? None-Type modules?
pass
else:
# use actual user input
selected = (selected[0][0], p1[1].rstrip(), selected[0][2])
run_program(selected)
con.close()