From 4822a5f4c0c9b230863b5a68f4aa890136e11c7b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 15 Jul 2023 08:35:10 -0400 Subject: [PATCH] code documentation and refactoring --- src/lemmold/core.clj | 168 +++++++++++++++++++++++++++++++++---------- 1 file changed, 129 insertions(+), 39 deletions(-) diff --git a/src/lemmold/core.clj b/src/lemmold/core.clj index c08d30f..ab366d4 100644 --- a/src/lemmold/core.clj +++ b/src/lemmold/core.clj @@ -2,19 +2,42 @@ (:require [clj-http.client :as client]) (:require [clojure.data.json :as json])) -(def POST-LIST "/post/list") -(def COMMENTS "/comment/list") - -(defn make-api-url [inst endpoint] - (str "https://" inst "/api/v3" endpoint)) - -(defn api-call [api-url query-params] +(def DEFAULT-INSTANCE + "The default instance to access." + "lemmy.ml") +(def POST-PAGESIZE + "Number of posts to show per 'page'. Set by the API." + 5) +(def COMMENT-PAGESIZE + "Number of comments to show per 'page'. Kept low for smaller screens." + 1) +(def COMMENT-LIMIT + "Maximum number of comments to retrieve for a post." + 50) + +(def POST-LIST + "API endpoint for post list." + "/post/list") +(def COMMENTS + "API endpoint for comment list (of a given post)." + "/comment/list") + +(defn make-api-url + "Builds URL for API request given the instance and endpoint." + [inst endpoint] + (str "https://" inst "/api/v3" endpoint)) + +(defn api-call + "Completes an API request, returning the processed JSON." + [api-url query-params] (-> api-url (client/get {:accept :json :query-params query-params}) (get :body) (json/read-str))) -(defn post-list [instance community page] +(defn post-list + "Fetches a post list from the given instance and endpoint." + [instance community page] (let [query-params (cond-> {:sort "Hot" :page (str page)} (not (empty? community)) (assoc :community_name community))] @@ -22,12 +45,17 @@ (api-call query-params) (get "posts")))) -(defn comments-list [instance post] +(defn comments-list + "Fetches the comment list for a given post." + [instance post] (-> (make-api-url instance COMMENTS) - (api-call {:limit "50" :post_id (str (get-in post ["post" "id"]))}) + (api-call {:limit (str COMMENT-LIMIT) + :post_id (str (get-in post ["post" "id"]))}) (get "comments"))) -(defn show-post-item [index post] +(defn show-post-item + "Renders a listing of the given post. Index is for user selection." + [index post] (let [items [["creator" "name"] ["community" "name"] ["post" "name"] @@ -36,26 +64,35 @@ data (cons (inc index) (mapv (partial get-in post) items))] (apply (partial printf "%d. %s on %s\n %s\n at %s (%d comments)\n\n") data))) -(defn show-comment-item [commnt] +(defn show-comment-item + "Renders the given comment (from a post)." + [commnt] (println (get-in commnt ["creator" "name"]) "says:") (println (get-in commnt ["comment" "content"])) - (println) - ) + (println)) -(defn show-posts [posts] - (doseq [index (range 0 5)] +(defn show-posts + "Displays a page's worth of post listings." + [posts] + (doseq [index (range 0 POST-PAGESIZE)] (show-post-item index (nth posts index)))) -(defn show-comments [comments] - (doseq [commnt (take 1 comments)] +(defn show-comments + "Displays a page's worth of comments." + [comments] + (doseq [commnt (take COMMENT-PAGESIZE comments)] (show-comment-item commnt))) -(defn show-posts-prompt [] - (print "#NPQ> ") +(defn show-posts-prompt + "Collects user input at post listing menu." + [] + (print "#NPCIQ> ") (flush) (first (read-line))) -(defn show-comments-prompt [] +(defn show-comments-prompt + "Collects user input at comment listing menu." + [] (print "BNP> ") (flush) (first (read-line))) @@ -66,37 +103,90 @@ (read-line)) (defn show-instance-prompt [] - (print "Enter instance name [lemmy.ml]: ") + (printf "Enter instance name [%s]: " DEFAULT-INSTANCE) (flush) - (let [inst (read-line)] (if (empty? inst) "lemmy.ml" inst))) + (let [inst (read-line)] (if (empty? inst) DEFAULT-INSTANCE inst))) -(defn view-post [instance post] +(defn view-post + "Main loop for viewing a post and its comments." + [instance post] (loop [offset 0 comments (comments-list instance post)] (println) - (show-comments (if (pos? offset) (drop (* 1 offset) comments) comments)) + (show-comments (drop (* COMMENT-PAGESIZE offset) comments)) (case (show-comments-prompt) \B (println) \N (recur (inc offset) comments) \P (recur (dec offset) comments) (do (println "Unknown command.") (recur offset comments))))) -(defn view-page [instance init-community] - (loop [top true community init-community page 1 posts (post-list instance community page)] +(defn view-nth-post + "Views the index-th post from the current post list." + [state posts index] + (view-post + (:instance state) + (nth posts (cond-> (+ 5 index) (:top state) (- 5)))) + state) + +(defn get-post-list + "Fetches a new list of posts given the current (view-page) state." + [state] + (post-list (:instance state) (:community state) (:page state))) + +(defn next-page + "Updates state for viewing the next page of posts." + [state] + (if (:top state) + (assoc state :top false) + (-> state (assoc :top true) (update :page inc)))) + +(defn prev-page + "Updates state for viewing the previous page of posts." + [state] + (if-not (:top state) + (assoc state :top true) + (-> state (assoc :top false) (update :page dec)))) + +(defn change-community + "Updates state for viewing a different community." + [state] + (-> state + (assoc :top true) + (assoc :page 1) + (assoc :community (show-community-prompt)))) + +(defn change-instance + "Updates state for viewing a different instance." + [state] + (-> state + (assoc :instance (show-instance-prompt)) + (change-community))) + +(defn view-page + "Main loop for viewing posts listings." + [init-instance init-community] + (loop [state {:top true + :instance init-instance + :community init-community + :page 1} + posts (get-post-list state)] (println) - (show-posts (if top posts (drop 5 posts))) + (show-posts (if (:top state) posts (drop POST-PAGESIZE posts))) (case (show-posts-prompt) - \N (if top (recur false community page posts) - (recur true community (inc page) (post-list instance community (inc page)))) - \P (if top (recur false community (dec page) (post-list instance community (dec page))) - (recur true community page posts)) + \N (let [new-state (next-page state)] + (recur new-state (if (:top new-state) (get-post-list new-state) posts))) + \P (let [new-state (prev-page state)] + (recur new-state (if (:top new-state) posts (get-post-list new-state)))) \Q (println) - \1 (do (view-post instance (nth posts (cond-> 5 top (- 5)))) (recur top community page posts)) - \2 (do (view-post instance (nth posts (cond-> 6 top (- 5)))) (recur top community page posts)) - \3 (do (view-post instance (nth posts (cond-> 7 top (- 5)))) (recur top community page posts)) - \4 (do (view-post instance (nth posts (cond-> 8 top (- 5)))) (recur top community page posts)) - \5 (do (view-post instance (nth posts (cond-> 9 top (- 5)))) (recur top community page posts)) - \C (let [comm (show-community-prompt)] (recur true comm 1 (post-list instance comm page))) - (do (println "Unknown command.") (recur top community page posts))))) + \1 (recur (view-nth-post state posts 0) posts) + \2 (recur (view-nth-post state posts 1) posts) + \3 (recur (view-nth-post state posts 2) posts) + \4 (recur (view-nth-post state posts 3) posts) + \5 (recur (view-nth-post state posts 4) posts) + \C (let [new-state (change-community state)] + (recur new-state (get-post-list new-state))) + \I (let [new-state (change-instance state)] + (recur new-state (get-post-list new-state))) + (do (println "Unknown command.") (recur state posts))))) (defn -main [& args] (println "Welcome to lemmold, your old-school Lemmy browser!")