]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch-hello.el
emacs: rename notmuch-decimal-separator to notmuch-hello-thousands-separator
[notmuch] / emacs / notmuch-hello.el
index e58dd24e3460ae445d9e218ca97d201e10f7ebcd..e6f87f8ae3d81a7af18969a9cd0abc52f2578a61 100644 (file)
   :type 'boolean
   :group 'notmuch)
 
+(defun notmuch-sort-saved-searches (alist)
+  "Generate an alphabetically sorted saved searches alist."
+  (sort alist (lambda (a b) (string< (car a) (car b)))))
+
+(defcustom notmuch-saved-search-sort-function nil
+  "Function used to sort the saved searches for the notmuch-hello view.
+
+This variable controls how saved searches should be sorted. No
+sorting (nil) displays the saved searches in the order they are
+stored in `notmuch-saved-searches'. Sort alphabetically sorts the
+saved searches in alphabetical order. Custom sort function should
+be a function or a lambda expression that takes the saved
+searches alist as a parameter, and returns a new saved searches
+alist to be used."
+  :type '(choice (const :tag "No sorting" nil)
+                (const :tag "Sort alphabetically" notmuch-sort-saved-searches)
+                (function :tag "Custom sort function"
+                          :value notmuch-sort-saved-searches))
+  :group 'notmuch)
+
 (defvar notmuch-hello-indent 4
   "How much to indent non-headers.")
 
   :type 'boolean
   :group 'notmuch)
 
+(defcustom notmuch-hello-tag-list-make-query nil
+  "Function or string to generate queries for the all tags list.
+
+This variable controls which query results are shown for each tag
+in the \"all tags\" list. If nil, it will use all messages with
+that tag. If this is set to a string, it is used as a filter for
+messages having that tag (equivalent to \"tag:TAG and (THIS-VARIABLE)\").
+Finally this can be a function that will be called for each tag and
+should return a filter for that tag, or nil to hide the tag."
+  :type '(choice (const :tag "All messages" nil)
+                (const :tag "Unread messages" "tag:unread")
+                (string :tag "Custom filter"
+                        :value "tag:unread")
+                (function :tag "Custom filter function"))
+  :group 'notmuch)
+
+(defcustom notmuch-hello-hide-tags nil
+  "List of tags to be hidden in the \"all tags\"-section."
+  :type '(repeat string)
+  :group 'notmuch)
+
 (defface notmuch-hello-logo-background
   '((((class color)
       (background dark))
@@ -91,13 +132,23 @@ So:
          (integer :tag "Number of characters")
          (float :tag "Fraction of window")))
 
-(defcustom notmuch-decimal-separator ","
-  "The string used as a decimal separator.
+(defcustom notmuch-hello-thousands-separator ","
+  "The string used as a thousands separator.
 
 Typically \",\" in the US and UK and \".\" in Europe."
   :group 'notmuch
   :type 'string)
 
+(defcustom notmuch-hello-mode-hook nil
+  "Functions called after entering `notmuch-hello-mode'."
+  :group 'notmuch
+  :type 'hook)
+
+(defcustom notmuch-hello-refresh-hook nil
+  "Functions called after updating a `notmuch-hello' buffer."
+  :type 'hook
+  :group 'notmuch)
+
 (defvar notmuch-hello-url "http://notmuchmail.org"
   "The `notmuch' web site.")
 
@@ -119,7 +170,7 @@ Typically \",\" in the US and UK and \".\" in Europe."
     (apply #'concat
      (number-to-string (car result))
      (mapcar (lambda (elem)
-             (format "%s%03d" notmuch-decimal-separator elem))
+             (format "%s%03d" notmuch-hello-thousands-separator elem))
             (cdr result)))))
 
 (defun notmuch-hello-trim (search)
@@ -148,8 +199,8 @@ Typically \",\" in the US and UK and \".\" in Europe."
                collect elem))
     ;; Add the new one.
     (customize-save-variable 'notmuch-saved-searches
-                            (push (cons name search)
-                                  notmuch-saved-searches))
+                            (add-to-list 'notmuch-saved-searches
+                                         (cons name search) t))
     (message "Saved '%s' as '%s'." search name)
     (notmuch-hello-update)))
 
