README.org (7368B)
1 #+title: denote-menu 2 #+author: Mohamed Suliman 3 #+email: sulimanm@tcd.ie 4 #+language: en 5 #+options: ':t toc:nil author:t email:t num:t 6 7 #+html: <a href="http://elpa.gnu.org/packages/denote-menu.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/denote-menu.svg"/></a> 8 9 * Overview 10 =denote-menu= provides an interface for viewing your denote files that 11 goes beyond using the standard =dired= emacs command to view your 12 =denote-directory=. Using dired is a fine method for viewing your 13 denote files (among other things), however denote's file naming scheme 14 tends to clutters the buffer with hyphens and underscores. This 15 package aims to declutter your view of your files by making it easy to 16 view the 3 main components of denote files, that is their timestamp, 17 title, and keywords. Derived from the builtin =tabulated-list-mode=, 18 the =*Denote*= buffer that is created with the =list-denotes= command 19 is visually similar to that created by commands like =list-packages= 20 and =list-processes=, and provides methods to filter the denote files 21 that are shown, as well as exporting to dired with the denote files 22 that are currently shown for them to be operated upon further. In this 23 way, =denote-menu= adheres to the core tenants of the denote package 24 itself. 25 26 It is /predictable/ as it makes use of existing emacs functionality to 27 display files in a tabulated way similar to the package menu. It is 28 /composable/, integrating well with other emacs packages (denote, in 29 this case) and builtin functionality, opting to not reinvent the wheel 30 as to how the data is displayed. The scope of this package is narrow: 31 displaying and filtering denote files in a visually appealing and 32 intuitive manner. =denote-menu= is also /flexible/ and /hackable/, 33 providing a simple API to create your own filters, and integrates well 34 with dired by providing the =denote-menu-export-to-dired= command, 35 which allows for further action on denote files beyond just viewing and 36 filtering them. 37 38 #+attr_html: :width 750px 39 [[file:screenshots/screenshot.png]] 40 41 * Installation 42 =denote-menu= is available on the GNU ELPA package archive. To install, 43 simply run 44 45 #+begin_example 46 M-x package-install RET denote-menu RET 47 #+end_example 48 49 50 This package requires Denote =v1.2.0= or above. 51 * Usage 52 Assuming that you have =denote-directory= set to a directory that has 53 denote files, simply run =M-x list-denotes= to open the =*Denote*= 54 buffer. You will be presented with a tabulated list of your denote 55 files whose filenames match the =denote-menu-initial-regex= regular 56 expression. By default this is set to match all denote files in the 57 =denote-directory=. 58 59 The tabulated list includes 3 columns, one for the timestamp, title, 60 and keywords of each denote file. The timestamp column includes a 61 button that when followed will open the corresponding denote file 62 using =find-file=. 63 64 ** Filtering by regular expression 65 To filter the denote files shown by a regular expression, run =M-x 66 denote-menu-filter=. This will prompt for a regular expression and 67 will update the buffer to list only those denote files whose filenames 68 match. Running =denote-menu-filter= again will further filter down the 69 list. This is akin to running =% m= inside a =dired= buffer. 70 ** Filtering by keyword 71 To filter the denote files shown to those that are tagged with 72 specific keywords, run =M-x denote-menu-filter-by-keyword=. This 73 command will prompt for a list of comma separated keywords (with 74 completion) and filter the list to those denote files that are tagged 75 with at least one of the inputted keywords. 76 ** Defining your own filters 77 There are two ways to define your own filters: 78 1. Write an interactive function that sets =denote-menu-current-regex= 79 to be a regular expression that matches your desired set of denote 80 files, and then calls =denote-menu-update-entries=. For example, if 81 I would like to a filter that filters out those denote files that 82 were not tagged with the "biblio" keyword, I would add the following to my 83 emacs configuration: 84 #+begin_src emacs-lisp 85 (defun my/denote-menu-filter-biblio-only () 86 (interactive) 87 (setq denote-menu-current-regex "_biblio") 88 (denote-menu-update-entries)) 89 #+end_src 90 91 2. Write an interactive function that sets =tabulated-list-entries= to 92 a be a function that maps each desired denote file path to an entry 93 using =denote-menu--path-to-entry= function, and calls 94 =revert-buffer=. For example, if the variable 95 =my-matching-denote-paths= contains a list of file paths of the 96 desired denote files, then your filter function would look something like the following: 97 #+begin_src emacs-lisp 98 (defun my/denote-menu-filter-custom () 99 (interactive) 100 (let ((my-matching-denote-paths '("/home/namilus/zettelkasten/20220719T135304--this-is-my-first-note__meta.org"))) 101 (setq tabulated-list-entries (lambda () (mapcar #'denote-menu--path-to-entry my-matching-denote-paths))) 102 (revert-buffer))) 103 #+end_src 104 ** Clearing filters 105 To clear the filters and revert back to the 106 =denote-menu-initial-regex=, run =M-x denote-menu-clear-filters=. 107 ** Exporting to =dired= 108 Adhering to the tenets of predictability and composability, 109 =denote-menu= provides the command =denote-menu-export-to-dired= to 110 allow further action on these files that is permitted in dired e.g 111 copying, moving, compressing, etc. We do not reinvent the wheel here 112 but instead defer to what already exists. 113 114 When in the =*Denote*= buffer running =M-x 115 denote-menu-export-to-dired= will open a =dired= buffer in the same 116 window with those denote files that were displayed in the =*Denote*= 117 buffer already marked. 118 * Sample configuration 119 The user options for =denote-menu= are: 120 - =denote-menu-date-column-width= :: A number value for the width of 121 the date column. Defaults to 17. 122 - =denote-menu-title-column-width= :: A number value for the width of 123 the title column. Defaults to 85. 124 - =denote-menu-keywords-column-width= :: A number value for the width 125 of the keywords column. Defaults to 30. This value is irrelevant as 126 it is the final column and will take up the remaining width of the buffer. 127 - =denote-menu-show-file-type= :: If non-nil, appends the file type of 128 the current denote file to the title. 129 - =denote-menu-initial-regex= :: A string that is the regular 130 expression that is used to initially populate the =*Denote*= buffer 131 with matching entries. This could allow for potential workflows such 132 as having a dedicated buffer to display your journal denote files 133 (e.g those tagged with the "journal" keyword), etc. Defaults to the 134 =.= regular expression. 135 - =denote-menu-action= :: A function that takes as argument the 136 current denote file path and performs an action on it. Defaults to 137 =(lambda (path) (find-file path))=. This function is then called 138 whenever the button in the timestamp column is followed. 139 140 141 A sample user configuration is given below that sets appropriate 142 keybindings for the commands described in the previous section: 143 144 #+begin_src emacs-lisp 145 (require 'denote-menu) 146 147 (global-set-key (kbd "C-c z") #'list-denotes) 148 149 (define-key denote-menu-mode-map (kbd "c") #'denote-menu-clear-filters) 150 (define-key denote-menu-mode-map (kbd "/ r") #'denote-menu-filter) 151 (define-key denote-menu-mode-map (kbd "/ k") #'denote-menu-filter-by-keyword) 152 (define-key denote-menu-mode-map (kbd "e") #'denote-menu-export-to-dired) 153 #+end_src 154