| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
(require 'pp) |
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 |
|
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
(defgroup bookmark nil |
|---|
| 97 |
"Setting, annotation and jumping to bookmarks." |
|---|
| 98 |
:group 'matching) |
|---|
| 99 |
|
|---|
| 100 |
|
|---|
| 101 |
(defcustom bookmark-use-annotations nil |
|---|
| 102 |
"*If non-nil, saving a bookmark queries for an annotation in a buffer." |
|---|
| 103 |
:type 'boolean |
|---|
| 104 |
:group 'bookmark) |
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 |
(defcustom bookmark-save-flag t |
|---|
| 108 |
"*Controls when Emacs saves bookmarks to a file. |
|---|
| 109 |
--> nil means never save bookmarks, except when `bookmark-save' is |
|---|
| 110 |
explicitly called \(\\[bookmark-save]\). |
|---|
| 111 |
--> t means save bookmarks when Emacs is killed. |
|---|
| 112 |
--> Otherwise, it should be a number that is the frequency with which |
|---|
| 113 |
the bookmark list is saved \(i.e.: the number of times which |
|---|
| 114 |
Emacs' bookmark list may be modified before it is automatically |
|---|
| 115 |
saved.\). If it is a number, Emacs will also automatically save |
|---|
| 116 |
bookmarks when it is killed. |
|---|
| 117 |
|
|---|
| 118 |
Therefore, the way to get it to save every time you make or delete a |
|---|
| 119 |
bookmark is to set this variable to 1 \(or 0, which produces the same |
|---|
| 120 |
behavior.\) |
|---|
| 121 |
|
|---|
| 122 |
To specify the file in which to save them, modify the variable |
|---|
| 123 |
`bookmark-default-file', which is `~/.emacs.bmk' by default." |
|---|
| 124 |
:type '(choice (const nil) integer (other t)) |
|---|
| 125 |
:group 'bookmark) |
|---|
| 126 |
|
|---|
| 127 |
|
|---|
| 128 |
(defconst bookmark-old-default-file "~/.emacs-bkmrks" |
|---|
| 129 |
"*The `.emacs.bmk' file used to be called this name.") |
|---|
| 130 |
|
|---|
| 131 |
|
|---|
| 132 |
|
|---|
| 133 |
(defvar bookmark-file nil |
|---|
| 134 |
"Old name for `bookmark-default-file'.") |
|---|
| 135 |
|
|---|
| 136 |
(defcustom bookmark-default-file |
|---|
| 137 |
(if bookmark-file |
|---|
| 138 |
|
|---|
| 139 |
bookmark-file |
|---|
| 140 |
(convert-standard-filename "~/.emacs.bmk")) |
|---|
| 141 |
"*File in which to save bookmarks by default." |
|---|
| 142 |
:type 'file |
|---|
| 143 |
:group 'bookmark) |
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 |
(defcustom bookmark-version-control 'nospecial |
|---|
| 147 |
"*Whether or not to make numbered backups of the bookmark file. |
|---|
| 148 |
It can have four values: t, nil, `never', and `nospecial'. |
|---|
| 149 |
The first three have the same meaning that they do for the |
|---|
| 150 |
variable `version-control', and the final value `nospecial' means just |
|---|
| 151 |
use the value of `version-control'." |
|---|
| 152 |
:type '(choice (const nil) (const never) (const nospecial) |
|---|
| 153 |
(other t)) |
|---|
| 154 |
:group 'bookmark) |
|---|
| 155 |
|
|---|
| 156 |
|
|---|
| 157 |
(defcustom bookmark-completion-ignore-case t |
|---|
| 158 |
"*Non-nil means bookmark functions ignore case in completion." |
|---|
| 159 |
:type 'boolean |
|---|
| 160 |
:group 'bookmark) |
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 |
(defcustom bookmark-sort-flag t |
|---|
| 164 |
"*Non-nil means that bookmarks will be displayed sorted by bookmark name. |
|---|
| 165 |
Otherwise they will be displayed in LIFO order (that is, most |
|---|
| 166 |
recently set ones come first, oldest ones come last)." |
|---|
| 167 |
:type 'boolean |
|---|
| 168 |
:group 'bookmark) |
|---|
| 169 |
|
|---|
| 170 |
|
|---|
| 171 |
(defcustom bookmark-automatically-show-annotations t |
|---|
| 172 |
"*Nil means don't show annotations when jumping to a bookmark." |
|---|
| 173 |
:type 'boolean |
|---|
| 174 |
:group 'bookmark) |
|---|
| 175 |
|
|---|
| 176 |
|
|---|
| 177 |
(defcustom bookmark-bmenu-file-column 30 |
|---|
| 178 |
"*Column at which to display filenames in a buffer listing bookmarks. |
|---|
| 179 |
You can toggle whether files are shown with \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-toggle-filenames]." |
|---|
| 180 |
:type 'integer |
|---|
| 181 |
:group 'bookmark) |
|---|
| 182 |
|
|---|
| 183 |
|
|---|
| 184 |
(defcustom bookmark-bmenu-toggle-filenames t |
|---|
| 185 |
"*Non-nil means show filenames when listing bookmarks. |
|---|
| 186 |
This may result in truncated bookmark names. To disable this, put the |
|---|
| 187 |
following in your `.emacs' file: |
|---|
| 188 |
|
|---|
| 189 |
\(setq bookmark-bmenu-toggle-filenames nil\)" |
|---|
| 190 |
:type 'boolean |
|---|
| 191 |
:group 'bookmark) |
|---|
| 192 |
|
|---|
| 193 |
|
|---|
| 194 |
(defcustom bookmark-menu-length 70 |
|---|
| 195 |
"*Maximum length of a bookmark name displayed on a popup menu." |
|---|
| 196 |
:type 'integer |
|---|
| 197 |
:group 'boolean) |
|---|
| 198 |
|
|---|
| 199 |
|
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 |
|
|---|
| 203 |
(defconst bookmark-xemacsp |
|---|
| 204 |
(string-match "\\(Lucid\\|Xemacs\\)" emacs-version)) |
|---|
| 205 |
|
|---|
| 206 |
|
|---|
| 207 |
|
|---|
| 208 |
(or (fboundp 'defalias) (fset 'defalias 'fset)) |
|---|
| 209 |
|
|---|
| 210 |
|
|---|
| 211 |
(or (fboundp 'frame-height) (defalias 'frame-height 'screen-height)) |
|---|
| 212 |
|
|---|
| 213 |
|
|---|
| 214 |
(or (boundp 'baud-rate) |
|---|
| 215 |
|
|---|
| 216 |
(setq baud-rate 19200)) |
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 |
|
|---|
| 221 |
|
|---|
| 222 |
|
|---|
| 223 |
|
|---|
| 224 |
|
|---|
| 225 |
|
|---|
| 226 |
|
|---|
| 227 |
|
|---|
| 228 |
|
|---|
| 229 |
|
|---|
| 230 |
(defvar bookmark-map nil |
|---|
| 231 |
"Keymap containing bindings to bookmark functions. |
|---|
| 232 |
It is not bound to any key by default: to bind it |
|---|
| 233 |
so that you have a bookmark prefix, just use `global-set-key' and bind a |
|---|
| 234 |
key of your choice to `bookmark-map'. All interactive bookmark |
|---|
| 235 |
functions have a binding in this keymap.") |
|---|
| 236 |
|
|---|
| 237 |
|
|---|
| 238 |
(define-prefix-command 'bookmark-map) |
|---|
| 239 |
|
|---|
| 240 |
|
|---|
| 241 |
|
|---|
| 242 |
(define-key bookmark-map "x" 'bookmark-set) |
|---|
| 243 |
|
|---|
| 244 |
(define-key bookmark-map "m" 'bookmark-set) |
|---|
| 245 |
|
|---|
| 246 |
(define-key bookmark-map "j" 'bookmark-jump) |
|---|
| 247 |
|
|---|
| 248 |
(define-key bookmark-map "g" 'bookmark-jump) |
|---|
| 249 |
|
|---|
| 250 |
(define-key bookmark-map "i" 'bookmark-insert) |
|---|
| 251 |
|
|---|
| 252 |
(define-key bookmark-map "e" 'edit-bookmarks) |
|---|
| 253 |
|
|---|
| 254 |
(define-key bookmark-map "f" 'bookmark-insert-location) |
|---|
| 255 |
|
|---|
| 256 |
(define-key bookmark-map "r" 'bookmark-rename) |
|---|
| 257 |
|
|---|
| 258 |
(define-key bookmark-map "d" 'bookmark-delete) |
|---|
| 259 |
|
|---|
| 260 |
(define-key bookmark-map "l" 'bookmark-load) |
|---|
| 261 |
|
|---|
| 262 |
(define-key bookmark-map "w" 'bookmark-write) |
|---|
| 263 |
|
|---|
| 264 |
(define-key bookmark-map "s" 'bookmark-save) |
|---|
| 265 |
|
|---|
| 266 |
|
|---|
| 267 |
|
|---|
| 268 |
(defvar bookmark-read-annotation-mode-map (copy-keymap text-mode-map) |
|---|
| 269 |
"Keymap for composing an annotation for a bookmark.") |
|---|
| 270 |
|
|---|
| 271 |
(define-key bookmark-read-annotation-mode-map "\C-c\C-c" |
|---|
| 272 |
'bookmark-send-annotation) |
|---|
| 273 |
|
|---|
| 274 |
|
|---|
| 275 |
|
|---|
| 276 |
|
|---|
| 277 |
(defvar bookmark-alist () |
|---|
| 278 |
"Association list of bookmarks and their records. |
|---|
| 279 |
You probably don't want to change the value of this alist yourself; |
|---|
| 280 |
instead, let the various bookmark functions do it for you. |
|---|
| 281 |
|
|---|
| 282 |
The format of the alist is |
|---|
| 283 |
|
|---|
| 284 |
\(BOOKMARK1 BOOKMARK2 ...\) |
|---|
| 285 |
|
|---|
| 286 |
where each BOOKMARK is of the form |
|---|
| 287 |
|
|---|
| 288 |
\(NAME |
|---|
| 289 |
\(filename . FILE\) |
|---|
| 290 |
\(front-context-string . FRONT-STR\) |
|---|
| 291 |
\(rear-context-string . REAR-STR\) |
|---|
| 292 |
\(position . POS\) |
|---|
| 293 |
\(info-node . POS\) |
|---|
| 294 |
\(annotation . ANNOTATION\)\) |
|---|
| 295 |
|
|---|
| 296 |
So the cdr of each bookmark is an alist too. |
|---|
| 297 |
`info-node' is optional, by the way.") |
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
(defvar bookmarks-already-loaded nil) |
|---|
| 301 |
|
|---|
| 302 |
|
|---|
| 303 |
|
|---|
| 304 |
|
|---|
| 305 |
(defvar bookmark-current-bookmark nil |
|---|
| 306 |
"Name of bookmark most recently used in the current file. |
|---|
| 307 |
It is buffer local, used to make moving a bookmark forward |
|---|
| 308 |
through a file easier.") |
|---|
| 309 |
|
|---|
| 310 |
(make-variable-buffer-local 'bookmark-current-bookmark) |
|---|
| 311 |
|
|---|
| 312 |
|
|---|
| 313 |
(defvar bookmark-alist-modification-count 0 |
|---|
| 314 |
"Number of modifications to bookmark list since it was last saved.") |
|---|
| 315 |
|
|---|
| 316 |
|
|---|
| 317 |
(defvar bookmark-search-size 16 |
|---|
| 318 |
"Length of the context strings recorded on either side of a bookmark.") |
|---|
| 319 |
|
|---|
| 320 |
|
|---|
| 321 |
(defvar bookmark-current-point 0) |
|---|
| 322 |
(defvar bookmark-yank-point 0) |
|---|
| 323 |
(defvar bookmark-current-buffer nil) |
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 |
|
|---|
| 328 |
|
|---|
| 329 |
|
|---|
| 330 |
|
|---|
| 331 |
|
|---|
| 332 |
|
|---|
| 333 |
(defun bookmark-name-from-full-record (full-record) |
|---|
| 334 |
"Return name of FULL-RECORD \(an alist element instead of a string\)." |
|---|
| 335 |
(car full-record)) |
|---|
| 336 |
|
|---|
| 337 |
|
|---|
| 338 |
(defun bookmark-all-names () |
|---|
| 339 |
"Return a list of all current bookmark names." |
|---|
| 340 |
(bookmark-maybe-load-default-file) |
|---|
| 341 |
(mapcar |
|---|
| 342 |
(lambda (full-record) |
|---|
| 343 |
(bookmark-name-from-full-record full-record)) |
|---|
| 344 |
bookmark-alist)) |
|---|
| 345 |
|
|---|
| 346 |
|
|---|
| 347 |
(defun bookmark-get-bookmark (bookmark) |
|---|
| 348 |
"Return the full entry for BOOKMARK in bookmark-alist. |
|---|
| 349 |
If BOOKMARK is not a string, return nil." |
|---|
| 350 |
(when (stringp bookmark) |
|---|
| 351 |
(apply (if bookmark-completion-ignore-case |
|---|
| 352 |
#'assoc-ignore-case |
|---|
| 353 |
#'assoc) |
|---|
| 354 |
(list bookmark bookmark-alist)))) |
|---|
| 355 |
|
|---|
| 356 |
|
|---|
| 357 |
(defun bookmark-get-bookmark-record (bookmark) |
|---|
| 358 |
"Return the guts of the entry for BOOKMARK in bookmark-alist. |
|---|
| 359 |
That is, all information but the name." |
|---|
| 360 |
(car (cdr (bookmark-get-bookmark bookmark)))) |
|---|
| 361 |
|
|---|
| 362 |
|
|---|
| 363 |
(defun bookmark-set-name (bookmark newname) |
|---|
| 364 |
"Set BOOKMARK's name to NEWNAME." |
|---|
| 365 |
(setcar |
|---|
| 366 |
(if (stringp bookmark) (bookmark-get-bookmark bookmark) bookmark) |
|---|
| 367 |
newname)) |
|---|
| 368 |
|
|---|
| 369 |
|
|---|
| 370 |
(defun bookmark-get-annotation (bookmark) |
|---|
| 371 |
"Return the annotation of BOOKMARK, or nil if none." |
|---|
| 372 |
(cdr (assq 'annotation (bookmark-get-bookmark-record bookmark)))) |
|---|
| 373 |
|
|---|
| 374 |
|
|---|
| 375 |
(defun bookmark-set-annotation (bookmark ann) |
|---|
| 376 |
"Set the annotation of BOOKMARK to ANN." |
|---|
| 377 |
(let ((cell (assq 'annotation (bookmark-get-bookmark-record bookmark)))) |
|---|
| 378 |
(if cell |
|---|
| 379 |
(setcdr cell ann) |
|---|
| 380 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 381 |
(list (cons 'annotation ann)))))) |
|---|
| 382 |
|
|---|
| 383 |
|
|---|
| 384 |
(defun bookmark-get-filename (bookmark) |
|---|
| 385 |
"Return the full filename of BOOKMARK." |
|---|
| 386 |
(cdr (assq 'filename (bookmark-get-bookmark-record bookmark)))) |
|---|
| 387 |
|
|---|
| 388 |
|
|---|
| 389 |
(defun bookmark-set-filename (bookmark filename) |
|---|
| 390 |
"Set the full filename of BOOKMARK to FILENAME." |
|---|
| 391 |
(let ((cell (assq 'filename (bookmark-get-bookmark-record bookmark)))) |
|---|
| 392 |
(if cell |
|---|
| 393 |
(setcdr cell filename) |
|---|
| 394 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 395 |
(list (cons 'filename filename)))))) |
|---|
| 396 |
|
|---|
| 397 |
|
|---|
| 398 |
(defun bookmark-get-position (bookmark) |
|---|
| 399 |
"Return the position \(i.e.: point\) of BOOKMARK." |
|---|
| 400 |
(cdr (assq 'position (bookmark-get-bookmark-record bookmark)))) |
|---|
| 401 |
|
|---|
| 402 |
|
|---|
| 403 |
(defun bookmark-set-position (bookmark position) |
|---|
| 404 |
"Set the position \(i.e.: point\) of BOOKMARK to POSITION." |
|---|
| 405 |
(let ((cell (assq 'position (bookmark-get-bookmark-record bookmark)))) |
|---|
| 406 |
(if cell |
|---|
| 407 |
(setcdr cell position) |
|---|
| 408 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 409 |
(list (cons 'position position)))))) |
|---|
| 410 |
|
|---|
| 411 |
|
|---|
| 412 |
(defun bookmark-get-front-context-string (bookmark) |
|---|
| 413 |
"Return the front-context-string of BOOKMARK." |
|---|
| 414 |
(cdr (assq 'front-context-string (bookmark-get-bookmark-record bookmark)))) |
|---|
| 415 |
|
|---|
| 416 |
|
|---|
| 417 |
(defun bookmark-set-front-context-string (bookmark string) |
|---|
| 418 |
"Set the front-context-string of BOOKMARK to STRING." |
|---|
| 419 |
(let ((cell (assq 'front-context-string |
|---|
| 420 |
(bookmark-get-bookmark-record bookmark)))) |
|---|
| 421 |
(if cell |
|---|
| 422 |
(setcdr cell string) |
|---|
| 423 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 424 |
(list (cons 'front-context-string string)))))) |
|---|
| 425 |
|
|---|
| 426 |
|
|---|
| 427 |
(defun bookmark-get-rear-context-string (bookmark) |
|---|
| 428 |
"Return the rear-context-string of BOOKMARK." |
|---|
| 429 |
(cdr (assq 'rear-context-string (bookmark-get-bookmark-record bookmark)))) |
|---|
| 430 |
|
|---|
| 431 |
|
|---|
| 432 |
(defun bookmark-set-rear-context-string (bookmark string) |
|---|
| 433 |
"Set the rear-context-string of BOOKMARK to STRING." |
|---|
| 434 |
(let ((cell (assq 'rear-context-string |
|---|
| 435 |
(bookmark-get-bookmark-record bookmark)))) |
|---|
| 436 |
(if cell |
|---|
| 437 |
(setcdr cell string) |
|---|
| 438 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 439 |
(list (cons 'rear-context-string string)))))) |
|---|
| 440 |
|
|---|
| 441 |
|
|---|
| 442 |
(defun bookmark-get-info-node (bookmark) |
|---|
| 443 |
"Get the info node associated with BOOKMARK." |
|---|
| 444 |
(cdr (assq 'info-node (bookmark-get-bookmark-record bookmark)))) |
|---|
| 445 |
|
|---|
| 446 |
|
|---|
| 447 |
(defun bookmark-set-info-node (bookmark node) |
|---|
| 448 |
"Set the Info node of BOOKMARK to NODE." |
|---|
| 449 |
(let ((cell (assq 'info-node |
|---|
| 450 |
(bookmark-get-bookmark-record bookmark)))) |
|---|
| 451 |
(if cell |
|---|
| 452 |
(setcdr cell node) |
|---|
| 453 |
(nconc (bookmark-get-bookmark-record bookmark) |
|---|
| 454 |
(list (cons 'info-node node))))) |
|---|
| 455 |
|
|---|
| 456 |
(message "%S" (assq 'info-node (bookmark-get-bookmark-record bookmark))) |
|---|
| 457 |
(sit-for 4) |
|---|
| 458 |
) |
|---|
| 459 |
|
|---|
| 460 |
|
|---|
| 461 |
(defvar bookmark-history nil |
|---|
| 462 |
"The history list for bookmark functions.") |
|---|
| 463 |
|
|---|
| 464 |
|
|---|
| 465 |
(defun bookmark-completing-read (prompt &optional default) |
|---|
| 466 |
"Prompting with PROMPT, read a bookmark name in completion. |
|---|
| 467 |
PROMPT will get a \": \" stuck on the end no matter what, so you |
|---|
| 468 |
probably don't want to include one yourself. |
|---|
| 469 |
Optional second arg DEFAULT is a string to return if the user enters |
|---|
| 470 |
the empty string." |
|---|
| 471 |
(bookmark-maybe-load-default-file) |
|---|
| 472 |
(let* ((completion-ignore-case bookmark-completion-ignore-case) |
|---|
| 473 |
(default default) |
|---|
| 474 |
(prompt (if default |
|---|
| 475 |
(concat prompt (format " (%s): " default)) |
|---|
| 476 |
(concat prompt ": "))) |
|---|
| 477 |
(str |
|---|
| 478 |
(completing-read prompt |
|---|
| 479 |
bookmark-alist |
|---|
| 480 |
nil |
|---|
| 481 |
0 |
|---|
| 482 |
nil |
|---|
| 483 |
'bookmark-history))) |
|---|
| 484 |
(if (string-equal "" str) |
|---|
| 485 |
(list default) |
|---|
| 486 |
(list str)))) |
|---|
| 487 |
|
|---|
| 488 |
|
|---|
| 489 |
(defmacro bookmark-maybe-historicize-string (string) |
|---|
| 490 |
"Put STRING into the bookmark prompt history, if caller non-interactive. |
|---|
| 491 |
We need this because sometimes bookmark functions are invoked from |
|---|
| 492 |
menus, so `completing-read' never gets a chance to set `bookmark-history'." |
|---|
| 493 |
`(or |
|---|
| 494 |
(interactive-p) |
|---|
| 495 |
(setq bookmark-history (cons ,string bookmark-history)))) |
|---|
| 496 |
|
|---|
| 497 |
|
|---|
| 498 |
(defun bookmark-make (name &optional annotation overwrite info-node) |
|---|
| 499 |
"Make a bookmark named NAME. |
|---|
| 500 |
Optional second arg ANNOTATION gives it an annotation. |
|---|
| 501 |
Optional third arg OVERWRITE means replace any existing bookmarks with |
|---|
| 502 |
this name. |
|---|
| 503 |
Optional fourth arg INFO-NODE means this bookmark is at info node |
|---|
| 504 |
INFO-NODE, so record this fact in the bookmark's entry." |
|---|
| 505 |
(bookmark-maybe-load-default-file) |
|---|
| 506 |
(let ((stripped-name (copy-sequence name))) |
|---|
| 507 |
(or bookmark-xemacsp |
|---|
| 508 |
|
|---|
| 509 |
|
|---|
| 510 |
(set-text-properties 0 (length stripped-name) nil stripped-name)) |
|---|
| 511 |
(if (and (bookmark-get-bookmark stripped-name) (not overwrite)) |
|---|
| 512 |
|
|---|
| 513 |
|
|---|
| 514 |
(setcdr (bookmark-get-bookmark stripped-name) |
|---|
| 515 |
(list (bookmark-make-cell annotation info-node))) |
|---|
| 516 |
|
|---|
| 517 |
|
|---|
| 518 |
|
|---|
| 519 |
|
|---|
| 520 |
|
|---|
| 521 |
(setq bookmark-alist |
|---|
| 522 |
(cons |
|---|
| 523 |
(list stripped-name |
|---|
| 524 |
(bookmark-make-cell annotation info-node)) |
|---|
| 525 |
bookmark-alist))) |
|---|
| 526 |
|
|---|
| 527 |
|
|---|
| 528 |
(setq bookmark-current-bookmark stripped-name) |
|---|
| 529 |
(setq bookmark-alist-modification-count |
|---|
| 530 |
(1+ bookmark-alist-modification-count)) |
|---|
| 531 |
(if (bookmark-time-to-save-p) |
|---|
| 532 |
(bookmark-save)))) |
|---|
| 533 |
|
|---|
| 534 |
|
|---|
| 535 |
(defun bookmark-make-cell (annotation &optional info-node) |
|---|
| 536 |
"Return the record part of a new bookmark, given ANNOTATION. |
|---|
| 537 |
Must be at the correct position in the buffer in which the bookmark is |
|---|
| 538 |
being set. This might change someday. |
|---|
| 539 |
Optional second arg INFO-NODE means this bookmark is at info node |
|---|
| 540 |
INFO-NODE, so record this fact in the bookmark's entry." |
|---|
| 541 |
(let ((the-record |
|---|
| 542 |
(` ((filename . (, (bookmark-buffer-file-name))) |
|---|
| 543 |
(front-context-string |
|---|
| 544 |
. (, (if (>= (- (point-max) (point)) bookmark-search-size) |
|---|
| 545 |
(buffer-substring-no-properties |
|---|
| 546 |
(point) |
|---|
| 547 |
(+ (point) bookmark-search-size)) |
|---|
| 548 |
nil))) |
|---|
| 549 |
(rear-context-string |
|---|
| 550 |
. (, (if (>= (- (point) (point-min)) bookmark-search-size) |
|---|
| 551 |
(buffer-substring-no-properties |
|---|
| 552 |
(point) |
|---|
| 553 |
(- (point) bookmark-search-size)) |
|---|
| 554 |
nil))) |
|---|
| 555 |
(position . (, (point))) |
|---|
| 556 |
)))) |
|---|
| 557 |
|
|---|
| 558 |
|
|---|
| 559 |
|
|---|
| 560 |
|
|---|
| 561 |
(set-text-properties 0 (length annotation) nil annotation) |
|---|
| 562 |
(set-text-properties 0 (length info-node) nil info-node) |
|---|
| 563 |
|
|---|
| 564 |
(if annotation |
|---|
| 565 |
(nconc the-record (list (cons 'annotation annotation)))) |
|---|
| 566 |
(if info-node |
|---|
| 567 |
(nconc the-record (list (cons 'info-node info-node)))) |
|---|
| 568 |
|
|---|
| 569 |
|
|---|
| 570 |
the-record)) |
|---|
| 571 |
|
|---|
| 572 |
|
|---|
| 573 |
|
|---|
| 574 |
|
|---|
| 575 |
|
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 |
|
|---|
| 579 |
|
|---|
| 580 |
|
|---|
| 581 |
|
|---|
| 582 |
|
|---|
| 583 |
|
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| 588 |
|
|---|
| 589 |
|
|---|
| 590 |
|
|---|
| 591 |
|
|---|
| 592 |
|
|---|
| 593 |
|
|---|
| 594 |
|
|---|
| 595 |
|
|---|
| 596 |
|
|---|
| 597 |
|
|---|
| 598 |
|
|---|
| 599 |
|
|---|
| 600 |
|
|---|
| 601 |
|
|---|
| 602 |
|
|---|
| 603 |
|
|---|
| 604 |
|
|---|
| 605 |
|
|---|
| 606 |
|
|---|
| 607 |
|
|---|
| 608 |
|
|---|
| 609 |
|
|---|
| 610 |
|
|---|
| 611 |
|
|---|
| 612 |
|
|---|
| 613 |
|
|---|
| 614 |
|
|---|
| 615 |
|
|---|
| 616 |
|
|---|
| 617 |
|
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
|
|---|
| 623 |
(defconst bookmark-file-format-version 1 |
|---|
| 624 |
"The current version of the format used by bookmark files. |
|---|
| 625 |
You should never need to change this.") |
|---|
| 626 |
|
|---|
| 627 |
|
|---|
| 628 |
(defconst bookmark-end-of-version-stamp-marker |
|---|
| 629 |
"-*- End Of Bookmark File Format Version Stamp -*-\n" |
|---|
| 630 |
"This string marks the end of the version stamp in a bookmark file.") |
|---|
| 631 |
|
|---|
| 632 |
|
|---|
| 633 |
(defun bookmark-alist-from-buffer () |
|---|
| 634 |
"Return a bookmark-alist (in any format) from the current buffer. |
|---|
| 635 |
The buffer must of course contain bookmark format information. |
|---|
| 636 |
Does not care from where in the buffer it is called, and does not |
|---|
| 637 |
affect point." |
|---|
| 638 |
(save-excursion |
|---|
| 639 |
(goto-char (point-min)) |
|---|
| 640 |
(if (search-forward bookmark-end-of-version-stamp-marker nil t) |
|---|
| 641 |
(read (current-buffer)) |
|---|
| 642 |
|
|---|
| 643 |
(if (search-forward "(" nil t) |
|---|
| 644 |
(progn |
|---|
| 645 |
(forward-char -1) |
|---|
| 646 |
(read (current-buffer))) |
|---|
| 647 |
|
|---|
| 648 |
(error "Not bookmark format"))))) |
|---|
| 649 |
|
|---|
| 650 |
|
|---|
| 651 |
(defun bookmark-upgrade-version-0-alist (old-list) |
|---|
| 652 |
"Upgrade a version 0 alist OLD-LIST to the current version." |
|---|
| 653 |
(mapcar |
|---|
| 654 |
(lambda (bookmark) |
|---|
| 655 |
(let* ((name (car bookmark)) |
|---|
| 656 |
(record (car (cdr bookmark))) |
|---|
| 657 |
(filename (nth 0 record)) |
|---|
| 658 |
(front-str (nth 1 record)) |
|---|
| 659 |
(rear-str (nth 2 record)) |
|---|
| 660 |
(position (nth 3 record)) |
|---|
| 661 |
(ann (nth 4 record))) |
|---|
| 662 |
(list |
|---|
| 663 |
name |
|---|
| 664 |
(` ((filename . (, filename)) |
|---|
| 665 |
(front-context-string . (, (or front-str ""))) |
|---|
| 666 |
(rear-context-string . (, (or rear-str ""))) |
|---|
| 667 |
(position . (, position)) |
|---|
| 668 |
(annotation . (, ann))))))) |
|---|
| 669 |
old-list)) |
|---|
| 670 |
|
|---|
| 671 |
|
|---|
| 672 |
(defun bookmark-upgrade-file-format-from-0 () |
|---|
| 673 |
"Upgrade a bookmark file of format 0 (the original format) to format 1. |
|---|
| 674 |
This expects to be called from point-min in a bookmark file." |
|---|
| 675 |
(message "Upgrading bookmark format from 0 to %d..." |
|---|
| 676 |
bookmark-file-format-version) |
|---|
| 677 |
(let* ((old-list (bookmark-alist-from-buffer)) |
|---|
| 678 |
(new-list (bookmark-upgrade-version-0-alist old-list))) |
|---|
| 679 |
(delete-region (point-min) (point-max)) |
|---|
| 680 |
(bookmark-insert-file-format-version-stamp) |
|---|
| 681 |
(pp new-list (current-buffer)) |
|---|
| 682 |
(save-buffer)) |
|---|
| 683 |
(goto-char (point-min)) |
|---|
| 684 |
(message "Upgrading bookmark format from 0 to %d...done" |
|---|
| 685 |
bookmark-file-format-version) |
|---|
| 686 |
) |
|---|
| 687 |
|
|---|
| 688 |
|
|---|
| 689 |
(defun bookmark-grok-file-format-version () |
|---|
| 690 |
"Return an integer which is the file-format version of this bookmark file. |
|---|
| 691 |
This expects to be called from point-min in a bookmark file." |
|---|
| 692 |
(if (looking-at "^;;;;") |
|---|
| 693 |
(save-excursion |
|---|
| 694 |
(save-match-data |
|---|
| 695 |
(re-search-forward "[0-9]") |
|---|
| 696 |
(forward-char -1) |
|---|
| 697 |
(read (current-buffer)))) |
|---|
| 698 |
|
|---|
| 699 |
|
|---|
| 700 |
0)) |
|---|
| 701 |
|
|---|
| 702 |
|
|---|
| 703 |
(defun bookmark-maybe-upgrade-file-format () |
|---|
| 704 |
"Check the file-format version of this bookmark file. |
|---|
| 705 |
If the version is not up-to-date, upgrade it automatically. |
|---|
| 706 |
This expects to be called from point-min in a bookmark file." |
|---|
| 707 |
(let ((version (bookmark-grok-file-format-version))) |
|---|
| 708 |
(cond |
|---|
| 709 |
((= version bookmark-file-format-version) |
|---|
| 710 |
) |
|---|
| 711 |
((= version 0) |
|---|
| 712 |
(bookmark-upgrade-file-format-from-0)) |
|---|
| 713 |
(t |
|---|
| 714 |
(error "Bookmark file format version strangeness"))))) |
|---|
| 715 |
|
|---|
| 716 |
|
|---|
| 717 |
(defun bookmark-insert-file-format-version-stamp () |
|---|
| 718 |
"Insert text indicating current version of bookmark file format." |
|---|
| 719 |
(insert |
|---|
| 720 |
(format ";;;; Emacs Bookmark Format Version %d ;;;;\n" |
|---|
| 721 |
bookmark-file-format-version)) |
|---|
| 722 |
(insert ";;; This format is meant to be slightly human-readable;\n" |
|---|
| 723 |
";;; nevertheless, you probably don't want to edit it.\n" |
|---|
| 724 |
";;; " |
|---|
| 725 |
bookmark-end-of-version-stamp-marker)) |
|---|
| 726 |
|
|---|
| 727 |
|
|---|
| 728 |
|
|---|
| 729 |
|
|---|
| 730 |
|
|---|
| 731 |
|
|---|
| 732 |
|
|---|
| 733 |
|
|---|
| 734 |
(defun bookmark-set (&optional name parg) |
|---|
| 735 |
"Set a bookmark named NAME inside a file. |
|---|
| 736 |
If name is nil, then the user will be prompted. |
|---|
| 737 |
With prefix arg, will not overwrite a bookmark that has the same name |
|---|
| 738 |
as NAME if such a bookmark already exists, but instead will \"push\" |
|---|
| 739 |
the new bookmark onto the bookmark alist. Thus the most recently set |
|---|
| 740 |
bookmark with name NAME would be the one in effect at any given time, |
|---|
| 741 |
but the others are still there, should you decide to delete the most |
|---|
| 742 |
recent one. |
|---|
| 743 |
|
|---|
| 744 |
To yank words from the text of the buffer and use them as part of the |
|---|
| 745 |
bookmark name, type C-w while setting a bookmark. Successive C-w's |
|---|
| 746 |
yank successive words. |
|---|
| 747 |
|
|---|
| 748 |
Typing C-u inserts the name of the last bookmark used in the buffer |
|---|
| 749 |
\(as an aid in using a single bookmark name to track your progress |
|---|
| 750 |
through a large file\). If no bookmark was used, then C-u inserts the |
|---|
| 751 |
name of the file being visited. |
|---|
| 752 |
|
|---|
| 753 |
Use \\[bookmark-delete] to remove bookmarks \(you give it a name, |
|---|
| 754 |
and it removes only the first instance of a bookmark with that name from |
|---|
| 755 |
the list of bookmarks.\)" |
|---|
| 756 |
(interactive (list nil current-prefix-arg)) |
|---|
| 757 |
(or |
|---|
| 758 |
(bookmark-buffer-file-name) |
|---|
| 759 |
(error "Buffer not visiting a file or directory")) |
|---|
| 760 |
|
|---|
| 761 |
(bookmark-maybe-load-default-file) |
|---|
| 762 |
|
|---|
| 763 |
(setq bookmark-current-point (point)) |
|---|
| 764 |
(setq bookmark-yank-point (point)) |
|---|
| 765 |
(setq bookmark-current-buffer (current-buffer)) |
|---|
| 766 |
|
|---|
| 767 |
(let* ((default (or bookmark-current-bookmark |
|---|
| 768 |
(bookmark-buffer-name))) |
|---|
| 769 |
(str |
|---|
| 770 |
(or name |
|---|
| 771 |
(read-from-minibuffer |
|---|
| 772 |
(format "Set bookmark (%s): " default) |
|---|
| 773 |
nil |
|---|
| 774 |
(let ((now-map (copy-keymap minibuffer-local-map))) |
|---|
| 775 |
(define-key now-map "\C-w" 'bookmark-yank-word) |
|---|
| 776 |
(define-key now-map "\C-u" 'bookmark-insert-current-bookmark) |
|---|
| 777 |
now-map)))) |
|---|
| 778 |
(annotation nil)) |
|---|
| 779 |
(and (string-equal str "") (setq str default)) |
|---|
| 780 |
|
|---|
| 781 |
(if bookmark-use-annotations |
|---|
| 782 |
(bookmark-read-annotation parg str) |
|---|
| 783 |
(bookmark-make str annotation parg (bookmark-info-current-node)) |
|---|
| 784 |
(setq bookmark-current-bookmark str) |
|---|
| 785 |
(bookmark-bmenu-surreptitiously-rebuild-list) |
|---|
| 786 |
(goto-char bookmark-current-point)))) |
|---|
| 787 |
|
|---|
| 788 |
|
|---|
| 789 |
(defun bookmark-info-current-node () |
|---|
| 790 |
"If in Info-mode, return current node name (a string), else nil." |
|---|
| 791 |
(if (eq major-mode 'Info-mode) |
|---|
| 792 |
Info-current-node)) |
|---|
| 793 |
|
|---|
| 794 |
|
|---|
| 795 |
(defun bookmark-kill-line (&optional newline-too) |
|---|
| 796 |
"Kill from point to end of line. |
|---|
| 797 |
If optional arg NEWLINE-TOO is non-nil, delete the newline too. |
|---|
| 798 |
Does not affect the kill-ring." |
|---|
| 799 |
(let ((eol (save-excursion (end-of-line) (point)))) |
|---|
| 800 |
(delete-region (point) eol) |
|---|
| 801 |
(if (and newline-too (looking-at "\n")) |
|---|
| 802 |
(delete-char 1)))) |
|---|
| 803 |
|
|---|
| 804 |
|
|---|
| 805 |
|
|---|
| 806 |
(defvar bookmark-annotation-paragraph nil) |
|---|
| 807 |
(defvar bookmark-annotation-name nil) |
|---|
| 808 |
(defvar bookmark-annotation-buffer nil) |
|---|
| 809 |
(defvar bookmark-annotation-file nil) |
|---|
| 810 |
(defvar bookmark-annotation-point nil) |
|---|
| 811 |
|
|---|
| 812 |
|
|---|
| 813 |
(defun bookmark-send-annotation () |
|---|
| 814 |
"Use buffer contents as the annotation for a bookmark. |
|---|
| 815 |
Exclude lines that begin with `#'. |
|---|
| 816 |
Store the annotation text in the bookmark list with |
|---|
| 817 |
the bookmark (and file, and point) specified in buffer local variables." |
|---|
| 818 |
(interactive) |
|---|
| 819 |
(if (not (eq major-mode 'bookmark-read-annotation-mode)) |
|---|
| 820 |
(error "Not in bookmark-read-annotation-mode")) |
|---|
| 821 |
(goto-char (point-min)) |
|---|
| 822 |
(while (< (point) (point-max)) |
|---|
| 823 |
(if (looking-at "^#") |
|---|
| 824 |
(bookmark-kill-line t) |
|---|
| 825 |
(forward-line 1))) |
|---|
| 826 |
(let ((annotation (buffer-string)) |
|---|
| 827 |
(parg bookmark-annotation-paragraph) |
|---|
| 828 |
(bookmark bookmark-annotation-name) |
|---|
| 829 |
(pt bookmark-annotation-point) |
|---|
| 830 |
(buf bookmark-annotation-buffer)) |
|---|
| 831 |
|
|---|
| 832 |
|
|---|
| 833 |
|
|---|
| 834 |
|
|---|
| 835 |
|
|---|
| 836 |
(save-excursion |
|---|
| 837 |
(pop-to-buffer buf) |
|---|
| 838 |
(goto-char pt) |
|---|
| 839 |
(bookmark-make bookmark annotation parg (bookmark-info-current-node)) |
|---|
| 840 |
(setq bookmark-current-bookmark bookmark)) |
|---|
| 841 |
(bookmark-bmenu-surreptitiously-rebuild-list) |
|---|
| 842 |
(goto-char bookmark-current-point)) |
|---|
| 843 |
(kill-buffer (current-buffer))) |
|---|
| 844 |
|
|---|
| 845 |
|
|---|
| 846 |
(defun bookmark-default-annotation-text (bookmark) |
|---|
| 847 |
(concat "# Type the annotation for bookmark '" bookmark "' here.\n" |
|---|
| 848 |
"# All lines which start with a '#' will be deleted.\n" |
|---|
| 849 |
"# Type C-c C-c when done.\n#\n" |
|---|
| 850 |
"# Author: " (user-full-name) " <" (user-login-name) "@" |
|---|
| 851 |
(system-name) ">\n" |
|---|
| 852 |
"# Date: " (current-time-string) "\n")) |
|---|
| 853 |
|
|---|
| 854 |
|
|---|
| 855 |
(defvar bookmark-read-annotation-text-func 'bookmark-default-annotation-text |
|---|
| 856 |
"Function to return default text to use for a bookmark annotation. |
|---|
| 857 |
It takes the name of the bookmark, as a string, as an arg.") |
|---|
| 858 |
|
|---|
| 859 |
(defun bookmark-read-annotation-mode (buf point parg bookmark) |
|---|
| 860 |
"Mode for composing annotations for a bookmark. |
|---|
| 861 |
Wants BUF POINT PARG and BOOKMARK. |
|---|
| 862 |
When you have finished composing, type \\[bookmark-send-annotation] to send |
|---|
| 863 |
the annotation. |
|---|
| 864 |
|
|---|
| 865 |
\\{bookmark-read-annotation-mode-map} |
|---|
| 866 |
" |
|---|
| 867 |
(interactive) |
|---|
| 868 |
(kill-all-local-variables) |
|---|
| 869 |
(make-local-variable 'bookmark-annotation-paragraph) |
|---|
| 870 |
(make-local-variable 'bookmark-annotation-name) |
|---|
| 871 |
(make-local-variable 'bookmark-annotation-buffer) |
|---|
| 872 |
(make-local-variable 'bookmark-annotation-file) |
|---|
| 873 |
(make-local-variable 'bookmark-annotation-point) |
|---|
| 874 |
(setq bookmark-annotation-paragraph parg) |
|---|
| 875 |
(setq bookmark-annotation-name bookmark) |
|---|
| 876 |
(setq bookmark-annotation-buffer buf) |
|---|
| 877 |
(setq bookmark-annotation-file (buffer-file-name buf)) |
|---|
| 878 |
(setq bookmark-annotation-point point) |
|---|
| 879 |
(use-local-map bookmark-read-annotation-mode-map) |
|---|
| 880 |
(setq major-mode 'bookmark-read-annotation-mode) |
|---|
| 881 |
(insert (funcall bookmark-read-annotation-text-func bookmark)) |
|---|
| 882 |
(run-hooks 'text-mode-hook)) |
|---|
| 883 |
|
|---|
| 884 |
|
|---|
| 885 |
(defun bookmark-read-annotation (parg bookmark) |
|---|
| 886 |
"Pop up a buffer for entering a bookmark annotation. |
|---|
| 887 |
Text surrounding the bookmark is PARG; the bookmark name is BOOKMARK." |
|---|
| 888 |
(let ((buf (current-buffer)) |
|---|
| 889 |
(point (point))) |
|---|
| 890 |
(pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*")) |
|---|
| 891 |
(bookmark-read-annotation-mode buf point parg bookmark))) |
|---|
| 892 |
|
|---|
| 893 |
|
|---|
| 894 |
(defvar bookmark-edit-annotation-mode-map (copy-keymap text-mode-map) |
|---|
| 895 |
"Keymap for editing an annotation of a bookmark.") |
|---|
| 896 |
|
|---|
| 897 |
|
|---|
| 898 |
(define-key bookmark-edit-annotation-mode-map "\C-c\C-c" |
|---|
| 899 |
'bookmark-send-edited-annotation) |
|---|
| 900 |
|
|---|
| 901 |
|
|---|
| 902 |
|
|---|