@@ -291,14 +342,14 @@ should be. Returns a cons cell `(tags-per-line width)'."
 (defvar notmuch-hello-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map widget-keymap)
-    (define-key map "v" '(lambda () "Display the notmuch version" (interactive)
-                           (message "notmuch version %s" (notmuch-version))))
+    (define-key map "v" (lambda () "Display the notmuch version" (interactive)
+                         (message "notmuch version %s" (notmuch-version))))
     (define-key map "?" 'notmuch-help)
     (define-key map "q" 'notmuch-kill-this-buffer)
     (define-key map "=" 'notmuch-hello-update)
     (define-key map "G" 'notmuch-hello-poll-and-update)
     (define-key map (kbd "<C-tab>") 'widget-backward)
-    (define-key map "m" 'notmuch-mua-mail)
+    (define-key map "m" 'notmuch-mua-new-mail)
     (define-key map "s" 'notmuch-hello-goto-search)
     map)
   "Keymap for \"notmuch hello\" buffers.")
@@ -315,9 +366,29 @@ Complete list of currently available key bindings:
  (use-local-map notmuch-hello-mode-map)
  (setq major-mode 'notmuch-hello-mode
        mode-name "notmuch-hello")
+ (run-mode-hooks 'notmuch-hello-mode-hook)
  ;;(setq buffer-read-only t)
 )
 
+(defun notmuch-hello-generate-tag-alist ()
+  "Return an alist from tags to queries to display in the all-tags section."
+  (notmuch-remove-if-not
+   #'cdr
+   (mapcar (lambda (tag)
+            (cons tag
+                  (cond
+                   ((functionp notmuch-hello-tag-list-make-query)
+                    (concat "tag:" tag " and ("
+                            (funcall notmuch-hello-tag-list-make-query tag) ")"))
+                   ((stringp notmuch-hello-tag-list-make-query)
+                    (concat "tag:" tag " and ("
+                            notmuch-hello-tag-list-make-query ")"))
+                   (t (concat "tag:" tag)))))
+          (notmuch-remove-if-not
+           (lambda (tag)
+             (not (member tag notmuch-hello-hide-tags)))
+           (process-lines notmuch-command "search-tags")))))
+
 ;;;###autoload
 (defun notmuch-hello (&optional no-display)
   "Run notmuch and display saved searches, known tags, etc."
@@ -338,11 +409,16 @@ Complete list of currently available key bindings:
                     (progn
                       (widget-forward 1)
                       (widget-value (widget-at)))
-                  (error nil)))))
+                  (error nil))))
+       (inhibit-read-only t))
+
+    ;; Delete all editable widget fields.  Editable widget fields are
+    ;; tracked in a buffer local variable `widget-field-list' (and
+    ;; others).  If we do `erase-buffer' without properly deleting the
+    ;; widgets, some widget-related functions are confused later.
+    (mapc 'widget-delete widget-field-list)
 
-    (kill-all-local-variables)
-    (let ((inhibit-read-only t))
-      (erase-buffer))
+    (erase-buffer)
 
     (unless (eq major-mode 'notmuch-hello-mode)
       (notmuch-hello-mode))
@@ -389,20 +465,22 @@ Complete list of currently available key bindings:
     (let ((found-target-pos nil)
          (final-target-pos nil))
       (let* ((saved-alist
-             ;; Filter out empty saved seaches if required.
+             ;; Filter out empty saved searches if required.
              (if notmuch-show-empty-saved-searches
                  notmuch-saved-searches
                (loop for elem in notmuch-saved-searches
                      if (> (string-to-number (notmuch-saved-search-count (cdr elem))) 0)
                      collect elem)))
             (saved-widest (notmuch-hello-longest-label saved-alist))
-            (alltags-alist (if notmuch-show-all-tags-list
-                               (mapcar '(lambda (tag) (cons tag (concat "tag:" tag)))
-                                       (process-lines notmuch-command "search-tags"))))
+            (alltags-alist (if notmuch-show-all-tags-list (notmuch-hello-generate-tag-alist)))
             (alltags-widest (notmuch-hello-longest-label alltags-alist))
             (widest (max saved-widest alltags-widest)))
 
        (when saved-alist
+         ;; Sort saved searches if required.
+         (when notmuch-saved-search-sort-function
+           (setq saved-alist
+                 (funcall notmuch-saved-search-sort-function saved-alist)))
          (widget-insert "\nSaved searches: ")
          (widget-create 'push-button
                         :notify (lambda (&rest ignore)
@@ -425,6 +503,10 @@ Complete list of currently available key bindings:
                                       (length "Search: ")))
                       :action (lambda (widget &rest ignore)
                                 (notmuch-hello-search (widget-value widget))))
+       ;; add an invisible space to make `widget-end-of-line' ignore
+       ;; trailine spaces in the search widget field
+       (widget-insert " ")
+       (put-text-property (1- (point)) (point) 'invisible t)
        (widget-insert "\n")
 
        (when notmuch-hello-recent-searches
@@ -437,36 +519,36 @@ Complete list of currently available key bindings:
          (widget-insert "\n\n")
          (let ((start (point))
                (nth 0))
-           (mapc '(lambda (search)
-                    (let ((widget-symbol (intern (format "notmuch-hello-search-%d" nth))))
-                      (set widget-symbol
-                           (widget-create 'editable-field
-                                      ;; Don't let the search boxes be
-                                      ;; less than 8 characters wide.
-                                      :size (max 8
-                                                 (- (window-width)
-                                                    ;; Leave some space
-                                                    ;; at the start and
-                                                    ;; end of the
-                                                    ;; boxes.
-                                                    (* 2 notmuch-hello-indent)
-                                                    ;; 1 for the space
-                                                    ;; before the
-                                                    ;; `[save]' button. 6
-                                                    ;; for the `[save]'
-                                                    ;; button.
-                                                    1 6))
-                                      :action (lambda (widget &rest ignore)
-                                                (notmuch-hello-search (widget-value widget)))
-                                      search))
-                      (widget-insert " ")
-                      (widget-create 'push-button
-                                     :notify (lambda (widget &rest ignore)
-                                               (notmuch-hello-add-saved-search widget))
-                                     :notmuch-saved-search-widget widget-symbol
-                                     "save"))
-                    (widget-insert "\n")
-                    (setq nth (1+ nth)))
+           (mapc (lambda (search)
+                   (let ((widget-symbol (intern (format "notmuch-hello-search-%d" nth))))
+                     (set widget-symbol
+                          (widget-create 'editable-field
+                                         ;; Don't let the search boxes be
+                                         ;; less than 8 characters wide.
+                                         :size (max 8
+                                                    (- (window-width)
+                                                       ;; Leave some space
+                                                       ;; at the start and
+                                                       ;; end of the
+                                                       ;; boxes.
+                                                       (* 2 notmuch-hello-indent)
+                                                       ;; 1 for the space
+                                                       ;; before the
+                                                       ;; `[save]' button. 6
+                                                       ;; for the `[save]'
+                                                       ;; button.
+                                                       1 6))
+                                         :action (lambda (widget &rest ignore)
+                                                   (notmuch-hello-search (widget-value widget)))
+                                         search))
+                     (widget-insert " ")
+                     (widget-create 'push-button
+                                    :notify (lambda (widget &rest ignore)
+                                              (notmuch-hello-add-saved-search widget))
+                                    :notmuch-saved-search-widget widget-symbol
+                                    "save"))
+                   (widget-insert "\n")
+                   (setq nth (1+ nth)))
                  notmuch-hello-recent-searches)
            (indent-rigidly start (point) notmuch-hello-indent)))
 
@@ -514,7 +596,9 @@ Complete list of currently available key bindings:
          (widget-forward 1)))
 
       (unless (widget-at)
-       (notmuch-hello-goto-search)))))
+       (notmuch-hello-goto-search))))
+
+  (run-hooks 'notmuch-hello-refresh-hook))
 
 (defun notmuch-folder ()
   "Deprecated function for invoking notmuch---calling `notmuch' is preferred now."