From 26229fac9c93a427a85e86b899ed54639116de9a Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Mon, 7 Sep 2020 13:19:52 +0530 Subject: [PATCH] Allow searching from Emacs Signed-off-by: Joseph Nuthalapati --- README.md | 4 +++- nimcoon.el | 42 ++++++++++++++++++++++++++++++++++++------ src/lib.nim | 3 +-- src/nimcoon.nim | 16 ++++++++++++++-- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a879180..6bac1ee 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,9 @@ I tried all kinds of alternative YouTube players for the desktop. Most are eithe YouTube's business incentive is to make you watch as many videos as possible. If you open the YouTube website and are logged into it, you will just get distracted by recommendations and forget why you opened it in the first place. You might have wanted to watch a conference talk but end up going down a rabbit hole of other "interesting" videos customized for you. -NimCoon has a spartan design. It doesn't even show images of the search results. I have had better success with managing my YouTube consumption after shifting to this tool. Pinafore's wellness settings are an inspiration for this. +NimCoon has a spartan design. It doesn't even show images of the search results. It doesn't let you browse YouTube. You have to explicitly search for something. + +I have had better success with managing my YouTube consumption after shifting to this tool. Settings inspired by Pinafore's wellness settings. ### Why no issues or merge requests? diff --git a/nimcoon.el b/nimcoon.el index 5fdb2c9..5146a91 100644 --- a/nimcoon.el +++ b/nimcoon.el @@ -5,8 +5,8 @@ ;;; (load! "nimcoon") ;;; Non-interactive functions to respond to URL clicks -(defun nimcoon-play-url (url) - "Play given url in NimCoon" +(defun nimcoon-play-url (url &rest args) + "Play given URL in NimCoon." (start-process "nimcoon" nil "nimcoon" url)) ;; Play all YouTube URLs in NimCoon @@ -15,22 +15,48 @@ (("youtu\\.?be" . nimcoon-play-url) ("." . browse-url-default-browser)))) +(defun run-nimcoon(args query) + "Search by QUERY and play in NimCoon." + (call-process "nimcoon" nil 0 nil args query)) + ;;; Interactive functions (defun nimcoon-feeling-lucky-music(query) (interactive "sSearch query: ") - (call-process "nimcoon" nil 0 nil "-m" "-l" (format "'%s'" query))) + (run-nimcoon "-ml" query)) (defun nimcoon-feeling-lucky-video(query) (interactive "sSearch query: ") - (call-process "nimcoon" nil 0 nil "-l" (format "'%s'" query))) + (run-nimcoon "-l" query)) (defun nimcoon-download-video(query) (interactive "sSearch query: ") - (call-process "nimcoon" nil 0 nil "-d" "-l" (format "'%s'" query))) + (run-nimcoon "-dl" query)) (defun nimcoon-download-music(query) (interactive "sSearch query: ") - (call-process "nimcoon" nil 0 nil "-d" "-l" "-m" (format "'%s'" query))) + (run-nimcoon "-dlm" query)) + +;; Assumes only one process exists. Must capture the pid of the running NimCoon process and only kill it. +(defun nimcoon-kill-background-processes() + "Kill NimCoon process running in the background. Useful for stopping background music." + (interactive) + (shell-command "kill `pgrep nimcoon` `pgrep mpv` `pgrep vlc`")) + +(defun nimcoon-search-video(query) + "Search for a video by QUERY." + (interactive "sSearch query: ") + (with-output-to-temp-buffer "*NimCoon search results*" + (call-process "nimcoon" nil "*NimCoon search results*" t "--non-interactive" query) + (with-current-buffer "*NimCoon search results*" + (org-mode)))) + +(defun nimcoon-search-music(query) + "Search for a video by QUERY." + (interactive "sSearch query: ") + (with-output-to-temp-buffer "*NimCoon search results*" + (call-process "nimcoon" nil "*NimCoon search results*" t "--music" "--non-interactive" query) + (with-current-buffer "*NimCoon search results*" + (org-mode)))) ;;; Keybindings (map! :leader @@ -39,5 +65,9 @@ (:prefix ("d" . "Download") :desc "Video" "v" #'nimcoon-download-video :desc "Music" "m" #'nimcoon-download-music) + (:prefix ("s" . "Search") + :desc "Video" "v" #'nimcoon-search-video + :desc "Music" "m" #'nimcoon-search-music) + :desc "Kill" "k" #'nimcoon-kill-process :desc "Video" "v" #'nimcoon-feeling-lucky-video :desc "Music" "m" #'nimcoon-feeling-lucky-music)) diff --git a/src/lib.nim b/src/lib.nim index e242532..16082c5 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -49,7 +49,6 @@ proc presentVideoOptions*(searchResults: SearchResults) = for index, (title, url) in searchResults: styledEcho $index, ". ", styleBright, fgMagenta, title, "\n", resetStyle, fgCyan, " ", url, "\n" - func buildPlayerArgs(url: string, options: Table[string, bool], player: string): seq[string] = let musicOnly = if options["musicOnly"]: "--no-video" else: "" let fullScreen = if options["fullScreen"]: "--fullscreen" else: "" @@ -63,7 +62,7 @@ proc play*(player: string, options: Table[string, bool], url: string, title: str if "--no-video" in args: discard execShellCmd(&"{player} {args.join(\" \")}") else: - discard execProcess(player, args=args, options=processOptions) + discard startProcess(player, args=args, options=processOptions) func buildMusicDownloadArgs(url: string): seq[string] = diff --git a/src/nimcoon.nim b/src/nimcoon.nim index f3b29c6..e1cbb23 100644 --- a/src/nimcoon.nim +++ b/src/nimcoon.nim @@ -14,7 +14,7 @@ import proc parseArguments(): CommandLineOptions = var searchQuery = "" - options = to_table({"musicOnly": false, "feelingLucky": false, "fullScreen": false, "download": false}) + options = to_table({"musicOnly": false, "feelingLucky": false, "fullScreen": false, "download": false, "non-interactive": false}) for kind, key, value in getopt(): case kind @@ -26,12 +26,17 @@ proc parseArguments(): CommandLineOptions = of "l", "lucky": options["feelingLucky"] = true of "f", "full-screen": options["fullScreen"] = true of "d", "download": options["download"] = true + of "n", "non-interactive": options["non-interactive"] = true of cmdEnd: discard + if searchQuery == "": + stderr.writeLine "NimCoon doesn't permit browsing. You must provide a search query." + quit(1) + (searchQuery, options) -proc isValidOptions*(options: Options): bool = +proc isValidOptions(options: Options): bool = # Check for invalid combinations of options var invalidCombinations = [("musicOnly", "fullScreen"), ("download", "fullScreen")] result = true @@ -56,6 +61,13 @@ proc main() = quit(0) let searchResults = getSearchResults(searchQuery) + if options["non-interactive"]: + for index, (title, url) in searchResults: + echo title + echo url + echo "" + quit(0) + let numResults = min(limit, len(searchResults)) present(searchResults, options, (0, numResults-1), player) -- 2.43.0