emms-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emms-patches] darcs patch: add a metadata browser - emms-browser.el (an


From: Damien Elmes
Subject: [Emms-patches] darcs patch: add a metadata browser - emms-browser.el (and 1 more)
Date: Thu, 8 Jun 2006 18:09:59 +0900 (JST)

Thu Jun  8 17:44:00 JST 2006  Damien Elmes <address@hidden>
  * add a metadata browser - emms-browser.el
  * preliminary work on a metadata browser - still alpha, but it's
    useable for me
  * also updated my email address in emms-cache.el (whoops)

Thu Jun  8 18:07:03 JST 2006  Damien Elmes <address@hidden>
  * fix RET on trailing \n
  \n isn't propertized which means hitting RET on a playlist or browser
  entry fails. this patch moves the point before trying to read the
  properties.
New patches:

[add a metadata browser - emms-browser.el
Damien Elmes <address@hidden>**20060608084400
 * preliminary work on a metadata browser - still alpha, but it's
   useable for me
 * also updated my email address in emms-cache.el (whoops)
] {
addfile ./emms-browser.el
hunk ./emms-browser.el 1
+;;; emms-browser.el --- provide a buffer to browse files
+
+;; Copyright (C) 2006  Damien Elmes <address@hidden>
+
+;; Author: Damien Elmes <address@hidden>
+;; Keywords: emms, mp3, mpeg, multimedia
+
+;; This file 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 2, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This code allows you to browse the metadata cache and add tracks to
+;; your playlist. To be properly useful, you should M-x
+;; emms-add-directory-tree to all the files you own at least once so
+;; that the cache is fully populated.
+
+;; To use, run (emms-devel) and then bind emms-smart-browse to a key,
+;; like:
+
+;; (global-set-key (kbd "<f2>") 'emms-smart-browse)
+
+;; The 'smart browsing' code attempts to link the browser and playlist
+;; windows together, so that closing one will close both. Activating
+;; it will toggle between three states:
+
+;; a) both windows displayed, with the browser focused
+;; b) focus switched to the playlist window
+;; c) the extra window closed, and both buffers buried
+
+;; Some useful keybindings in the browser buffer:
+
+;; SPC      - add all the tracks on the current line to the playlist
+;; RET      - do the same, and start the first added track playing
+;; /        - isearch through the available items
+;; q        - bury both buffers (if you use emms-smart-browse)
+
+;; If you just want access to the browser, try M-x
+;; emms-browse-by-TYPE, where TYPE is one of artist, album, genre or
+;; year.
+
+;; If you don't want to activate the code with (emms-devel), you can
+;; activate it manually with:
+
+;; (require 'emms-browser)
+
+;;; Code:
+
+(require 'emms-cache)
+
+;; --------------------------------------------------
+;; Variables and configuration
+;; --------------------------------------------------
+
+(defgroup emms-browser nil
+  "*The Emacs Multimedia System browser"
+  :prefix "emms-browser-"
+  :group 'multimedia
+  :group 'applications)
+
+(defcustom emms-browser-default-browsing-function
+  'emms-browse-by-artist
+  "The default browsing mode."
+  :group 'emms-browser
+  :type 'function)
+
+(defcustom emms-browser-comparison-test
+  'case-fold
+  "A method for comparing entries in the cache.
+The default is to compare case-insensitively."
+  :group 'emms-browser
+  :type 'symbol)
+
+(defcustom emms-browser-show-display-hook nil
+  "Hooks to run when starting or switching to a browser buffer."
+  :group 'emms-browser
+  :type 'hook)
+
+(defcustom emms-browser-hide-display-hook nil
+  "Hooks to run when burying or removing a browser buffer."
+  :group 'emms-browser
+  :type 'hook)
+
+(defcustom emms-browser-tracks-added-hook nil
+  "Hooks to run when tracks are added to the playlist."
+  :group 'emms-browser
+  :type 'hook)
+
+(defvar emms-browser-buffer nil
+  "The current browser buffer, if any.")
+
+(defvar emms-browser-buffer-name "*EMMS Browser*"
+  "The default buffer name.")
+
+(defvar emms-browser-current-mapping nil
+  "The current mapping db, eg. artist -> track.")
+(make-variable-buffer-local 'emms-browser-current-mapping)
+
+(defconst emms-browser-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map text-mode-map)
+    (define-key map (kbd "q") 'emms-browser-bury-buffer)
+    (define-key map (kbd "/") 'emms-isearch-buffer)
+    (define-key map (kbd "?") 'describe-mode)
+    (define-key map (kbd "RET") 'emms-browser-add-tracks-and-play)
+    (define-key map (kbd "SPC") 'emms-browser-add-tracks)
+    map)
+  "Keymap for `emms-browser-mode'.")
+
+(defface emms-browser-tracks-face
+  '((((class color) (background dark))
+     (:foreground "plum"))
+    (((class color) (background light))
+     (:foreground "Blue"))
+    (((type tty) (class mono))
+     (:inverse-video t))
+    (t (:background "Blue")))
+  "Face for the tracks in a playlist buffer."
+  :group 'emms-browser-mode)
+
+;; --------------------------------------------------
+;; General mode setup
+;; --------------------------------------------------
+
+(defun emms-browser (&optional name)
+  "Launch or switch to the EMMS Browser."
+  (interactive)
+  (when (or (null emms-browser-buffer)
+            (not (buffer-live-p emms-browser-buffer)))
+    (setq emms-browser-buffer (emms-browser-new-buffer name)))
+  ;; if the buffer is displayed, switch the window instead
+  (let ((wind (get-buffer-window emms-browser-buffer)))
+    (if wind
+        (select-window wind)
+      (switch-to-buffer emms-browser-buffer)))
+  (run-mode-hooks 'emms-browser-show-display-hook))
+
+(defun emms-browser-mode ()
+  "A major mode for the Emms browser.
+\\{emms-browser-mode-map}"
+      ;; create a new buffer
+  (interactive)
+
+  (use-local-map emms-browser-mode-map)
+  (setq major-mode 'emms-browser-mode
+        mode-name "Emms-Browser")
+
+  (setq buffer-read-only t))
+
+(defun emms-browser-new-buffer (&optional name)
+  "Create a new browser buffer.
+The buffer is named NAME, but made unique. NAME defaults to
+`emms-playlist-buffer-name'.
+If called interactively, the new buffer is also selected."
+  (let ((buf (generate-new-buffer (or name
+                                      emms-browser-buffer-name))))
+    (with-current-buffer buf
+      (when (not (eq major-mode 'emms-browser-mode))
+        (emms-browser-mode))
+      (when (interactive-p)
+        (switch-to-buffer buf)))
+    buf))
+
+(defun emms-browser-ensure-browser-buffer ()
+  (unless (eq major-mode 'emms-browser-mode)
+    (error "Current buffer is not an emms-browser buffer")))
+
+(defun emms-browser-bury-buffer ()
+  "Bury the browser buffer, running hooks."
+  (interactive)
+  (run-mode-hooks 'emms-browser-hide-display-hook)
+  (bury-buffer))
+
+(defun emms-browser-new (&optional name)
+  "Create or switch to a browser buffer, clearing it."
+  (emms-browser name)
+  (emms-with-inhibit-read-only-t
+   (delete-region (point-min) (point-max))))
+
+;; --------------------------------------------------
+;; Browsing methods - by artist/album/etc
+;; --------------------------------------------------
+
+(defmacro emms-browser-add-category (name track-type)
+  "Create an interactive function emms-browse-by-NAME."
+  (let ((funname (intern (concat "emms-browse-by-" name)))
+        (modedesc (concat "Browsing by: " name))
+        (funcdesc (concat "Browse by " name ".")))
+  `(defun ,funname ()
+     ,funcdesc
+     (interactive)
+     (emms-browser-new ,modedesc)
+     (emms-browser-display-by ,track-type)
+     (goto-char (point-min)))))
+
+(emms-browser-add-category "artist" 'info-artist)
+(emms-browser-add-category "album" 'info-album)
+(emms-browser-add-category "genre" 'info-genre)
+(emms-browser-add-category "year" 'info-year)
+
+(defun emms-browser-make-by (field-type)
+  "Make a mapping with FIELD-TYPE, eg artist -> tracks."
+  (let ((db (make-hash-table
+             :test emms-browser-comparison-test))
+        field existing-entry)
+    (maphash (lambda (path track)
+               (setq field (emms-track-get track field-type "missing-tag"))
+               (setq existing-entry (gethash field db))
+               (if existing-entry
+                   (puthash field (cons track existing-entry) db)
+                 (puthash field (list track) db)))
+             emms-cache-db)
+    db))
+
+(defun emms-browser-display-by (field-type)
+  "Render a mapping into a browser buffer."
+  (let ((db (emms-browser-make-by field-type)))
+    (maphash (lambda (field track)
+               (emms-browser-insert-entry field track))
+             db)
+    (setq emms-browser-current-mapping db)
+    (emms-with-inhibit-read-only-t
+     (let ((sort-fold-case t))
+       (sort-lines nil (point-min) (point-max))))))
+
+(defun case-fold-string= (a b)
+  (compare-strings a nil nil b nil nil t))
+
+(defun case-fold-string-hash (a)
+  (sxhash (upcase a)))
+
+(define-hash-table-test 'case-fold
+  'case-fold-string= 'case-fold-string-hash)
+
+;; --------------------------------------------------
+;; Operations on individual lines
+;; --------------------------------------------------
+
+(defun emms-browser-insert-entry (entry tracks)
+  "Add a single ENTRY -> TRACKS mapping to the buffer."
+  (emms-browser-ensure-browser-buffer)
+  (emms-with-inhibit-read-only-t
+   ;; why don't we propertize the \n?
+   (insert (emms-propertize entry
+                            'emms-tracks tracks
+                            'face 'emms-browser-tracks-face) "\n")))
+
+(defun emms-browser-add-tracks ()
+  "Add all the tracks on the current line to the playlist."
+  (interactive)
+  ;; display the bottom of the current playlist
+  (let ((tracks (emms-browser-tracks-at))
+        (count 0))
+    (unless tracks
+      (error "No tracks on current line!"))
+    (dolist (track tracks)
+      ;; FIXME: assumes 'file type
+      (emms-add-file (emms-track-get track 'name))
+      (setq count (1+ count)))
+    (run-mode-hooks 'emms-browser-tracks-added-hook)
+    (message "Added %d tracks." count)))
+
+(defun emms-browser-add-tracks-and-play ()
+  "Add all the tracks on the current line, play the first file."
+  (interactive)
+  (let (old-pos)
+    (with-current-emms-playlist
+      (setq old-pos (point-max)))
+    (emms-browser-add-tracks)
+    (with-current-emms-playlist
+      (goto-char old-pos)
+      (emms-playlist-select (point)))
+    ;; FIXME: is there a better way of doing this?
+    (emms-stop)
+    (emms-start)))
+
+(defun emms-browser-tracks-at (&optional pos)
+  "Return the tracks at POS (point if not given), or nil if none."
+  (emms-browser-ensure-browser-buffer)
+  (emms-with-widened-buffer
+   (get-text-property (or pos (point))
+                     'emms-tracks)))
+
+(defun emms-isearch-buffer ()
+  "Isearch through the buffer."
+  (interactive)
+  (goto-char (point-min))
+  (call-interactively 'isearch-forward))
+
+;; --------------------------------------------------
+;; Linked browser and playlist windows (experimental)
+;; --------------------------------------------------
+
+(defcustom emms-browser-switch-to-playlist-on-add
+  nil
+  "Whether to switch to to the playlist after adding files."
+  :group 'emms-browser
+  :type 'boolean)
+
+(defun emms-smart-browse ()
+  "Display browser and playlist.
+Toggle between selecting browser, playlist or hiding both. Tries
+to behave sanely if the user has manually changed the window
+configuration."
+  (interactive)
+  (add-to-list 'emms-browser-show-display-hook
+               'emms-browser-display-playlist)
+  (add-to-list 'emms-browser-hide-display-hook
+               'emms-browser-hide-linked-window)
+  ;; switch to the playlist window when adding tracks?
+  (add-to-list 'emms-browser-tracks-added-hook
+               (lambda () (interactive)
+                 (when emms-browser-switch-to-playlist-on-add
+                   (emms-smart-browse))
+                 ;; recenter
+                 (with-selected-window
+                     (emms-browser-get-linked-window)
+                   ;; FIXME: how do we achieve the same behaviour as
+                   ;; c-u when calling interactively?
+                   (recenter))))
+  (let (wind buf)
+  (cond
+   ((eq major-mode 'emms-browser-mode)
+    (setq buf (emms-browser-get-linked-buffer))
+    (setq wind (emms-browser-get-linked-window))
+    ;; if the playlist window is visible, select it
+    (if wind
+        (select-window wind)
+      ;; otherwise display and select it
+      (select-window (emms-browser-display-playlist))))
+   ((eq major-mode 'emms-playlist-mode)
+    (setq wind (emms-browser-get-linked-window))
+    ;; if the playlist window is selected, and the browser is visible,
+    ;; hide both
+    (if wind
+        (progn
+          (select-window wind)
+          (emms-browser-bury-buffer))
+      ;; otherwise bury both
+      (bury-buffer)
+      (emms-browser-hide-linked-window)))
+   (t
+    ;; show both
+    (funcall emms-browser-default-browsing-function)))))
+
+(defun emms-browser-get-linked-buffer ()
+  "Return linked buffer (eg browser if playlist is selected."
+  (cond
+   ((eq major-mode 'emms-browser-mode)
+    (car (emms-playlist-buffer-list)))
+   ((eq major-mode 'emms-playlist-mode)
+    emms-browser-buffer)))
+
+(defun emms-browser-get-linked-window ()
+  "Return linked window (eg browser if playlist is selected."
+  (let ((buf (emms-browser-get-linked-buffer)))
+    (when buf
+      (get-buffer-window buf))))
+
+(defun emms-browser-display-playlist ()
+  "A hook to show the playlist when the browser is displayed.
+Returns the playlist window."
+  (interactive)
+  (let ((pbuf (emms-browser-get-linked-buffer))
+        (pwin (emms-browser-get-linked-window)))
+    ;; if the window isn't alive..
+    (unless (window-live-p pwin)
+      (save-selected-window
+        (split-window-horizontally)
+        (other-window 1)
+        (if pbuf
+            (switch-to-buffer pbuf)
+          ;; there's no playlist - create one
+          (setq pbuf (emms-playlist-current-clear))
+          (switch-to-buffer pbuf))
+        ;; make q in the playlist window hide the linked browser
+        (define-key emms-playlist-mode-map (kbd "q")
+          (lambda ()
+            (interactive)
+            (emms-browser-hide-linked-window)
+            (bury-buffer)))
+        (setq pwin (get-buffer-window pbuf))
+        (goto-char (point-max))))
+    pwin))
+
+(defun emms-browser-hide-linked-window ()
+  "Delete a playlist or browser window when the other is hidden."
+  (interactive)
+  (let ((other-buf (emms-browser-get-linked-buffer))
+        (other-win (emms-browser-get-linked-window)))
+    (when (and other-win
+               (window-live-p other-win))
+      (delete-window other-win))
+    ;; bury the buffer, or it becomes visible when we hide the
+    ;; linked buffer
+    (bury-buffer other-buf)))
+
+(provide 'emms-browser)
+;;; emms-browser.el ends here
hunk ./emms-cache.el 3
-;; Copyright (C) 2006  Damien Elmes <address@hidden>
+;; Copyright (C) 2006  Damien Elmes <address@hidden>
hunk ./emms-setup.el 126
+  (require 'emms-browser)
}

[fix RET on trailing \n
Damien Elmes <address@hidden>**20060608090703
 \n isn't propertized which means hitting RET on a playlist or browser
 entry fails. this patch moves the point before trying to read the
 properties.
] {
hunk ./emms-browser.el 255
-   ;; why don't we propertize the \n?
hunk ./emms-browser.el 291
-  (emms-with-widened-buffer
-   (get-text-property (or pos (point))
-                     'emms-tracks)))
+  (save-excursion
+    ;; move the point to the start of the line, since the trailing new
+    ;; line is not propertized
+    (move-beginning-of-line nil)
+    (emms-with-widened-buffer
+     (get-text-property (or pos (point))
+                        'emms-tracks))))
hunk ./emms-playlist-mode.el 176
-  (if (not emms-playlist-mode-open-playlists)
-      (emms-playlist-mode-play-current-track)
-    (let* ((track (emms-playlist-track-at))
-           (name (emms-track-get track 'name))
-           (type (emms-track-get track 'type)))
-      (if (or (eq type 'playlist)
-              (and (eq type 'file)
-                   (string-match "\\.\\(m3u\\|pls\\)\\'" name)))
-          (emms-playlist-mode-load-playlist)
-        (emms-playlist-mode-play-current-track)))))
+  (save-excursion
+    ;; move to the start of the line, in case the point is on the \n,
+    ;; which isn't propertized
+    (move-beginning-of-line nil)
+    (if (not emms-playlist-mode-open-playlists)
+        (emms-playlist-mode-play-current-track)
+      (let* ((track (emms-playlist-track-at))
+             (name (emms-track-get track 'name))
+             (type (emms-track-get track 'type)))
+        (if (or (eq type 'playlist)
+                (and (eq type 'file)
+                     (string-match "\\.\\(m3u\\|pls\\)\\'" name)))
+            (emms-playlist-mode-load-playlist)
+          (emms-playlist-mode-play-current-track))))))
}

Context:

[emms.el: Change directory to / before starting the player.
address@hidden 
[emms-playlist-mode: When making new overlays, do not allow the rear to 
advance.  This prevents some display issues.  If we really need to modify the 
text there, we should be using (insert-before-markers).
Michael Olson <address@hidden>**20060607215212] 
[Make emms-property-region bulletproof.
Michael Olson <address@hidden>**20060607215113] 
[Fix typo in emms-property-region
address@hidden 
[emms.el, simplified emms-property-region considerably.
address@hidden 
[Very basic support for recording the time you last played a track.
address@hidden
 
 * emms-last-played.el: New file.
   Nothing fancy right now, more to come soon.
 * emms-setup.el: emms-devel now requires and setups emms-last-played.
] 
[Mark the cache as dirty for each modification.
address@hidden 
[emms.el: The currently playing marker now should stay where it is, even for 
yanks
address@hidden 
[emms-playlist-mode: Stop overlay from being attached to text inserted before it
address@hidden 
[fix damien elmes's email address
Damien Elmes <address@hidden>**20060607154000] 
[emms sources now switch add/play behavior when a prefix argument is supplied.
address@hidden 
[Add autoloads to emms-setup.el
address@hidden 
[Typo, defvar => defcustom for emms-cache-set-function
address@hidden 
[Cleaned up the cached code in emms.el a bit
address@hidden 
[refactor caching code into emms-cache.el
Damien Elmes <address@hidden>**20060607125345
 * caching support is now provided via two function vars in emms.el,
   emms-cache-get-function and emms-cache-set-function
 * (emms-standard) or above will enable caching support
 * you'll need to remove .emms-cache or s/emms-info-cache/emms-cache-db/
] 
[emms-info: Fix bug that occurs after clearing the current playlist and trying 
to re-add songs to it.
Michael Olson <address@hidden>**20060606144439] 
[emms-playlist-mode doesn't need overlay compatibility anymore
address@hidden 
[emms-playlist-mode.el - now with less overlay!
address@hidden 
[AUTHORS: fixed Lucas' e-mail address
address@hidden 
[AUTHORS: Damien Elmes address updated
address@hidden 
[info-cache-dirty/coding
Damien Elmes <address@hidden>**20060605163339
 
 * mark the info cache as dirty when it's modified, so we don't have to
   write it out all the time
 * save the cache as mule-utf-8 - comments? i'm not sure if this is
   correct
] 
[emms-info caching (thanks to Damien Elmes)
address@hidden 
[Sort file names from `emms-source-file-directory-tree-function'.
address@hidden 
[Add some sources for inserting playlists without inserting their contents, and 
likewise for directories of playlist files.  Exclude some files and directories 
from being added when walking directories.
Michael Olson <address@hidden>**20060604195602] 
[emms-player-mpd: Differentiate between files and URLs when it makes sense to 
do so.
Michael Olson <address@hidden>**20060604195449] 
[Miscellaneous minor cleanups.
Michael Olson <address@hidden>**20060604195311] 
[Make sure we never have an empty track description when inserting a song into 
a playlist buffer.
Michael Olson <address@hidden>**20060604194940] 
[Remove debian-extras package as requested by ftpmasters (debian)
address@hidden 
[Put volume options in their own customize group.
Martin Schoenmakers <address@hidden>**20060601193853
 
 Added a separate emms-volume group for customize and put things there instead
 of in the main thing.
] 
[Make handling of multiple playlist buffers less error-prone.
Michael Olson <address@hidden>**20060531203810] 
[emms-volume.el: Cosmetic stuff, defvar -> defcustom
address@hidden 
[emms-volume.el: Minor cosmetic cleanup
address@hidden 
[emms-volme.el: Add some requires.
address@hidden 
[emms-volume-amixer.el: Provide a way to set the control for amixer
address@hidden 
[AUTHORS: Add Martin Schoenmakers. Welcome! :-)
address@hidden 
[Add emms-volume and emms-volume-amixer.
Martin Schoenmakers <address@hidden>**20060530223500
 
 New files: emms-volume.el provides some general volume changing things,
 including a minor mode to more easily change volume when not in the
 EMMS buffer. emms-volume-amixer.el is a backend using amixer.
 
] 
[emms-streams: Re-add space after prompt and use completion for type.
Michael Olson <address@hidden>**20060530190620] 
[emms-streams: When the user wants emms-streams to play the selected stream 
instead of add it, create our own playlist buffer.  When quitting, if we own 
the current playlist buffer, kill it.
Michael Olson <address@hidden>**20060530144243] 
[allow nonzero ogginfo exit plus some reindenting
Martin Schoenmakers <address@hidden>**20060530130411
 
 When ogginfo gave a nonzero value on exit, any valid data would get tossed
 if there was any. This prevented emms from showing info for files that are
 tagged but a bit odd.
 
 Also reindented emms-info-ogginfo accordingly, which incidentally removed
 some tabs in favour of spaces.
 
] 
[emms-streams: Re-implement yank and kill so that they do the right thing with 
emms-stream-list.
Michael Olson <address@hidden>**20060530045429] 
[emms-streams: Implement kill and yank.
Michael Olson <address@hidden>**20060530040114] 
[emms-streams: Make hitting RET on a URL do the right thing, improve cursor 
movement, and mark the buffer as unmodified after performing a save.
Michael Olson <address@hidden>**20060529030043] 
[emms-player-mpd: Make seek work correctly.
Michael Olson <address@hidden>**20060525033120] 
[emms-player-mpd: Use more robust method of detecting whether we need to 
force-feed MusicPD our playlist.
Michael Olson <address@hidden>**20060525014253] 
[emms-playlist-mode: Make "d" kill the entire line.  This seems to be a good 
compromise of those who use C-k and those who want more standard object-killing 
behavior.
foo**20060524200008] 
[emms-player-mpd: When showing the currently-playing song, prepend the name of 
the radio station, if it exists.
foo**20060524195911] 
[emms-player-mpd: Fix bug that caused unconditional reloading of the entire 
MusicPD playlist whenever the track was changed manually.
Michael Olson <address@hidden>**20060524061655] 
[emms-player-mpd: Overhaul for streamlist support, and fix a few miscellaneous 
issues.
Michael Olson <address@hidden>**20060524055707] 
[emms-player-mpd: Add a few checks to make sure that the given buffer exists 
before trying to do anything with it.
Michael Olson <address@hidden>**20060517035419] 
[emms-source-playlist: Do not expand names of files in playlists, as this can 
cause problems with emms-player-mpd in some configurations.
Michael Olson <address@hidden>**20060516081257] 
[emms-playlist-mode: Implement the option (disabled by default) of opening a 
new EMMS buffer for a playlist, when hitting RET on one.
Michael Olson <address@hidden>**20060510040730] 
[emms-playlist-mode.el: Don't put a period after the mode map. This hangs 21.4 
on display.
address@hidden 
[TAG 2.0
address@hidden 
Patch bundle hash:
01bc748d1acba9aa81e121a13b5dfb713d826f0f

reply via email to

[Prev in Thread] Current Thread [Next in Thread]