branch: elpa/logview
commit 7f62361f24f7fae748aeb3940d9e9f3323071ddf
Author: Paul Pogonyshev <pogonys...@gmail.com>
Commit: Paul Pogonyshev <pogonys...@gmail.com>

    Add a command to manually choose log submode; requested in issue #15.
---
 logview.el | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 9 deletions(-)

diff --git a/logview.el b/logview.el
index 0dab12d3a8..fb67db19ba 100644
--- a/logview.el
+++ b/logview.el
@@ -451,6 +451,7 @@ To temporarily change this on per-buffer basis type 
\\<logview-mode-map>\\[logvi
                                                  (group "THREAD")
                                                  (group "IGNORED"))
                                          eow))
+(defconst logview--timestamp-entry-part-regexp (rx bow "TIMESTAMP" eow))
 
 (defvar logview--datetime-options '(:second-fractional-extension t
                                     :only-4-digit-years t
@@ -497,6 +498,8 @@ Levels are ordered least to most important.")
 (defvar logview--empty-filter-id '((nil nil) (nil nil) (nil nil)))
 (defvar-local logview--applied-filter-id logview--empty-filter-id)
 
+(defvar logview--submode-name-history)
+(defvar logview--timestamp-format-history)
 (defvar logview--name-regexp-history)
 (defvar logview--thread-regexp-history)
 (defvar logview--message-regexp-history)
@@ -591,6 +594,7 @@ Levels are ordered least to most important.")
      (logview-toggle-show-ellipses                                           
"Toggle ‘show ellipses’")
      "Options can be customized globally or changed in each buffer.")
     ("Miscellaneous"
+     (logview-choose-submode                                                 
"Manually choose appropriate submode")
      (logview-customize-submode-options                                      
"Customize options that affect submode selection")
      (bury-buffer                                                            
"Bury buffer")
      (logview-refresh-buffer-as-needed                                       
"Append tail or revert the buffer, as needed")
@@ -723,8 +727,10 @@ that the line is not the first in the buffer."
                        ("o v" logview-toggle-copy-visible-text-only)
                        ("o m" logview-toggle-search-only-in-messages)
                        ("o e" logview-toggle-show-ellipses)
+                       ("o s" logview-choose-submode)
                        ("o S" logview-customize-submode-options)
                        ;; For compatibility with the inactive keymap.
+                       ("C-c C-c" logview-choose-submode)
                        ("C-c C-s" logview-customize-submode-options)
                        ;; Miscellaneous commands.
                        ("?"   logview-mode-help)
@@ -741,6 +747,7 @@ that the line is not the first in the buffer."
 
 (defvar logview-mode-inactive-map
   (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "C-c C-c") 'logview-choose-submode)
     (define-key map (kbd "C-c C-s") 'logview-customize-submode-options)
     map)
   "Keymap used by `logview-mode' when the mode is inactive.
@@ -760,7 +767,7 @@ successfully.")
   (logview--guess-submode)
   (logview--update-invisibility-spec)
   (unless (logview-initialized-p)
-    (message "Cannot determine log format; press C-c C-s to customize relevant 
options")))
+    (message "Cannot determine log format; press C-c C-c to choose manually or 
C-c C-s to customize relevant options")))
 
 (defun logview--update-keymap ()
   (use-local-map (if (and buffer-read-only (logview-initialized-p))
@@ -1533,6 +1540,56 @@ argument is positive, disable it otherwise."
                                   "Hidden log entries are completely 
invisible")
   (logview--update-invisibility-spec))
 
+(defun logview-choose-submode (submode &optional timestamp)
+  "Manually choose submode for the current buffer.
+SUBMODE must be a name or an alias a supported submode from
+`logview-additional-submodes' or `logview-std-submodes' (aliases
+are understood too).  Timestamp may be either such a name or
+alias from `logview-additional-timestamp-formats' or
+`logview-std-timestamp-formats', or just a raw Java pattern.  If
+submode doesn't use timestamps, this parameter is ignored.
+
+When called interactively, both parameters are read in the
+minibuffer."
+  (interactive (list (let (submodes)
+                       (logview--iterate-split-alists (lambda (name definition)
+                                                        (push name submodes)
+                                                        (setq submodes (append 
(cdr (assq 'aliases definition)) submodes)))
+                                                      
logview-additional-submodes logview-std-submodes)
+                       (logview--completing-read "Submode name: " submodes nil 
t nil 'logview--submode-name-history))))
+  (let ((submode-definition (catch 'found
+                              (logview--iterate-split-alists (lambda (name 
definition)
+                                                               (when (string= 
submode name)
+                                                                 (throw 'found 
definition)))
+                                                             
logview-additional-submodes logview-std-submodes)))
+        timestamp-definition)
+    (unless submode-definition
+      (error "Unknown submode `%s'" submode))
+    (when (string-match logview--timestamp-entry-part-regexp (cdr (assq 
'format submode-definition)))
+      (unless timestamp
+        (unless (called-interactively-p 'interactive)
+          (error "Must specify a timestamp format for submode `%s'" submode))
+        (setq timestamp (let (timestamps)
+                          (logview--iterate-split-alists (lambda (name 
definition)
+                                                           (push name 
timestamps)
+                                                           (setq timestamps 
(append (cdr (assq 'aliases definition)) timestamps)))
+                                                         
logview-additional-timestamp-formats logview-std-timestamp-formats)
+                          (dolist (format (logview--all-timestamp-formats))
+                            (unless (datetime-pattern-locale-dependent-p 'java 
(car format))
+                              (push (car format) timestamps)))
+                          (completing-read "Timestamp format: " timestamps nil 
nil nil 'logview--timestamp-format-history))))
+      (setq timestamp-definition (catch 'found
+                                   (logview--iterate-split-alists (lambda 
(name definition)
+                                                                    (when 
(string= timestamp name)
+                                                                      (throw 
'found definition)))
+                                                                  
logview-additional-timestamp-formats logview-std-timestamp-formats)
+                                   ;; Unlike with submodes, allow unrecognized 
timestamps.
+                                   `(,timestamp (java-pattern . ,timestamp)))))
+    (catch 'success
+      (logview--initialize-submode submode submode-definition (list 
timestamp-definition))
+      ;; This must not happen.
+      (error "Internal error initializing submode `%s'" submode))))
+
 (defun logview-customize-submode-options ()
   "Customize all options that affect submode selection.
 These are:
@@ -1729,8 +1786,8 @@ returns non-nil."
             standard-timestamps)
         (logview--iterate-split-alists (lambda (_timestamp-name timestamp) 
(push timestamp standard-timestamps))
                                        logview-additional-timestamp-formats 
logview-std-timestamp-formats)
-        (dolist (regexp (logview--all-timestamp-formats))
-          (push (list (cons 'regexp regexp)) standard-timestamps))
+        (dolist (format (logview--all-timestamp-formats))
+          (push (cdr format) standard-timestamps))
         (setq standard-timestamps (nreverse standard-timestamps))
         (catch 'success
           (logview--iterate-split-alists (lambda (name definition)
@@ -1739,9 +1796,9 @@ returns non-nil."
                                              (error (warn 
(error-message-string error)))))
                                          logview-additional-submodes 
logview-std-submodes))))))
 
-(defun logview--initialize-submode (name definition standard-timestamps 
test-line)
+(defun logview--initialize-submode (name definition standard-timestamps 
&optional test-line)
   (let* ((format            (cdr (assq 'format    definition)))
-         (timestamp-names   (cdr (assq 'timestamp definition)))
+         (timestamp-names   (when test-line (cdr (assq 'timestamp 
definition))))
          (timestamp-options (if timestamp-names
                                 (mapcar (lambda (name)
                                           (logview--get-split-alists name 
"timestamp format"
@@ -1823,7 +1880,7 @@ returns non-nil."
       ;; the test line doesn't have even two digits at the expected
       ;; place, don't even loop through all the timestamp options.
       (setcar timestamp-at ".*[0-9][0-9].*")
-      (unless (string-match (apply #'concat parts) test-line)
+      (when (and test-line (not (string-match (apply #'concat parts) 
test-line)))
         (setq cannot-match t)))
     (unless cannot-match
       (dolist (timestamp-option (if timestamp-at timestamp-options '(nil)))
@@ -1842,7 +1899,7 @@ returns non-nil."
             (when timestamp-at
               (setcar timestamp-at (format "\\(?%d:%s\\)" 
logview--timestamp-group timestamp-regexp)))
             (let ((regexp (apply #'concat parts)))
-              (when (string-match regexp test-line)
+              (when (or (null test-line) (string-match regexp test-line))
                 (setq logview--submode-name           name
                       logview--process-buffer-changes t
                       logview--entry-regexp           regexp
@@ -1906,8 +1963,8 @@ returns non-nil."
                          (push (cdr key) (cdr existing)))
                      (puthash regexp (cons (car key) (list (cdr key))) 
uniques))))
                patterns)
-      (maphash (lambda (regexp _key)
-                 (push regexp logview--all-timestamp-formats-cache))
+      (maphash (lambda (regexp key)
+                 (push `(,(car key) (regexp . ,regexp)) 
logview--all-timestamp-formats-cache))
                uniques)
       (let ((inhibit-message t))
         (message "Logview/datetime: built list of %d timestamp regexps in %.3f 
s" (hash-table-count uniques) (- (float-time) start-time)))))

Reply via email to