From 481296101404e71b904e39bff18ed8a2923da3d0 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 4 Jun 2022 20:55:46 +0530 Subject: [PATCH] Added the ability to search posts and manage them. Plus minor changes. --- gempost | 154 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 65 deletions(-) diff --git a/gempost b/gempost index 622e0df..4bd27a0 100755 --- a/gempost +++ b/gempost @@ -30,7 +30,7 @@ postDir = wdir + "postdir/" # all post files along with the archive.gmi are stor indexFile = wdir + "postIndex" # the index is maintained in this file editor = "nano --restricted -t" -def menuFunction(menu = []): +def menuFunction(menu = [], headerLine = "Use the arrow keys or j,k to make a selection. Press 'c' to cancel.\n"): stdscr = curses.initscr() # initializing curses curses.noecho() curses.cbreak() @@ -49,7 +49,6 @@ def menuFunction(menu = []): if (menu == []): # do nothing if list is empty curses.endwin() - print("\nYou don't have any posts yet.") return None highlight, highlight_prev = 0, 0 # variable that controls which entry is selected, variable that stores its previous value @@ -87,7 +86,8 @@ def menuFunction(menu = []): endOfPage = len(imenu) highlight = endOfPage - 1 - stdscr.addstr("Use the arrow keys or j,k to make a selection. Press 'c' to cancel.\n") + #stdscr.addstr("Use the arrow keys or j,k to make a selection. Press 'c' to cancel.\n") + stdscr.addstr(headerLine) for sno in range(len(imenu)): if (sno == highlight): @@ -209,28 +209,12 @@ def newpost(title, existing_content = None): else: modified = True # modify the function if doing this for existing file - """ - uf = input("\n1 - (DEFAULT) automatically generate filename using a random hash\n2 - enter filename manually\n-> ") - if (uf == '2'): - while True: - filename = input("\nFilename (.gmi will be added automatically): ") - if filename[-1] == '\n': # removing newline character that creeps in there due to input() - filename = filename[:-1] - if f"{filename}.gmi" in listdir(f"{wdir}postdir/"): - prYellow("This filename already exists. Please use a different filename.") - else: - break - else: - filename = sha1(str(f"{title}{random()}").encode("utf-8")).hexdigest() # generating a unique filename - """ filename = sha1(str(f"{title}{random()}").encode("utf-8")).hexdigest() # generating a unique filename exec(f"touch {wdir + filename}.gmi") # creating empty file - ch = input("\nAdd an ASCII Art header to your post? (define it in blogpostHeader.gmi): ([y]/n) ") - if (ch == 'n' or ch == 'N'): - pass - else: + che = input("\nAdd an ASCII Art header to your post? (define it in blogpostHeader.gmi): (y/[n]) ") + if (che == 'y' or che == 'Y'): try: with open(f"{wdir}blogpostHeader.gmi") as a: # checking if header for each post has been defined postHeader = a.readlines() @@ -238,12 +222,12 @@ def newpost(title, existing_content = None): with open(f"{wdir + filename}.gmi",'w') as f: f.writelines(postHeader) except FileNotFoundError: - postHeader = "" + postHeader = [""] + else: + postHeader = [""] if modified: # add content to file using the existing_content list instead of opening editor - if (ch != 'n' or ch != 'N'): - with open(f"{wdir}blogpostHeader.gmi") as a: # loading post header - postHeader = a.readlines() + if (che != 'y' or che == 'Y'): with open(f"{wdir+filename}.gmi", 'w') as o: o.writelines(postHeader + existing_content) else: @@ -279,30 +263,29 @@ def newpost(title, existing_content = None): prGreen("\n Your post is live!") # yay? -def manage(): - allposts = [] # storing all indexFile entries inside a list - with open(f"{indexFile}",'r') as i: - allposts = i.readlines() +def manage(direct = ""): + """ Posts management function. If direct is given a string filename, then that filename is selected directly. """ + if (direct == ""): + with open(f"{indexFile}",'r') as i: # storing all indexFile entries inside a list + allposts = i.readlines() - #if (len(allposts) == 0): # exit function if no files in index - #return 0 - - postsList = [] - for i in allposts: # creating a list containing titles corresponding to filenames - postsList.append([i[56:-1],i[11:51]]) + postsList = [] + for i in allposts: # creating a list containing titles corresponding to filenames + postsList.append([i[56:-1],i[11:51]]) - menuItems = [] - for i in postsList: # formatting it into a string list for the ncurses menu function - menuItems.append(f"{i[0]} | {i[1]}") - + menuItems = [] + for i in postsList: # formatting it into a string list for the ncurses menu function + menuItems.append(f"{i[0]} | {i[1]}") - which = menuFunction(menuItems) + which = menuFunction(menuItems) - if (which == None): # menuFunction returns None if the list supplied to it is empty - print("\nCancelled.") - return 0 + if (which == None): # menuFunction returns None if the list supplied to it is empty + if (menuItems == []): + print("You don't have any posts yet.") + print("\nCancelled.") + return 0 - print(f"\nYou have selected:\n\nTitle: {postsList[which][0]}\nFilename: {postsList[which][1]}.gmi") + print(f"\nYou have selected:\n\nTITLE: {postsList[which][0]}\nFILENAME: {postsList[which][1]}.gmi") try: mode = int(input("\nSELECT MODE:\n1 - EDIT\n2 - DELETE\n3 - CANCEL\n-> ")) # what does the user want to do with the selection? @@ -311,34 +294,45 @@ def manage(): return 0 if (mode == 1): # if mode is EDIT, open editor with the post file - print(f'\nEditing "{postsList[which][0]}" ...') - exec(f"{editor} {postDir}{postsList[which][1]}.gmi") - prGreen("Post updated.") + if (direct == ""): + print(f'\nEditing "{postsList[which][0]}" ...') + exec(f"{editor} {postDir}{postsList[which][1]}.gmi") + else: + print(f'\nEditing {direct}.gmi') + exec(f"{editor} {postDir}{direct}.gmi") + prGreen("\nPost updated.") elif (mode == 2): # for DELETE mode, first delete post file, delete its reference from {wdir}postIndex, and rebuild the {wdir}posts.gmi and {postDir}archive.gmi files - exec(f"mv {postDir}{postsList[which][1]}.gmi {wdir}trash/") - print(f"\nfile moved to trash") - exec(f"sed -i '/{postsList[which][1]}.gmi/d' {indexFile}") - print(f"postIndex updated") + if (direct == ""): + exec(f"mv {postDir}{postsList[which][1]}.gmi {wdir}trash/") + exec(f"sed -i '/{postsList[which][1]}.gmi/d' {indexFile}") + else: + exec(f"mv {postDir}{direct}.gmi {wdir}trash/") + exec(f"sed -i '/{direct}.gmi/d' {indexFile}") rebuildReferences(None, None, "delete") + print(f"\nfile moved to trash") + print(f"postIndex updated") print("rebuilt posts.gmi, archive.gmi") prGreen("All done.") + elif (mode == 3): print("\nCancelled.") else: pass # information strings -helpText = f""" +helpText = """ gempost (v0.6) - *experimental* gemlog manager for tilde.team Available arguments: post - create a new post Usage: - post (without arguments) Write a blog post from scratch. - post [path to file without braces] Post from .gmi file. First line will be used as heading. + post (without arguments) Write a blog post from scratch + post [path to file] Post from .gmi file, first line will be used as heading manage - edit or delete your posts + search [search term] - Search your post headings for a search term and manage just those posts + purge - premanently delete the files in trash/ init - set up your public_gemini/ directory for gempost reset - delete all posts and re-initialize public_gemini/ @@ -429,23 +423,19 @@ elif (arg == "qs"): elif (arg == "post"): checkInit() - if (len(argv) == 3): # checking if more than 1 arg (except python) to see if source file has been supplied + if (len(argv) >= 3): # checking if more than 1 arg (except python) to see if source file has been supplied filePath = argv[2] # storing that file's path in a var print(f"Using file {filePath}") # tell the user that the program is using a source file - exiting_content, firstLine = [], "" # content of the file, and title respectively + exiting_content = [] # stores content of the file + + title = input("\nPOST TITLE: ") + try: with open(filePath, 'r') as f: # populating file content and title variables existing_content = f.readlines() - firstLine = existing_content[0][2:] # first line, used as title + + newpost(title, existing_content) - if (firstLine[-1] == '\n'): # if there is a NewLine character at the end of title line (probably will be), remove it from post title - firstLine = firstLine[:-1] - - if (len(firstLine) == 0): # message and exit if title empty - prRed("Post title cannot be empty.") - exit() - else: - newpost(firstLine, existing_content) except FileNotFoundError: prRed("Invalid file path / file does not exist.") @@ -462,6 +452,40 @@ elif (arg == "manage"): checkInit() manage() +elif (arg == "search"): + checkInit() + + if (len(argv) >= 3): # getting search term from args + t = argv[2] + else: + prYellow("No search term specified.") + exit() + + allposts = [] # storing all indexFile entries inside a list + with open(f"{indexFile}",'r') as i: + allposts = i.readlines() + + postsList = [] + for i in allposts: # creating a list containing titles corresponding to filenames for posts that have the search term in their titles + if t in i[56:-1]: + postsList.append([i[56:-1],i[11:51]]) + + menuItems = [] + for i in postsList: # formatting it into a string list for the ncurses menu function + menuItems.append(f"{i[0]} | {i[1]}") + + which = menuFunction(menuItems, "Search listing:\n") + + if (which == None): # menuFunction returns None if the list supplied to it is empty + print("\nNo items found.") + exit() + else: + print(f"\nYou have selected:\n\nTITLE: {postsList[which][0]}\nFILENAME: {postsList[which][1]}.gmi") + + c = input("\nOpen manager? (y/[n]) ") + if (c == 'y' or c == 'Y'): + manage(f"{postsList[which][1]}") + elif (arg == "purge"): # permanently delete trashed posts checkInit() if (len(listdir(f"{wdir}trash/")) == 0):