fordon_greeman / voidfiles

Branch: main
Switch branches/tags
main
theidioticdev add emacs 2079ec5 22h ago
251 lines · 8.4 KB Raw Blame History
1 ;;; emms-metaplaylist-mode.el --- A major mode for lists of Emms playlists -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2006-2021, 2023 Free Software Foundation, Inc.
4
5 ;; Author: Yoni Rabkin <yrk@gnu.org>
6
7 ;; This file is part of EMMS.
8
9 ;; EMMS is free software; you can redistribute it and/or
10 ;; modify it under the terms of the GNU General Public License
11 ;; as published by the Free Software Foundation; either version 3
12 ;; of the License, or (at your option) any later version.
13
14 ;; EMMS is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with EMMS; if not, write to the Free Software
21 ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 ;; 02110-1301, USA.
23
24 ;;; Commentary:
25 ;;
26 ;; `emms-metaplaylist-mode' creates an interactive list of all the
27 ;; Emms playlist buffers. The currently active buffer is
28 ;; highlighted. You can choose a buffer from the list with RET and get
29 ;; taken there.
30
31 ;;; Code:
32 (require 'emms)
33 (require 'emms-playlist-mode)
34
35
36 ;;; --------------------------------------------------------
37 ;;; Variables, customisation and faces
38 ;;; --------------------------------------------------------
39 (defgroup emms-metaplaylist-mode nil
40 "*The Emacs Multimedia System meta-playlist mode."
41 :prefix "emms-metaplaylist-mode-"
42 :group 'multimedia)
43
44 (defcustom emms-metaplaylist-mode-buffer-name "*Emms Playlist Buffers*"
45 "Name of the buffer in which Emms playlists will be listed."
46 :type 'string)
47
48 (defcustom emms-metaplaylist-mode-hooks nil
49 "List of hooks to run on entry to emms-metaplaylist-mode."
50 :type 'hook)
51
52 (defface emms-metaplaylist-mode-face
53 '((((class color) (background dark))
54 (:foreground "AntiqueWhite3"))
55 (((class color) (background light))
56 (:foreground "red3"))
57 (((type tty) (class mono))
58 (:inverse-video t))
59 (t (:background "WhiteSmoke")))
60 "Face for the buffer names in the playlists buffer.")
61
62 (defface emms-metaplaylist-mode-current-face
63 '((((class color) (background dark))
64 (:foreground "red2"))
65 (((class color) (background light))
66 (:background "red3" :foreground "white"))
67 (((type tty) (class mono))
68 (:inverse-video t))
69 (t (:background "red3")))
70 "Face for the current buffer name in the playlists buffer.")
71
72
73 ;;; --------------------------------------------------------
74 ;;; Keymap
75 ;;; --------------------------------------------------------
76 (defvar emms-metaplaylist-mode-map
77 (let ((map (make-sparse-keymap)))
78 (set-keymap-parent map text-mode-map)
79 (define-key map (kbd "n") #'next-line)
80 (define-key map (kbd "p") #'previous-line)
81 (define-key map (kbd "RET") #'emms-metaplaylist-mode-goto-current)
82 (define-key map (kbd "SPC") #'emms-metaplaylist-mode-set-active)
83 (define-key map (kbd "g") #'emms-metaplaylist-mode-update)
84 (define-key map (kbd "C") #'emms-metaplaylist-mode-new-buffer)
85 (define-key map (kbd "C-k") #'emms-metaplaylist-mode-kill-buffer)
86 (define-key map (kbd "c") #'emms-metaplaylist-mode-center-current)
87 (define-key map (kbd "q") #'kill-current-buffer)
88 (define-key map (kbd "v") #'emms-metaplaylist-mode-goto)
89 (define-key map (kbd "?") #'describe-mode)
90 map)
91 "Keymap for `emms-metaplaylist-mode'.")
92
93
94 ;;; --------------------------------------------------------
95 ;;; Metaplaylist
96 ;;; --------------------------------------------------------
97 (defun emms-metaplaylist-mode-goto-current ()
98 "Switch to the buffer at point."
99 (interactive)
100 (let ((buffer (get-buffer
101 (buffer-substring (line-beginning-position)
102 (line-end-position)))))
103 (emms-playlist-set-playlist-buffer buffer)
104 (switch-to-buffer buffer)))
105
106 (defun emms-metaplaylist-mode-goto ()
107 "Visit the playlist without making it current."
108 (interactive)
109 (let ((buffer (get-buffer
110 (buffer-substring (line-beginning-position)
111 (line-end-position)))))
112 (switch-to-buffer buffer)))
113
114 (defun emms-metaplaylist-mode-write (playlists)
115 "Print the sorted list of PLAYLISTS."
116 (delete-region (point-min) (point-max))
117 (mapc (lambda (buf)
118 (let ((inhibit-read-only t))
119 (insert (buffer-name buf))
120 (add-text-properties
121 (line-beginning-position) (line-end-position)
122 (list 'face
123 (if (eq buf emms-playlist-buffer)
124 'emms-metaplaylist-mode-current-face
125 'emms-metaplaylist-mode-face)))
126 (newline)))
127 playlists))
128
129 ;; Emms' list changes order, and that's OK, but we want something
130 ;; stable for display purposes.
131 (defun emms-metaplaylist-mode-sorted-buffer-list ()
132 "Return a sorted list of playlist buffers."
133 (sort
134 (copy-tree
135 (emms-playlist-buffer-list))
136 #'(lambda (a b)
137 (string< (buffer-name a)
138 (buffer-name b)))))
139
140 (defun emms-metaplaylist-mode-center-current ()
141 "Center on the current playlist buffer"
142 (interactive)
143 (when (buffer-name emms-playlist-buffer)
144 (let ((p nil))
145 (save-excursion
146 (goto-char (point-min))
147 (setq p (search-forward-regexp (regexp-quote
148 (buffer-name emms-playlist-buffer))
149 (point-max) t)))
150 (when (not p) (error "cannot not find the current playlist buffer"))
151 (goto-char p)
152 (goto-char (line-beginning-position)))))
153
154 (defun emms-metaplaylist-mode-create ()
155 "Create the meta-playlist buffer."
156 (let ((name emms-metaplaylist-mode-buffer-name)
157 (playlists (emms-metaplaylist-mode-sorted-buffer-list)))
158 (if playlists
159 (with-current-buffer (get-buffer-create name)
160 (emms-metaplaylist-mode)
161 (emms-metaplaylist-mode-write playlists)
162 (emms-metaplaylist-mode-center-current)
163 (current-buffer))
164 (error "No Emms playlist buffers"))))
165
166 (defun emms-metaplaylist-mode-assert-buffer ()
167 "Assert that we are in the metaplaylist mode buffer."
168 (when (not (eq (current-buffer)
169 (get-buffer emms-metaplaylist-mode-buffer-name)))
170 (error "not the metalplaylist buffer")))
171
172 (defun emms-metaplaylist-mode-update ()
173 "Update the metalplaylist display."
174 (interactive)
175 (emms-metaplaylist-mode-assert-buffer)
176 (let ((inhibit-read-only t))
177 (emms-metaplaylist-mode-write
178 (emms-metaplaylist-mode-sorted-buffer-list)))
179 (emms-metaplaylist-mode-center-current))
180
181 (defun emms-metaplaylist-mode-kill-buffer ()
182 "Kill the buffer at point"
183 (interactive)
184 (let ((buffer (get-buffer
185 (buffer-substring (line-beginning-position)
186 (line-end-position)))))
187 (when (not buffer)
188 (error "can't find buffer at point"))
189 (if (y-or-n-p (format "kill playlist buffer \"%s\"?"
190 (buffer-name buffer)))
191 (kill-buffer buffer)
192 (message "Buffer kill aborted."))
193 (emms-metaplaylist-mode-update)))
194
195
196 ;;; --------------------------------------------------------
197 ;;; Playlist Management
198 ;;; --------------------------------------------------------
199 (defun emms-metaplaylist-mode-new-buffer (buffer-name)
200 "Creates a new buffer playlist buffer BUFFER-NAME."
201 (interactive "sBuffer Name: ")
202 (if (get-buffer buffer-name)
203 (error "Buffer must not exist.")
204 (let ((buf (get-buffer-create buffer-name)))
205 (with-current-buffer buf
206 (emms-playlist-mode)
207 (setq emms-playlist-buffer-p t)))
208 (emms-metaplaylist-mode-go)
209 (emms-metaplaylist-mode-update)))
210
211 (defun emms-metaplaylist-mode-set-active ()
212 "Set the buffer at point to be the active playlist."
213 (interactive)
214 (emms-playlist-set-playlist-buffer
215 (get-buffer (buffer-substring (line-beginning-position) (line-end-position))))
216 (emms-metaplaylist-mode-update))
217
218
219 ;;; --------------------------------------------------------
220 ;;; Mode entry
221 ;;; --------------------------------------------------------
222 (defun emms-metaplaylist-mode-go ()
223 "Single entry point to the metaplaylist interface."
224 (interactive)
225 (let ((mpm-buffer (get-buffer emms-metaplaylist-mode-buffer-name)))
226 (if mpm-buffer
227 (with-current-buffer mpm-buffer
228 (emms-metaplaylist-mode-update))
229 (setq mpm-buffer (emms-metaplaylist-mode-create)))
230 (switch-to-buffer mpm-buffer)))
231
232 (defun emms-metaplaylist-mode ()
233 "A major mode for Emms playlists.
234
235 \\{emms-metaplaylist-mode-map}"
236 ;; (interactive)
237 (kill-all-local-variables)
238
239 (use-local-map emms-metaplaylist-mode-map)
240 (setq major-mode 'emms-metaplaylist-mode
241 mode-name "Emms-MetaPlaylist")
242
243 (setq buffer-read-only t)
244
245 (run-hooks 'emms-metaplaylist-mode-hooks))
246
247
248 (provide 'emms-metaplaylist-mode)
249
250
251 ;;; emms-metaplaylist-mode.el ends here