summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yeetube-buffer.el192
-rw-r--r--yeetube.el109
2 files changed, 80 insertions, 221 deletions
diff --git a/yeetube-buffer.el b/yeetube-buffer.el
deleted file mode 100644
index 379a8eb..0000000
--- a/yeetube-buffer.el
+++ /dev/null
@@ -1,192 +0,0 @@
-;;; yeetube-buffer.el --- Yeetube Buffer -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2023 Thanos Apollo
-
-;; Author: Thanos Apollo <[email protected]>
-;; Keywords: extensions youtube videos
-;; URL: https://git.thanosapollo.org/yeetube
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This package is an extension for yeetube, to create a custom
-;; *yeetube* buffer.
-
-;;; Code:
-
-(require 'cl-lib)
-
-(defcustom yeetube-buffer-display-emojis nil
- "Display video title's emojis.
-
-Emojis cause formatting issues, this should be off by default."
- :type 'boolean
- :group 'yeetube)
-
-(defgroup yeetube-buffer-faces nil
- "Faces used by yeetube."
- :group 'yeetube
- :tag "Yeetube Faces"
- :prefix 'yeetube-face)
-
-(defface yeetube-buffer-face-header-query
- '((t :inherit font-lock-function-name-face))
- "Face used for the video published date."
- :group 'yeetube-buffer-faces)
-
-(defface yeetube-buffer-face-duration
- '((t :inherit font-lock-string-face))
- "Face used for the video duration."
- :group 'yeetube-buffer-faces)
-
-(defface yeetube-buffer-face-view-count
- '((t :inherit font-lock-keyword-face))
- "Face used for the video view count."
- :group 'yeetube-buffer-faces)
-
-(defface yeetube-buffer-face-title
- '((t :inherit font-lock-variable-use-face))
- "Face used for video title."
- :group 'yeetube-buffer-faces)
-
-(defface yeetube-buffer-face-channel
- '((t :inherit font-lock-function-call-face))
- "Face used for video channel name."
- :group 'yeetube-buffer-faces)
-
-(defun yeetube-buffer-strip-emojis (str)
- "Remove characters which are part of the `emoji' script from STR."
- (cl-remove-if (lambda (c)
- (equal (aref char-script-table c) 'emoji))
- str))
-
-(defun yeetube-buffer-fix-view-count (view-count)
- "Fix VIEW-COUNT display issues."
- (replace-regexp-in-string "[^0-9]" "" view-count))
-
-(defun yeetube-buffer-view-count-add-commas (string)
- "Add commas for STRING."
- (let ((result "")
- (len (length string)))
- (dotimes (i len)
- (setf result (concat (substring string (- len i 1) (- len i)) result))
- (when (and (> (- len (1+ i)) 0)
- (= (% (1+ i) 3) 0))
- (setf result (concat "," result))))
- result))
-
-;;; Formatting inspired from ytel
-(defun yeetube-buffer--format-header-title (query)
- "Format header for QUERY."
- (let* ((n (string-width query))
- (extra-chars (- n 53))
- (formatted-string
- (if (<= extra-chars 0)
- (concat query
- (make-string (abs extra-chars) ?\ )
- " ")
- (concat (seq-subseq query 0 50)
- "... " ))))
- (propertize formatted-string 'face 'yeetube-buffer-face-header-query)))
-
-(defun yeetube-buffer--format-title (title)
- "Format a video TITLE to be inserted in the *yeetube* buffer."
- (let* ((n (string-width title))
- (extra-chars (- n 60))
- (formatted-string
- (if (<= extra-chars 0)
- (concat title
- (make-string (abs extra-chars) ?\ )
- " ")
- (concat (seq-subseq title 0 57)
- "... " ))))
- (propertize formatted-string 'face 'yeetube-buffer-face-title)))
-
-(defun yeetube-buffer--format-view-count (view-count)
- "Format a video VIEW-COUNT to be inserted in the *yeetube* buffer."
- (let* ((n (string-width view-count))
- (extra-chars (- n 13))
- (formatted-string
- (if (<= extra-chars 0)
- (concat view-count
- (make-string (abs extra-chars) ?\ )
- " ")
- (concat (seq-subseq view-count 0 10)
- "..."))))
- (propertize formatted-string 'face 'yeetube-buffer-face-view-count)))
-
-(defun yeetube-buffer--format-video-duration (video-duration)
- "Format a video VIDEO-DURATION to be inserted in the *yeetube* buffer."
- (let* ((n (string-width video-duration))
- (extra-chars (- n 13))
- (formatted-string (if (<= extra-chars 0)
- (concat video-duration
- (make-string (abs extra-chars) ?\ )
- " ")
- (concat (seq-subseq video-duration 0 10)
- "..."))))
- (propertize formatted-string 'face 'yeetube-buffer-face-duration)))
-
-(defun yeetube-buffer--format-channel (channel)
- "Format a video CHANNEL to be inserted in the *yeetube* buffer."
- (let* ((n (string-width channel))
- (extra-chars (- n 15))
- (formatted-string
- (if (<= extra-chars 0)
- (concat channel
- (make-string (abs extra-chars) ?\ )
- " ")
- (concat (seq-subseq channel 0 11)
- "... " ))))
- (propertize formatted-string 'face 'yeetube-buffer-face-channel)))
-
-(defun yeetube-buffer--format-header (query)
- "Render header for *yeetube* buffer for QUERY."
- (setf header-line-format
- (concat
- "Search: " (yeetube-buffer--format-header-title query)
- (yeetube-buffer--format-view-count "Views")
- (yeetube-buffer--format-video-duration "Duration")
- (yeetube-buffer--format-channel "Channel"))))
-
-(defun yeetube-buffer-insert-content (content)
- "Insert formatted CONTENT."
- (insert
- (concat
- (yeetube-buffer--format-title (cl-getf content :title))
- (yeetube-buffer--format-view-count (yeetube-buffer-view-count-add-commas
- (yeetube-buffer-fix-view-count
- (cl-getf content :view-count))))
- (yeetube-buffer--format-video-duration (cl-getf content :duration))
- (yeetube-buffer--format-channel (cl-getf content :channel))
- "\n")))
-
-;;;###autoload
-(defun yeetube-buffer-create (query content buffer-mode)
- "Create *yeetube* buffer with BUFFER-MODE for search QUERY, displaying CONTENT."
- (with-current-buffer
- (switch-to-buffer (get-buffer-create "*yeetube*"))
- (funcall buffer-mode)
- (setf buffer-read-only nil)
- (erase-buffer)
- (yeetube-buffer--format-header query)
- (cl-loop for result in (reverse content)
- do (yeetube-buffer-insert-content result))
- (delete-char -1)
- (goto-char (point-min))
- (setf buffer-read-only t)))
-
-(provide 'yeetube-buffer)
-;;; yeetube-buffer.el ends here
diff --git a/yeetube.el b/yeetube.el
index a79bcef..01100cb 100644
--- a/yeetube.el
+++ b/yeetube.el
@@ -40,8 +40,8 @@
(require 'compat)
(require 'url)
+(require 'tabulated-list)
(require 'cl-lib)
-(require 'yeetube-buffer)
(require 'yeetube-mpv)
(defgroup yeetube nil
@@ -51,7 +51,7 @@
(defcustom yeetube-results-limit 20
"Define a limit for search results."
- :type 'natnump
+ :type 'number
:group 'yeetube)
(defcustom yeetube-player #'yeetube-mpv-play
@@ -73,6 +73,37 @@ Example Usage:
:type 'string
:group 'yeetube)
+(defgroup yeetube-faces nil
+ "Faces used by yeetube."
+ :group 'yeetube
+ :tag "Yeetube Faces"
+ :prefix 'yeetube-face)
+
+(defface yeetube-face-header-query
+ '((t :inherit font-lock-function-name-face))
+ "Face used for the video published date."
+ :group 'yeetube-faces)
+
+(defface yeetube-face-duration
+ '((t :inherit font-lock-string-face))
+ "Face used for the video duration."
+ :group 'yeetube-faces)
+
+(defface yeetube-face-view-count
+ '((t :inherit font-lock-keyword-face))
+ "Face used for the video view count."
+ :group 'yeetube-faces)
+
+(defface yeetube-face-title
+ '((t :inherit font-lock-variable-use-face))
+ "Face used for video title."
+ :group 'yeetube-faces)
+
+(defface yeetube-face-channel
+ '((t :inherit font-lock-function-call-face))
+ "Face used for video channel name."
+ :group 'yeetube-faces)
+
(defvar yeetube-invidious-instances
'("vid.puffyan.us"
"invidious.flokinet.to"
@@ -110,9 +141,7 @@ Keywords:
- :channel"
(unless (keywordp keyword)
(error "Value `%s' is not a keyword" keyword))
- (let ((video-info
- (cl-getf (nth (- (line-number-at-pos) 1) (reverse yeetube-content)) keyword)))
- video-info))
+ (cl-getf (tabulated-list-get-id) keyword))
(defun yeetube-get-url ()
"Get video url."
@@ -217,8 +246,10 @@ WHERE indicates where in the buffer the update should happen."
(decode-coding-region (point-min) (point-max) 'utf-8)
(goto-char (point-min))
(toggle-enable-multibyte-characters)
- (yeetube-get-content)
- (yeetube-buffer-create query yeetube-content 'yeetube-mode)))
+ (yeetube-get-content))
+ (with-current-buffer
+ (switch-to-buffer (get-buffer-create (concat "*yeetube*")))
+ (yeetube-mode)))
;;;###autoload
(defun yeetube-browse-url ()
@@ -248,16 +279,17 @@ then for item."
("\\\\" . ""))
"Unicode character replacements.")
-;; Usually titles from youtube get messed up,
-;; This should fix some of the common issues.
-(defun yeetube---fix-title (title)
- "Adjust TITLE."
- (mapc (lambda (replacement)
- (setf title (replace-regexp-in-string (car replacement) (cdr replacement) title)))
- yeetube--title-replacements)
- (if yeetube-buffer-display-emojis
- title
- (yeetube-buffer-strip-emojis title)))
+(defun yeetube-view-count-format (string)
+ "Add commas for STRING."
+ (let* ((string (replace-regexp-in-string "[^0-9]" "" string))
+ (len (length string))
+ (result ""))
+ (cl-loop for i from 0 to (1- len)
+ do (setf result (concat (substring string (- len i 1) (- len i)) result))
+ if (and (> (- len (1+ i)) 0)
+ (= (% (1+ i) 3) 0))
+ do (setf result (concat "," result)))
+ result))
(defun yeetube-get-content ()
"Get content from youtube."
@@ -269,9 +301,8 @@ then for item."
(- (search-forward ",") 2))))
(unless (member videoid (car yeetube-content))
(yeetube-get-item "title") ;; Video Title
- (let ((title (yeetube---fix-title
- (buffer-substring (+ (point) 3)
- (- (search-forward ",\"") 5)))))
+ (let ((title (buffer-substring (+ (point) 3)
+ (- (search-forward ",\"") 5))))
(unless (member title (car yeetube-content))
(yeetube-get-item "viewcounttext") ;; View Count
(let ((view-count (buffer-substring (+ (point) 3)
@@ -284,7 +315,7 @@ then for item."
(- (search-forward ",") 2))))
(push (list :title title
:videoid videoid
- :view-count view-count
+ :view-count (yeetube-view-count-format view-count)
:duration video-duration
:channel channel)
yeetube-content))))))))))
@@ -371,16 +402,24 @@ prompt blank to keep the default name."
(setf download-counter (1+ download-counter))
(yeetube-download--ytdlp url name yeetube-download-audio-format)))))
-;; Yeetube Mode
+(defun yeetube-propertize-vector (content &rest fields-face-pairs)
+ "Create a vector with each item propertized with its corresponding face.
+CONTENT is a list of strings.
+FIELDS-FACE-PAIRS is a list of fields and faces."
+ (apply #'vector
+ (cl-loop for (field face) on fields-face-pairs by #'cddr
+ collect (propertize (cl-getf content field) 'face face))))
+
+;; Yeetube Mode
(defvar-keymap yeetube-mode-map
:doc "Keymap for yeetube commands"
"RET" #'yeetube-play
"M-RET" #'yeetube-search
"b" #'yeetube-browse-url
"d" #'yeetube-download-video
- "D" #'yeetube-change-download-directory
- "a" #'yeetube-change-download-audio-format
+ "D" #'yeetube-download-change-directory
+ "a" #'yeetube-download-change-audio-format
"p" #'yeetube-mpv-toggle-pause
"v" #'yeetube-mpv-toggle-video
"V" #'yeetube-mpv-toggle-no-video-flag
@@ -389,13 +428,25 @@ prompt blank to keep the default name."
"r" #'yeetube-replay
"q" #'quit-window)
-(define-derived-mode yeetube-mode special-mode "Yeetube"
+(define-derived-mode yeetube-mode tabulated-list-mode "Yeetube"
"Yeetube mode."
- :interactive t
- (abbrev-mode 0)
+ :keymap yeetube-mode-map
+ (setf tabulated-list-format [("Title" 60 t) ("Views" 12 t) ("Duration" 12 t) ("Channel" 12 t)]
+ tabulated-list-entries
+ (cl-map 'list
+ (lambda (content)
+ (list content
+ (yeetube-propertize-vector content
+ :title 'yeetube-face-title
+ :view-count 'yeetube-face-view-count
+ :duration 'yeetube-face-duration
+ :channel 'yeetube-face-channel)))
+ yeetube-content)
+ tabulated-list-sort-key (cons "Title" nil))
(display-line-numbers-mode 0)
- :lighter " yeetube-mode"
- :keymap yeetube-mode-map)
+ (tabulated-list-init-header)
+ (tabulated-list-print)
+ (hl-line-mode))
(provide 'yeetube)
;;; yeetube.el ends here