From 01c2c28dcc9efb83f3d9c38332312e40850309f5 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Fri, 8 Oct 2021 19:21:28 -0500 Subject: Refactor entry points --- README.md | 46 +++++++++------------ setup.cfg | 8 ++-- wikijscmd/__init__.py | 11 ----- wikijscmd/__main__.py | 6 ++- wikijscmd/app.py | 53 +++++++++++++++++++++++++ wikijscmd/cli.py | 52 ------------------------ wikijscmd/ncurses.py | 103 ----------------------------------------------- wikijscmd/tui.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+), 200 deletions(-) create mode 100644 wikijscmd/app.py delete mode 100755 wikijscmd/cli.py delete mode 100755 wikijscmd/ncurses.py create mode 100644 wikijscmd/tui.py diff --git a/README.md b/README.md index 3dfb013..c283225 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,28 @@ A client to use wiki.js over the command line. Supports creating, editing, and viewing pages, and viewing the wiki file tree. +## Installation + +Install the module: `python3 -m pip install wikijscmd` + +Create a file `/etc/wikijscmd/config.ini` with the following information: +``` +[wiki] +key=YOUR_KEY_HERE +url=YOUR_GRAPHQL_ENDPOINT_HERE +``` +The key is provided via the admin panel under the API access tab. The URL +for wiki.js is typically the URL of your wiki with the path `/graphql`. For +example, if your wiki is at `wiki.example.com`, the url field should be set to +`https://wiki.example.com/graphql`. + ## Usage wikijscmd supports the following commands: ### create PATH TITLE CONTENT? -creates a page with the given page, title, and content. Content is optional, -if none is provided, then an editor will open based on the VISUAL or EDITOR -variable. +creates a page with the given page, title, and content. Content is optional, +if none is provided, then an editor will open based on the VISUAL or EDITOR +variable. ### edit (PATH|ID) opens a page in the editor based on VISUAL or EDITOR variables for the given @@ -33,31 +48,6 @@ command `create 1970/01/01 "Janurary 1"`. ### move (PATH|ID) DEST\_PATH Moves a page identified by the path or ID given to the destination path. -## Installation -Clone the repository or download the source code. - -Install python3, and pip for python3 for your system. - -Install the dependencies -`pip3 install -r requirements.txt` - -Create a file `/etc/wikijscmd/config.ini` with the following information: -``` -[wiki] -key=YOUR_KEY_HERE -url=YOUR_GRAPHQL_ENDPOINT_HERE -``` -The key is provided via the admin panel under the API access tab. The URL -for wiki.js is typically the URL of your wiki with the path `/graphql`. For -example, if your wiki is at `wiki.example.com`, the url field should be set to -`https://wiki.example.com/graphql`. - -Run `main.py` in order to use the program. - -Example uses: -- Create a page `./main.py create 2021/02/26 "February 26"` -- Edit a page `./main.py edit 2021/02/26` - ## Ncurses TUI A ncurses TUI beta client also is provided, though it is still a work in progress. It is run through the file `ncurses.py` diff --git a/setup.cfg b/setup.cfg index 58f4a0d..5754d69 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,8 @@ [metadata] name = wikijscmd-markpowers -version = 0.0.1 +version = 0.1.0 author = Mark Powers -author_email = author@example.com +author_email = mark@marks.kitchen description = A command line interface client for wiki.js long_description = file: README.md long_description_content_type = text/markdown @@ -23,6 +23,6 @@ python_requires = >=3.6 [options.packages.find] where=wikijscmd -[entry_points] +[options.entry_points] console_scripts = - wikijscmd = wikijscmd.cli:cli() + wikijscmd = wikijscmd.cli:cli diff --git a/wikijscmd/__init__.py b/wikijscmd/__init__.py index 8f45ae2..e69de29 100644 --- a/wikijscmd/__init__.py +++ b/wikijscmd/__init__.py @@ -1,11 +0,0 @@ -from wikijscmd import cli -from wikijscmd import ncurses - -def main(): - cli.cli() - -def tui(): - try: - ncurses.wrapper(m) - except Exception as e: - raise e diff --git a/wikijscmd/__main__.py b/wikijscmd/__main__.py index 02ddab3..267af9f 100644 --- a/wikijscmd/__main__.py +++ b/wikijscmd/__main__.py @@ -1,4 +1,6 @@ -import wikijscmd +import sys + +from . import app if __name__ == '__main__': - wikijscmd.main() + app.main() diff --git a/wikijscmd/app.py b/wikijscmd/app.py new file mode 100644 index 0000000..c16a446 --- /dev/null +++ b/wikijscmd/app.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +import sys +import argparse + +from wikijscmd.config import config +from wikijscmd.commands import create, edit, single, tree, today, move, fill_in_pages +from wikijscmd.tui import tui + +def main(): + parser = argparse.ArgumentParser("wikijscmd") + parser.set_defaults(command=None) + subparsers = parser.add_subparsers() + + parser_create = subparsers.add_parser("create", help="create a page") + parser_create.add_argument("path", type=str, help="the path of the new page") + parser_create.add_argument("title", type=str, help="the title of the new page") + parser_create.add_argument("content", nargs="?", type=str, help="optional page content") + parser_create.set_defaults(command=create) + + parser_tree = subparsers.add_parser("tree", help="search in the page tree") + parser_tree.add_argument("regex", type=str, help="optional regex to search paths with") + parser_tree.set_defaults(command=tree) + + parser_single = subparsers.add_parser("single", help="view a single page") + parser_single.add_argument("path", type=str, help="the path of the page to view") + parser_single.set_defaults(command=single) + + parser_edit = subparsers.add_parser("edit", help="edit a page") + parser_edit.add_argument("path", type=str, help="the path of the page to edit") + parser_edit.set_defaults(command=edit) + + parser_today = subparsers.add_parser("today", help="create/edit the journal page for today") + parser_today.set_defaults(command=today) + + parser_move = subparsers.add_parser("move", help="move a page") + parser_move.add_argument("source", type=str, help="the path of the page to move") + parser_move.add_argument("dest", type=str, help="the destination path") + parser_move.set_defaults(command=move) + + parser_journal = subparsers.add_parser("journal", help="create journal pages") + parser_journal.set_defaults(command=fill_in_pages) + + parser_tui = subparsers.add_parser("tui", help="lauch a ncurses interface") + parser_tui.set_defaults(command=tui) + + args = vars(parser.parse_args()) + callback = args["command"] + if callback is None: + parser.print_help() + else: + del args["command"] + callback(**args) diff --git a/wikijscmd/cli.py b/wikijscmd/cli.py deleted file mode 100755 index 2847e40..0000000 --- a/wikijscmd/cli.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import argparse - -from wikijscmd.config import config -from wikijscmd.commands import create, edit, single, tree, today, move, fill_in_pages - -def cli(): - parser = argparse.ArgumentParser("wikijscmd") - parser.set_defaults(command=None) - subparsers = parser.add_subparsers() - - parser_create = subparsers.add_parser("create", help="create a page") - parser_create.add_argument("path", type=str, help="the path of the new page") - parser_create.add_argument("title", type=str, help="the title of the new page") - parser_create.add_argument("content", nargs="?", type=str, help="optional page content") - parser_create.set_defaults(command=create) - - parser_tree = subparsers.add_parser("tree", help="search in the page tree") - parser_tree.add_argument("regex", type=str, help="optional regex to search paths with") - parser_tree.set_defaults(command=tree) - - parser_single = subparsers.add_parser("single", help="view a single page") - parser_single.add_argument("path", type=str, help="the path of the page to view") - parser_single.set_defaults(command=single) - - parser_edit = subparsers.add_parser("edit", help="edit a page") - parser_edit.add_argument("path", type=str, help="the path of the page to edit") - parser_edit.set_defaults(command=edit) - - parser_today = subparsers.add_parser("today", help="create/edit the journal page for today") - parser_today.set_defaults(command=today) - - parser_move = subparsers.add_parser("move", help="move a page") - parser_move.add_argument("source", type=str, help="the path of the page to move") - parser_move.add_argument("dest", type=str, help="the destination path") - parser_move.set_defaults(command=move) - - parser_journal = subparsers.add_parser("journal", help="create journal pages") - parser_journal.set_defaults(command=fill_in_pages) - - args = vars(parser.parse_args()) - callback = args["command"] - if callback is None: - parser.print_help() - else: - del args["command"] - callback(**args) - -if __name__ == "__main__": - main() diff --git a/wikijscmd/ncurses.py b/wikijscmd/ncurses.py deleted file mode 100755 index ecc145f..0000000 --- a/wikijscmd/ncurses.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python3 - -import curses -from curses import wrapper - -from wikijscmd import util - -def pager(stdscr, lst): - ''' - Runs a pager for each string item in lst - ''' - cols = stdscr.getmaxyx()[1] - rows = stdscr.getmaxyx()[0] - offset = 0 - selected = 0 - while True: - stdscr.clear() - for i in range(min(rows-1, len(lst))): - x = lst[i+offset] - if i+offset == selected: - stdscr.addstr(i, 0, x[:cols], curses.A_UNDERLINE) - else: - stdscr.addstr(i, 0, x[:cols]) - if offset == 0: - stdscr.addstr(rows-1, 0, "--top--", curses.A_REVERSE) - elif offset + rows <= len(lst): - stdscr.addstr(rows-1, 0, "--more--", curses.A_REVERSE) - else: - stdscr.addstr(rows-1, 0, "--end--", curses.A_REVERSE) - k = stdscr.getch() - if k == curses.KEY_DOWN or k == ord('j'): - selected = min(len(lst), selected+1) - if (selected - offset) > (2 * rows / 3): - offset = min(len(lst)-rows+1, offset+1) - elif k == curses.KEY_UP or k == ord('k'): - selected = max(0, selected-1) - if (selected - offset) < (rows / 3): - offset = max(0, offset-1) - elif k == curses.KEY_NPAGE: - offset = min(len(lst)-rows+1, offset+rows-2) - selected = min(len(lst)-rows+1, selected+rows-2) - elif k == curses.KEY_PPAGE: - offset = max(0, offset-rows+2) - selected = max(0, selected-rows+2) - elif k == curses.KEY_HOME: - offset = 0 - selected = 0 - elif k == curses.KEY_END: - offset = len(lst)-rows+1 - selected = len(lst)-1 - elif k == curses.KEY_ENTER or k == 10: - return {"index": selected, "action": "select"} - elif k == ord('q'): - return {"index": selected, "action": "quit"} - elif k == ord('e'): - return {"index": selected, "action": "edit"} - elif k == ord('c'): - return {"index": selected, "action": "create"} - elif k == ord('t'): - return {"index": selected, "action": "today"} - stdscr.refresh() - -def enter_value(stdscr, prefix, row): - """ - Creates a prompt to enter a value on the given row - """ - title = "" - stdscr.addstr(row,0, prefix + title) - k = stdscr.getch() - while k != 10 and k != curses.KEY_ENTER: - if k in (curses.KEY_BACKSPACE, '\b', '\x7f'): - if len(title) > 0: - title = title[:-1] - else: - title += chr(k) - stdscr.deleteln() - stdscr.addstr(row,0, prefix + title) - k = stdscr.getch() - return title - -def m(stdscr): - """ - The main method for the ncurses wrapper - """ - items = util.get_tree("") - while True: - ret = pager(stdscr, [x["path"] + "\t" + x["title"] for x in items]) - if ret["action"] == "select": - selected = items[ret["index"]] - ret = pager(stdscr, main.get_single_page(selected["path"])["content"].split("\n")) - elif ret["action"] == "edit": - selected = items[ret["index"]] - main.edit({"path":selected["path"], "save": True}) - elif ret["action"] == "create": - stdscr.clear() - title = enter_value(stdscr, "Enter title: ", 0) - path = enter_value(stdscr, "Enter path: ", 1) - main.create({"path": path, "title": title}) - elif ret["action"] == "today": - main.today({}) - else: - break - diff --git a/wikijscmd/tui.py b/wikijscmd/tui.py new file mode 100644 index 0000000..16232bb --- /dev/null +++ b/wikijscmd/tui.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +import curses +from curses import wrapper + +from wikijscmd import util, commands + +def pager(stdscr, lst): + ''' + Runs a pager for each string item in lst + ''' + cols = stdscr.getmaxyx()[1] + rows = stdscr.getmaxyx()[0] + offset = 0 + selected = 0 + while True: + stdscr.clear() + for i in range(min(rows-1, len(lst))): + x = lst[i+offset] + if i+offset == selected: + stdscr.addstr(i, 0, x[:cols], curses.A_UNDERLINE) + else: + stdscr.addstr(i, 0, x[:cols]) + if offset == 0: + stdscr.addstr(rows-1, 0, "--top--", curses.A_REVERSE) + elif offset + rows <= len(lst): + stdscr.addstr(rows-1, 0, "--more--", curses.A_REVERSE) + else: + stdscr.addstr(rows-1, 0, "--end--", curses.A_REVERSE) + k = stdscr.getch() + if k == curses.KEY_DOWN or k == ord('j'): + selected = min(len(lst), selected+1) + if (selected - offset) > (2 * rows / 3): + offset = min(len(lst)-rows+1, offset+1) + elif k == curses.KEY_UP or k == ord('k'): + selected = max(0, selected-1) + if (selected - offset) < (rows / 3): + offset = max(0, offset-1) + elif k == curses.KEY_NPAGE: + offset = min(len(lst)-rows+1, offset+rows-2) + selected = min(len(lst)-rows+1, selected+rows-2) + elif k == curses.KEY_PPAGE: + offset = max(0, offset-rows+2) + selected = max(0, selected-rows+2) + elif k == curses.KEY_HOME: + offset = 0 + selected = 0 + elif k == curses.KEY_END: + offset = len(lst)-rows+1 + selected = len(lst)-1 + elif k == curses.KEY_ENTER or k == 10: + return {"index": selected, "action": "select"} + elif k == ord('q'): + return {"index": selected, "action": "quit"} + elif k == ord('e'): + return {"index": selected, "action": "edit"} + elif k == ord('c'): + return {"index": selected, "action": "create"} + elif k == ord('t'): + return {"index": selected, "action": "today"} + stdscr.refresh() + +def enter_value(stdscr, prefix, row): + """ + Creates a prompt to enter a value on the given row + """ + title = "" + stdscr.addstr(row,0, prefix + title) + k = stdscr.getch() + while k != 10 and k != curses.KEY_ENTER: + if k in (curses.KEY_BACKSPACE, '\b', '\x7f'): + if len(title) > 0: + title = title[:-1] + else: + title += chr(k) + stdscr.deleteln() + stdscr.addstr(row,0, prefix + title) + k = stdscr.getch() + return title + +def m(stdscr): + """ + The main method for the ncurses wrapper + """ + items = util.get_tree("") + while True: + ret = pager(stdscr, [x["path"] + "\t" + x["title"] for x in items]) + if ret["action"] == "select": + selected = items[ret["index"]] + ret = pager(stdscr, util.get_single_page(selected["path"])["content"].split("\n")) + elif ret["action"] == "edit": + selected = items[ret["index"]] + commands.edit(selected["path"], True) + elif ret["action"] == "create": + stdscr.clear() + title = enter_value(stdscr, "Enter title: ", 0) + path = enter_value(stdscr, "Enter path: ", 1) + commands.create(path, title) + elif ret["action"] == "today": + commands.today() + else: + break + +def tui(): + try: + wrapper(m) + except Exception as e: + raise e -- cgit v1.2.3