| 9 | | Copyright (C) 1995,96 Free Software Foundation, Inc. |
|---|
| 10 | | |
|---|
| 11 | | Permission is granted to make and distribute verbatim copies of this |
|---|
| 12 | | manual provided the copyright notice and this permission notice are |
|---|
| 13 | | preserved on all copies. |
|---|
| 14 | | |
|---|
| 15 | | Permission is granted to copy and distribute modified versions of |
|---|
| 16 | | this manual under the conditions for verbatim copying, provided also |
|---|
| 17 | | that the entire resulting derived work is distributed under the terms |
|---|
| 18 | | of a permission notice identical to this one. |
|---|
| 19 | | |
|---|
| 20 | | Permission is granted to copy and distribute translations of this |
|---|
| 21 | | manual into another language, under the above conditions for modified |
|---|
| 22 | | versions. |
|---|
| 23 | | |
|---|
| 24 | | |
|---|
| 25 | | File: gnus, Node: Keystrokes, Next: Emacs Lisp, Up: Emacs for Heathens |
|---|
| 26 | | |
|---|
| 27 | | Keystrokes |
|---|
| | 10 | Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, |
|---|
| | 11 | Inc. |
|---|
| | 12 | |
|---|
| | 13 | Permission is granted to copy, distribute and/or modify this document |
|---|
| | 14 | under the terms of the GNU Free Documentation License, Version 1.1 or |
|---|
| | 15 | any later version published by the Free Software Foundation; with the |
|---|
| | 16 | Invariant Sections being none, with the Front-Cover texts being "A GNU |
|---|
| | 17 | Manual", and with the Back-Cover Texts as in (a) below. A copy of the |
|---|
| | 18 | license is included in the section entitled "GNU Free Documentation |
|---|
| | 19 | License" in the Emacs manual. |
|---|
| | 20 | |
|---|
| | 21 | (a) The FSF's Back-Cover Text is: "You have freedom to copy and |
|---|
| | 22 | modify this GNU Manual, like GNU software. Copies published by the Free |
|---|
| | 23 | Software Foundation raise funds for GNU development." |
|---|
| | 24 | |
|---|
| | 25 | This document is part of a collection distributed under the GNU Free |
|---|
| | 26 | Documentation License. If you want to distribute this document |
|---|
| | 27 | separately from the collection, you can do so by adding a copy of the |
|---|
| | 28 | license to the document, as described in section 6 of the license. |
|---|
| | 29 | |
|---|
| | 30 | |
|---|
| | 31 | File: gnus, Node: Gnus Reference Guide, Next: Emacs for Heathens, Prev: Troubleshooting, Up: Appendices |
|---|
| | 32 | |
|---|
| | 33 | Gnus Reference Guide |
|---|
| | 34 | ==================== |
|---|
| | 35 | |
|---|
| | 36 | It is my hope that other people will figure out smart stuff that Gnus |
|---|
| | 37 | can do, and that other people will write those smart things as well. To |
|---|
| | 38 | facilitate that I thought it would be a good idea to describe the inner |
|---|
| | 39 | workings of Gnus. And some of the not-so-inner workings, while I'm at |
|---|
| | 40 | it. |
|---|
| | 41 | |
|---|
| | 42 | You can never expect the internals of a program not to change, but I |
|---|
| | 43 | will be defining (in some details) the interface between Gnus and its |
|---|
| | 44 | backends (this is written in stone), the format of the score files |
|---|
| | 45 | (ditto), data structures (some are less likely to change than others) |
|---|
| | 46 | and general methods of operation. |
|---|
| | 47 | |
|---|
| | 48 | * Menu: |
|---|
| | 49 | |
|---|
| | 50 | * Gnus Utility Functions:: Common functions and variable to use. |
|---|
| | 51 | * Backend Interface:: How Gnus communicates with the servers. |
|---|
| | 52 | * Score File Syntax:: A BNF definition of the score file standard. |
|---|
| | 53 | * Headers:: How Gnus stores headers internally. |
|---|
| | 54 | * Ranges:: A handy format for storing mucho numbers. |
|---|
| | 55 | * Group Info:: The group info format. |
|---|
| | 56 | * Extended Interactive:: Symbolic prefixes and stuff. |
|---|
| | 57 | * Emacs/XEmacs Code:: Gnus can be run under all modern Emacsen. |
|---|
| | 58 | * Various File Formats:: Formats of files that Gnus use. |
|---|
| | 59 | |
|---|
| | 60 | |
|---|
| | 61 | File: gnus, Node: Gnus Utility Functions, Next: Backend Interface, Up: Gnus Reference Guide |
|---|
| | 62 | |
|---|
| | 63 | Gnus Utility Functions |
|---|
| | 64 | ---------------------- |
|---|
| | 65 | |
|---|
| | 66 | When writing small functions to be run from hooks (and stuff), it's |
|---|
| | 67 | vital to have access to the Gnus internal functions and variables. |
|---|
| | 68 | Below is a list of the most common ones. |
|---|
| | 69 | |
|---|
| | 70 | `gnus-newsgroup-name' |
|---|
| | 71 | This variable holds the name of the current newsgroup. |
|---|
| | 72 | |
|---|
| | 73 | `gnus-find-method-for-group' |
|---|
| | 74 | A function that returns the select method for GROUP. |
|---|
| | 75 | |
|---|
| | 76 | `gnus-group-real-name' |
|---|
| | 77 | Takes a full (prefixed) Gnus group name, and returns the unprefixed |
|---|
| | 78 | name. |
|---|
| | 79 | |
|---|
| | 80 | `gnus-group-prefixed-name' |
|---|
| | 81 | Takes an unprefixed group name and a select method, and returns |
|---|
| | 82 | the full (prefixed) Gnus group name. |
|---|
| | 83 | |
|---|
| | 84 | `gnus-get-info' |
|---|
| | 85 | Returns the group info list for GROUP. |
|---|
| | 86 | |
|---|
| | 87 | `gnus-group-unread' |
|---|
| | 88 | The number of unread articles in GROUP, or `t' if that is unknown. |
|---|
| | 89 | |
|---|
| | 90 | `gnus-active' |
|---|
| | 91 | The active entry for GROUP. |
|---|
| | 92 | |
|---|
| | 93 | `gnus-set-active' |
|---|
| | 94 | Set the active entry for GROUP. |
|---|
| | 95 | |
|---|
| | 96 | `gnus-add-current-to-buffer-list' |
|---|
| | 97 | Adds the current buffer to the list of buffers to be killed on Gnus |
|---|
| | 98 | exit. |
|---|
| | 99 | |
|---|
| | 100 | `gnus-continuum-version' |
|---|
| | 101 | Takes a Gnus version string as a parameter and returns a floating |
|---|
| | 102 | point number. Earlier versions will always get a lower number |
|---|
| | 103 | than later versions. |
|---|
| | 104 | |
|---|
| | 105 | `gnus-group-read-only-p' |
|---|
| | 106 | Says whether GROUP is read-only or not. |
|---|
| | 107 | |
|---|
| | 108 | `gnus-news-group-p' |
|---|
| | 109 | Says whether GROUP came from a news backend. |
|---|
| | 110 | |
|---|
| | 111 | `gnus-ephemeral-group-p' |
|---|
| | 112 | Says whether GROUP is ephemeral or not. |
|---|
| | 113 | |
|---|
| | 114 | `gnus-server-to-method' |
|---|
| | 115 | Returns the select method corresponding to SERVER. |
|---|
| | 116 | |
|---|
| | 117 | `gnus-server-equal' |
|---|
| | 118 | Says whether two virtual servers are equal. |
|---|
| | 119 | |
|---|
| | 120 | `gnus-group-native-p' |
|---|
| | 121 | Says whether GROUP is native or not. |
|---|
| | 122 | |
|---|
| | 123 | `gnus-group-secondary-p' |
|---|
| | 124 | Says whether GROUP is secondary or not. |
|---|
| | 125 | |
|---|
| | 126 | `gnus-group-foreign-p' |
|---|
| | 127 | Says whether GROUP is foreign or not. |
|---|
| | 128 | |
|---|
| | 129 | `group-group-find-parameter' |
|---|
| | 130 | Returns the parameter list of GROUP. If given a second parameter, |
|---|
| | 131 | returns the value of that parameter for GROUP. |
|---|
| | 132 | |
|---|
| | 133 | `gnus-group-set-parameter' |
|---|
| | 134 | Takes three parameters; GROUP, PARAMETER and VALUE. |
|---|
| | 135 | |
|---|
| | 136 | `gnus-narrow-to-body' |
|---|
| | 137 | Narrows the current buffer to the body of the article. |
|---|
| | 138 | |
|---|
| | 139 | `gnus-check-backend-function' |
|---|
| | 140 | Takes two parameters, FUNCTION and GROUP. If the backend GROUP |
|---|
| | 141 | comes from supports FUNCTION, return non-`nil'. |
|---|
| | 142 | |
|---|
| | 143 | (gnus-check-backend-function "request-scan" "nnml:misc") |
|---|
| | 144 | => t |
|---|
| | 145 | |
|---|
| | 146 | `gnus-read-method' |
|---|
| | 147 | Prompts the user for a select method. |
|---|
| | 148 | |
|---|
| | 149 | |
|---|
| | 150 | File: gnus, Node: Backend Interface, Next: Score File Syntax, Prev: Gnus Utility Functions, Up: Gnus Reference Guide |
|---|
| | 151 | |
|---|
| | 152 | Backend Interface |
|---|
| | 153 | ----------------- |
|---|
| | 154 | |
|---|
| | 155 | Gnus doesn't know anything about NNTP, spools, mail or virtual |
|---|
| | 156 | groups. It only knows how to talk to "virtual servers". A virtual |
|---|
| | 157 | server is a "backend" and some "backend variables". As examples of the |
|---|
| | 158 | first, we have `nntp', `nnspool' and `nnmbox'. As examples of the |
|---|
| | 159 | latter we have `nntp-port-number' and `nnmbox-directory'. |
|---|
| | 160 | |
|---|
| | 161 | When Gnus asks for information from a backend--say `nntp'--on |
|---|
| | 162 | something, it will normally include a virtual server name in the |
|---|
| | 163 | function parameters. (If not, the backend should use the "current" |
|---|
| | 164 | virtual server.) For instance, `nntp-request-list' takes a virtual |
|---|
| | 165 | server as its only (optional) parameter. If this virtual server hasn't |
|---|
| | 166 | been opened, the function should fail. |
|---|
| | 167 | |
|---|
| | 168 | Note that a virtual server name has no relation to some physical |
|---|
| | 169 | server name. Take this example: |
|---|
| | 170 | |
|---|
| | 171 | (nntp "odd-one" |
|---|
| | 172 | (nntp-address "ifi.uio.no") |
|---|
| | 173 | (nntp-port-number 4324)) |
|---|
| | 174 | |
|---|
| | 175 | Here the virtual server name is `odd-one' while the name of the |
|---|
| | 176 | physical server is `ifi.uio.no'. |
|---|
| | 177 | |
|---|
| | 178 | The backends should be able to switch between several virtual |
|---|
| | 179 | servers. The standard backends implement this by keeping an alist of |
|---|
| | 180 | virtual server environments that they pull down/push up when needed. |
|---|
| | 181 | |
|---|
| | 182 | There are two groups of interface functions: "required functions", |
|---|
| | 183 | which must be present, and "optional functions", which Gnus will always |
|---|
| | 184 | check for presence before attempting to call 'em. |
|---|
| | 185 | |
|---|
| | 186 | All these functions are expected to return data in the buffer |
|---|
| | 187 | `nntp-server-buffer' (` *nntpd*'), which is somewhat unfortunately |
|---|
| | 188 | named, but we'll have to live with it. When I talk about "resulting |
|---|
| | 189 | data", I always refer to the data in that buffer. When I talk about |
|---|
| | 190 | "return value", I talk about the function value returned by the |
|---|
| | 191 | function call. Functions that fail should return `nil' as the return |
|---|
| | 192 | value. |
|---|
| | 193 | |
|---|
| | 194 | Some backends could be said to be "server-forming" backends, and |
|---|
| | 195 | some might be said not to be. The latter are backends that generally |
|---|
| | 196 | only operate on one group at a time, and have no concept of "server" - |
|---|
| | 197 | they have a group, and they deliver info on that group and nothing more. |
|---|
| | 198 | |
|---|
| | 199 | In the examples and definitions I will refer to the imaginary backend |
|---|
| | 200 | `nnchoke'. |
|---|
| | 201 | |
|---|
| | 202 | * Menu: |
|---|
| | 203 | |
|---|
| | 204 | * Required Backend Functions:: Functions that must be implemented. |
|---|
| | 205 | * Optional Backend Functions:: Functions that need not be implemented. |
|---|
| | 206 | * Error Messaging:: How to get messages and report errors. |
|---|
| | 207 | * Writing New Backends:: Extending old backends. |
|---|
| | 208 | * Hooking New Backends Into Gnus:: What has to be done on the Gnus end. |
|---|
| | 209 | * Mail-like Backends:: Some tips on mail backends. |
|---|
| | 210 | |
|---|
| | 211 | |
|---|
| | 212 | File: gnus, Node: Required Backend Functions, Next: Optional Backend Functions, Up: Backend Interface |
|---|
| | 213 | |
|---|
| | 214 | Required Backend Functions |
|---|
| | 215 | .......................... |
|---|
| | 216 | |
|---|
| | 217 | `(nnchoke-retrieve-headers ARTICLES &optional GROUP SERVER FETCH-OLD)' |
|---|
| | 218 | ARTICLES is either a range of article numbers or a list of |
|---|
| | 219 | `Message-ID's. Current backends do not fully support either--only |
|---|
| | 220 | sequences (lists) of article numbers, and most backends do not |
|---|
| | 221 | support retrieval of `Message-ID's. But they should try for both. |
|---|
| | 222 | |
|---|
| | 223 | The result data should either be HEADs or NOV lines, and the result |
|---|
| | 224 | value should either be `headers' or `nov' to reflect this. This |
|---|
| | 225 | might later be expanded to `various', which will be a mixture of |
|---|
| | 226 | HEADs and NOV lines, but this is currently not supported by Gnus. |
|---|
| | 227 | |
|---|
| | 228 | If FETCH-OLD is non-`nil' it says to try fetching "extra headers", |
|---|
| | 229 | in some meaning of the word. This is generally done by fetching |
|---|
| | 230 | (at most) FETCH-OLD extra headers less than the smallest article |
|---|
| | 231 | number in `articles', and filling the gaps as well. The presence |
|---|
| | 232 | of this parameter can be ignored if the backend finds it |
|---|
| | 233 | cumbersome to follow the request. If this is non-`nil' and not a |
|---|
| | 234 | number, do maximum fetches. |
|---|
| | 235 | |
|---|
| | 236 | Here's an example HEAD: |
|---|
| | 237 | |
|---|
| | 238 | 221 1056 Article retrieved. |
|---|
| | 239 | Path: ifi.uio.no!sturles |
|---|
| | 240 | From: sturles@ifi.uio.no (Sturle Sunde) |
|---|
| | 241 | Newsgroups: ifi.discussion |
|---|
| | 242 | Subject: Re: Something very droll |
|---|
| | 243 | Date: 27 Oct 1994 14:02:57 +0100 |
|---|
| | 244 | Organization: Dept. of Informatics, University of Oslo, Norway |
|---|
| | 245 | Lines: 26 |
|---|
| | 246 | Message-ID: <38o8e1$a0o@holmenkollen.ifi.uio.no> |
|---|
| | 247 | References: <38jdmq$4qu@visbur.ifi.uio.no> |
|---|
| | 248 | NNTP-Posting-Host: holmenkollen.ifi.uio.no |
|---|
| | 249 | . |
|---|
| | 250 | |
|---|
| | 251 | So a `headers' return value would imply that there's a number of |
|---|
| | 252 | these in the data buffer. |
|---|
| | 253 | |
|---|
| | 254 | Here's a BNF definition of such a buffer: |
|---|
| | 255 | |
|---|
| | 256 | headers = *head |
|---|
| | 257 | head = error / valid-head |
|---|
| | 258 | error-message = [ "4" / "5" ] 2number " " <error message> eol |
|---|
| | 259 | valid-head = valid-message *header "." eol |
|---|
| | 260 | valid-message = "221 " <number> " Article retrieved." eol |
|---|
| | 261 | header = <text> eol |
|---|
| | 262 | |
|---|
| | 263 | If the return value is `nov', the data buffer should contain |
|---|
| | 264 | "network overview database" lines. These are basically fields |
|---|
| | 265 | separated by tabs. |
|---|
| | 266 | |
|---|
| | 267 | nov-buffer = *nov-line |
|---|
| | 268 | nov-line = 8*9 [ field <TAB> ] eol |
|---|
| | 269 | field = <text except TAB> |
|---|
| | 270 | |
|---|
| | 271 | For a closer look at what should be in those fields, *note |
|---|
| | 272 | Headers::. |
|---|
| | 273 | |
|---|
| | 274 | `(nnchoke-open-server SERVER &optional DEFINITIONS)' |
|---|
| | 275 | SERVER is here the virtual server name. DEFINITIONS is a list of |
|---|
| | 276 | `(VARIABLE VALUE)' pairs that define this virtual server. |
|---|
| | 277 | |
|---|
| | 278 | If the server can't be opened, no error should be signaled. The |
|---|
| | 279 | backend may then choose to refuse further attempts at connecting |
|---|
| | 280 | to this server. In fact, it should do so. |
|---|
| | 281 | |
|---|
| | 282 | If the server is opened already, this function should return a |
|---|
| | 283 | non-`nil' value. There should be no data returned. |
|---|
| | 284 | |
|---|
| | 285 | `(nnchoke-close-server &optional SERVER)' |
|---|
| | 286 | Close connection to SERVER and free all resources connected to it. |
|---|
| | 287 | Return `nil' if the server couldn't be closed for some reason. |
|---|
| | 288 | |
|---|
| | 289 | There should be no data returned. |
|---|
| | 290 | |
|---|
| | 291 | `(nnchoke-request-close)' |
|---|
| | 292 | Close connection to all servers and free all resources that the |
|---|
| | 293 | backend have reserved. All buffers that have been created by that |
|---|
| | 294 | backend should be killed. (Not the `nntp-server-buffer', though.) |
|---|
| | 295 | This function is generally only called when Gnus is shutting down. |
|---|
| | 296 | |
|---|
| | 297 | There should be no data returned. |
|---|
| | 298 | |
|---|
| | 299 | `(nnchoke-server-opened &optional SERVER)' |
|---|
| | 300 | If SERVER is the current virtual server, and the connection to the |
|---|
| | 301 | physical server is alive, then this function should return a |
|---|
| | 302 | non-`nil' vlue. This function should under no circumstances |
|---|
| | 303 | attempt to reconnect to a server we have lost connection to. |
|---|
| | 304 | |
|---|
| | 305 | There should be no data returned. |
|---|
| | 306 | |
|---|
| | 307 | `(nnchoke-status-message &optional SERVER)' |
|---|
| | 308 | This function should return the last error message from SERVER. |
|---|
| | 309 | |
|---|
| | 310 | There should be no data returned. |
|---|
| | 311 | |
|---|
| | 312 | `(nnchoke-request-article ARTICLE &optional GROUP SERVER TO-BUFFER)' |
|---|
| | 313 | The result data from this function should be the article specified |
|---|
| | 314 | by ARTICLE. This might either be a `Message-ID' or a number. It |
|---|
| | 315 | is optional whether to implement retrieval by `Message-ID', but it |
|---|
| | 316 | would be nice if that were possible. |
|---|
| | 317 | |
|---|
| | 318 | If TO-BUFFER is non-`nil', the result data should be returned in |
|---|
| | 319 | this buffer instead of the normal data buffer. This is to make it |
|---|
| | 320 | possible to avoid copying large amounts of data from one buffer to |
|---|
| | 321 | another, while Gnus mainly requests articles to be inserted |
|---|
| | 322 | directly into its article buffer. |
|---|
| | 323 | |
|---|
| | 324 | If it is at all possible, this function should return a cons cell |
|---|
| | 325 | where the `car' is the group name the article was fetched from, |
|---|
| | 326 | and the `cdr' is the article number. This will enable Gnus to |
|---|
| | 327 | find out what the real group and article numbers are when fetching |
|---|
| | 328 | articles by `Message-ID'. If this isn't possible, `t' should be |
|---|
| | 329 | returned on successful article retrieval. |
|---|
| | 330 | |
|---|
| | 331 | `(nnchoke-request-group GROUP &optional SERVER FAST)' |
|---|
| | 332 | Get data on GROUP. This function also has the side effect of |
|---|
| | 333 | making GROUP the current group. |
|---|
| | 334 | |
|---|
| | 335 | If FAST, don't bother to return useful data, just make GROUP the |
|---|
| | 336 | current group. |
|---|
| | 337 | |
|---|
| | 338 | Here's an example of some result data and a definition of the same: |
|---|
| | 339 | |
|---|
| | 340 | 211 56 1000 1059 ifi.discussion |
|---|
| | 341 | |
|---|
| | 342 | The first number is the status, which should be 211. Next is the |
|---|
| | 343 | total number of articles in the group, the lowest article number, |
|---|
| | 344 | the highest article number, and finally the group name. Note that |
|---|
| | 345 | the total number of articles may be less than one might think |
|---|
| | 346 | while just considering the highest and lowest article numbers, but |
|---|
| | 347 | some articles may have been canceled. Gnus just discards the |
|---|
| | 348 | total-number, so whether one should take the bother to generate it |
|---|
| | 349 | properly (if that is a problem) is left as an exercise to the |
|---|
| | 350 | reader. |
|---|
| | 351 | |
|---|
| | 352 | group-status = [ error / info ] eol |
|---|
| | 353 | error = [ "4" / "5" ] 2<number> " " <Error message> |
|---|
| | 354 | info = "211 " 3* [ <number> " " ] <string> |
|---|
| | 355 | |
|---|
| | 356 | `(nnchoke-close-group GROUP &optional SERVER)' |
|---|
| | 357 | Close GROUP and free any resources connected to it. This will be |
|---|
| | 358 | a no-op on most backends. |
|---|
| | 359 | |
|---|
| | 360 | There should be no data returned. |
|---|
| | 361 | |
|---|
| | 362 | `(nnchoke-request-list &optional SERVER)' |
|---|
| | 363 | Return a list of all groups available on SERVER. And that means |
|---|
| | 364 | _all_. |
|---|
| | 365 | |
|---|
| | 366 | Here's an example from a server that only carries two groups: |
|---|
| | 367 | |
|---|
| | 368 | ifi.test 0000002200 0000002000 y |
|---|
| | 369 | ifi.discussion 3324 3300 n |
|---|
| | 370 | |
|---|
| | 371 | On each line we have a group name, then the highest article number |
|---|
| | 372 | in that group, the lowest article number, and finally a flag. |
|---|
| | 373 | |
|---|
| | 374 | active-file = *active-line |
|---|
| | 375 | active-line = name " " <number> " " <number> " " flags eol |
|---|
| | 376 | name = <string> |
|---|
| | 377 | flags = "n" / "y" / "m" / "x" / "j" / "=" name |
|---|
| | 378 | |
|---|
| | 379 | The flag says whether the group is read-only (`n'), is moderated |
|---|
| | 380 | (`m'), is dead (`x'), is aliased to some other group |
|---|
| | 381 | (`=other-group') or none of the above (`y'). |
|---|
| | 382 | |
|---|
| | 383 | `(nnchoke-request-post &optional SERVER)' |
|---|
| | 384 | This function should post the current buffer. It might return |
|---|
| | 385 | whether the posting was successful or not, but that's not |
|---|
| | 386 | required. If, for instance, the posting is done asynchronously, |
|---|
| | 387 | it has generally not been completed by the time this function |
|---|
| | 388 | concludes. In that case, this function should set up some kind of |
|---|
| | 389 | sentinel to beep the user loud and clear if the posting could not |
|---|
| | 390 | be completed. |
|---|
| | 391 | |
|---|
| | 392 | There should be no result data from this function. |
|---|
| | 393 | |
|---|
| | 394 | |
|---|
| | 395 | File: gnus, Node: Optional Backend Functions, Next: Error Messaging, Prev: Required Backend Functions, Up: Backend Interface |
|---|
| | 396 | |
|---|
| | 397 | Optional Backend Functions |
|---|
| | 398 | .......................... |
|---|
| | 399 | |
|---|
| | 400 | `(nnchoke-retrieve-groups GROUPS &optional SERVER)' |
|---|
| | 401 | GROUPS is a list of groups, and this function should request data |
|---|
| | 402 | on all those groups. How it does it is of no concern to Gnus, but |
|---|
| | 403 | it should attempt to do this in a speedy fashion. |
|---|
| | 404 | |
|---|
| | 405 | The return value of this function can be either `active' or |
|---|
| | 406 | `group', which says what the format of the result data is. The |
|---|
| | 407 | former is in the same format as the data from |
|---|
| | 408 | `nnchoke-request-list', while the latter is a buffer full of lines |
|---|
| | 409 | in the same format as `nnchoke-request-group' gives. |
|---|
| | 410 | |
|---|
| | 411 | group-buffer = *active-line / *group-status |
|---|
| | 412 | |
|---|
| | 413 | `(nnchoke-request-update-info GROUP INFO &optional SERVER)' |
|---|
| | 414 | A Gnus group info (*note Group Info::) is handed to the backend for |
|---|
| | 415 | alterations. This comes in handy if the backend really carries |
|---|
| | 416 | all the information (as is the case with virtual and imap groups). |
|---|
| | 417 | This function should destructively alter the info to suit its |
|---|
| | 418 | needs, and should return the (altered) group info. |
|---|
| | 419 | |
|---|
| | 420 | There should be no result data from this function. |
|---|
| | 421 | |
|---|
| | 422 | `(nnchoke-request-type GROUP &optional ARTICLE)' |
|---|
| | 423 | When the user issues commands for "sending news" (`F' in the |
|---|
| | 424 | summary buffer, for instance), Gnus has to know whether the |
|---|
| | 425 | article the user is following up on is news or mail. This |
|---|
| | 426 | function should return `news' if ARTICLE in GROUP is news, `mail' |
|---|
| | 427 | if it is mail and `unknown' if the type can't be decided. (The |
|---|
| | 428 | ARTICLE parameter is necessary in `nnvirtual' groups which might |
|---|
| | 429 | very well combine mail groups and news groups.) Both GROUP and |
|---|
| | 430 | ARTICLE may be `nil'. |
|---|
| | 431 | |
|---|
| | 432 | There should be no result data from this function. |
|---|
| | 433 | |
|---|
| | 434 | `(nnchoke-request-set-mark GROUP ACTION &optional SERVER)' |
|---|
| | 435 | Set/remove/add marks on articles. Normally Gnus handles the |
|---|
| | 436 | article marks (such as read, ticked, expired etc) internally, and |
|---|
| | 437 | store them in `~/.newsrc.eld'. Some backends (such as IMAP) |
|---|
| | 438 | however carry all information about the articles on the server, so |
|---|
| | 439 | Gnus need to propagate the mark information to the server. |
|---|
| | 440 | |
|---|
| | 441 | ACTION is a list of mark setting requests, having this format: |
|---|
| | 442 | |
|---|
| | 443 | (RANGE ACTION MARK) |
|---|
| | 444 | |
|---|
| | 445 | Range is a range of articles you wish to update marks on. Action |
|---|
| | 446 | is `set', `add' or `del', respectively used for removing all |
|---|
| | 447 | existing marks and setting them as specified, adding (preserving |
|---|
| | 448 | the marks not mentioned) mark and removing (preserving the marks |
|---|
| | 449 | not mentioned) marks. Mark is a list of marks; where each mark is |
|---|
| | 450 | a symbol. Currently used marks are `read', `tick', `reply', |
|---|
| | 451 | `expire', `killed', `dormant', `save', `download' and `unsend', |
|---|
| | 452 | but your backend should, if possible, not limit itself to these. |
|---|
| | 453 | |
|---|
| | 454 | Given contradictory actions, the last action in the list should be |
|---|
| | 455 | the effective one. That is, if your action contains a request to |
|---|
| | 456 | add the `tick' mark on article 1 and, later in the list, a request |
|---|
| | 457 | to remove the mark on the same article, the mark should in fact be |
|---|
| | 458 | removed. |
|---|
| | 459 | |
|---|
| | 460 | An example action list: |
|---|
| | 461 | |
|---|
| | 462 | (((5 12 30) 'del '(tick)) |
|---|
| | 463 | ((10 . 90) 'add '(read expire)) |
|---|
| | 464 | ((92 94) 'del '(read))) |
|---|
| | 465 | |
|---|
| | 466 | The function should return a range of articles it wasn't able to |
|---|
| | 467 | set the mark on (currently not used for anything). |
|---|
| | 468 | |
|---|
| | 469 | There should be no result data from this function. |
|---|
| | 470 | |
|---|
| | 471 | `(nnchoke-request-update-mark GROUP ARTICLE MARK)' |
|---|
| | 472 | If the user tries to set a mark that the backend doesn't like, this |
|---|
| | 473 | function may change the mark. Gnus will use whatever this function |
|---|
| | 474 | returns as the mark for ARTICLE instead of the original MARK. If |
|---|
| | 475 | the backend doesn't care, it must return the original MARK, and |
|---|
| | 476 | not `nil' or any other type of garbage. |
|---|
| | 477 | |
|---|
| | 478 | The only use for this I can see is what `nnvirtual' does with |
|---|
| | 479 | it--if a component group is auto-expirable, marking an article as |
|---|
| | 480 | read in the virtual group should result in the article being |
|---|
| | 481 | marked as expirable. |
|---|
| | 482 | |
|---|
| | 483 | There should be no result data from this function. |
|---|
| | 484 | |
|---|
| | 485 | `(nnchoke-request-scan &optional GROUP SERVER)' |
|---|
| | 486 | This function may be called at any time (by Gnus or anything else) |
|---|
| | 487 | to request that the backend check for incoming articles, in one |
|---|
| | 488 | way or another. A mail backend will typically read the spool file |
|---|
| | 489 | or query the POP server when this function is invoked. The GROUP |
|---|
| | 490 | doesn't have to be heeded--if the backend decides that it is too |
|---|
| | 491 | much work just scanning for a single group, it may do a total scan |
|---|
| | 492 | of all groups. It would be nice, however, to keep things local if |
|---|
| | 493 | that's practical. |
|---|
| | 494 | |
|---|
| | 495 | There should be no result data from this function. |
|---|
| | 496 | |
|---|
| | 497 | `(nnchoke-request-group-description GROUP &optional SERVER)' |
|---|
| | 498 | The result data from this function should be a description of |
|---|
| | 499 | GROUP. |
|---|
| | 500 | |
|---|
| | 501 | description-line = name <TAB> description eol |
|---|
| | 502 | name = <string> |
|---|
| | 503 | description = <text> |
|---|
| | 504 | |
|---|
| | 505 | `(nnchoke-request-list-newsgroups &optional SERVER)' |
|---|
| | 506 | The result data from this function should be the description of all |
|---|
| | 507 | groups available on the server. |
|---|
| | 508 | |
|---|
| | 509 | description-buffer = *description-line |
|---|
| | 510 | |
|---|
| | 511 | `(nnchoke-request-newgroups DATE &optional SERVER)' |
|---|
| | 512 | The result data from this function should be all groups that were |
|---|
| | 513 | created after `date', which is in normal human-readable date |
|---|
| | 514 | format. The data should be in the active buffer format. |
|---|
| | 515 | |
|---|
| | 516 | `(nnchoke-request-create-group GROUP &optional SERVER)' |
|---|
| | 517 | This function should create an empty group with name GROUP. |
|---|
| | 518 | |
|---|
| | 519 | There should be no return data. |
|---|
| | 520 | |
|---|
| | 521 | `(nnchoke-request-expire-articles ARTICLES &optional GROUP SERVER FORCE)' |
|---|
| | 522 | This function should run the expiry process on all articles in the |
|---|
| | 523 | ARTICLES range (which is currently a simple list of article |
|---|
| | 524 | numbers.) It is left up to the backend to decide how old articles |
|---|
| | 525 | should be before they are removed by this function. If FORCE is |
|---|
| | 526 | non-`nil', all ARTICLES should be deleted, no matter how new they |
|---|
| | 527 | are. |
|---|
| | 528 | |
|---|
| | 529 | This function should return a list of articles that it did not/was |
|---|
| | 530 | not able to delete. |
|---|
| | 531 | |
|---|
| | 532 | There should be no result data returned. |
|---|
| | 533 | |
|---|
| | 534 | `(nnchoke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM' |
|---|
| | 535 | &optional LAST) |
|---|
| | 536 | |
|---|
| | 537 | This function should move ARTICLE (which is a number) from GROUP |
|---|
| | 538 | by calling ACCEPT-FORM. |
|---|
| | 539 | |
|---|
| | 540 | This function should ready the article in question for moving by |
|---|
| | 541 | removing any header lines it has added to the article, and |
|---|
| | 542 | generally should "tidy up" the article. Then it should `eval' |
|---|
| | 543 | ACCEPT-FORM in the buffer where the "tidy" article is. This will |
|---|
| | 544 | do the actual copying. If this `eval' returns a non-`nil' value, |
|---|
| | 545 | the article should be removed. |
|---|
| | 546 | |
|---|
| | 547 | If LAST is `nil', that means that there is a high likelihood that |
|---|
| | 548 | there will be more requests issued shortly, so that allows some |
|---|
| | 549 | optimizations. |
|---|
| | 550 | |
|---|
| | 551 | The function should return a cons where the `car' is the group |
|---|
| | 552 | name and the `cdr' is the article number that the article was |
|---|
| | 553 | entered as. |
|---|
| | 554 | |
|---|
| | 555 | There should be no data returned. |
|---|
| | 556 | |
|---|
| | 557 | `(nnchoke-request-accept-article GROUP &optional SERVER LAST)' |
|---|
| | 558 | This function takes the current buffer and inserts it into GROUP. |
|---|
| | 559 | If LAST in `nil', that means that there will be more calls to this |
|---|
| | 560 | function in short order. |
|---|
| | 561 | |
|---|
| | 562 | The function should return a cons where the `car' is the group |
|---|
| | 563 | name and the `cdr' is the article number that the article was |
|---|
| | 564 | entered as. |
|---|
| | 565 | |
|---|
| | 566 | There should be no data returned. |
|---|
| | 567 | |
|---|
| | 568 | `(nnchoke-request-replace-article ARTICLE GROUP BUFFER)' |
|---|
| | 569 | This function should remove ARTICLE (which is a number) from GROUP |
|---|
| | 570 | and insert BUFFER there instead. |
|---|
| | 571 | |
|---|
| | 572 | There should be no data returned. |
|---|
| | 573 | |
|---|
| | 574 | `(nnchoke-request-delete-group GROUP FORCE &optional SERVER)' |
|---|
| | 575 | This function should delete GROUP. If FORCE, it should really |
|---|
| | 576 | delete all the articles in the group, and then delete the group |
|---|
| | 577 | itself. (If there is such a thing as "the group itself".) |
|---|
| | 578 | |
|---|
| | 579 | There should be no data returned. |
|---|
| | 580 | |
|---|
| | 581 | `(nnchoke-request-rename-group GROUP NEW-NAME &optional SERVER)' |
|---|
| | 582 | This function should rename GROUP into NEW-NAME. All articles in |
|---|
| | 583 | GROUP should move to NEW-NAME. |
|---|
| | 584 | |
|---|
| | 585 | There should be no data returned. |
|---|
| | 586 | |
|---|
| | 587 | |
|---|
| | 588 | File: gnus, Node: Error Messaging, Next: Writing New Backends, Prev: Optional Backend Functions, Up: Backend Interface |
|---|
| | 589 | |
|---|
| | 590 | Error Messaging |
|---|
| | 591 | ............... |
|---|
| | 592 | |
|---|
| | 593 | The backends should use the function `nnheader-report' to report |
|---|
| | 594 | error conditions--they should not raise errors when they aren't able to |
|---|
| | 595 | perform a request. The first argument to this function is the backend |
|---|
| | 596 | symbol, and the rest are interpreted as arguments to `format' if there |
|---|
| | 597 | are multiple of them, or just a string if there is one of them. This |
|---|
| | 598 | function must always returns `nil'. |
|---|
| | 599 | |
|---|
| | 600 | (nnheader-report 'nnchoke "You did something totally bogus") |
|---|
| | 601 | |
|---|
| | 602 | (nnheader-report 'nnchoke "Could not request group %s" group) |
|---|
| | 603 | |
|---|
| | 604 | Gnus, in turn, will call `nnheader-get-report' when it gets a `nil' |
|---|
| | 605 | back from a server, and this function returns the most recently |
|---|
| | 606 | reported message for the backend in question. This function takes one |
|---|
| | 607 | argument--the server symbol. |
|---|
| | 608 | |
|---|
| | 609 | Internally, these functions access BACKEND`-status-string', so the |
|---|
| | 610 | `nnchoke' backend will have its error message stored in |
|---|
| | 611 | `nnchoke-status-string'. |
|---|
| | 612 | |
|---|
| | 613 | |
|---|
| | 614 | File: gnus, Node: Writing New Backends, Next: Hooking New Backends Into Gnus, Prev: Error Messaging, Up: Backend Interface |
|---|
| | 615 | |
|---|
| | 616 | Writing New Backends |
|---|
| | 617 | .................... |
|---|
| | 618 | |
|---|
| | 619 | Many backends are quite similar. `nnml' is just like `nnspool', but |
|---|
| | 620 | it allows you to edit the articles on the server. `nnmh' is just like |
|---|
| | 621 | `nnml', but it doesn't use an active file, and it doesn't maintain |
|---|
| | 622 | overview databases. `nndir' is just like `nnml', but it has no concept |
|---|
| | 623 | of "groups", and it doesn't allow editing articles. |
|---|
| | 624 | |
|---|
| | 625 | It would make sense if it were possible to "inherit" functions from |
|---|
| | 626 | backends when writing new backends. And, indeed, you can do that if you |
|---|
| | 627 | want to. (You don't have to if you don't want to, of course.) |
|---|
| | 628 | |
|---|
| | 629 | All the backends declare their public variables and functions by |
|---|
| | 630 | using a package called `nnoo'. |
|---|
| | 631 | |
|---|
| | 632 | To inherit functions from other backends (and allow other backends to |
|---|
| | 633 | inherit functions from the current backend), you should use the |
|---|
| | 634 | following macros: |
|---|
| | 635 | |
|---|
| | 636 | `nnoo-declare' |
|---|
| | 637 | This macro declares the first parameter to be a child of the |
|---|
| | 638 | subsequent parameters. For instance: |
|---|
| | 639 | |
|---|
| | 640 | (nnoo-declare nndir |
|---|
| | 641 | nnml nnmh) |
|---|
| | 642 | |
|---|
| | 643 | `nndir' has declared here that it intends to inherit functions from |
|---|
| | 644 | both `nnml' and `nnmh'. |
|---|
| | 645 | |
|---|
| | 646 | `defvoo' |
|---|
| | 647 | This macro is equivalent to `defvar', but registers the variable as |
|---|
| | 648 | a public server variable. Most state-oriented variables should be |
|---|
| | 649 | declared with `defvoo' instead of `defvar'. |
|---|
| | 650 | |
|---|
| | 651 | In addition to the normal `defvar' parameters, it takes a list of |
|---|
| | 652 | variables in the parent backends to map the variable to when |
|---|
| | 653 | executing a function in those backends. |
|---|
| | 654 | |
|---|
| | 655 | (defvoo nndir-directory nil |
|---|
| | 656 | "Where nndir will look for groups." |
|---|
| | 657 | nnml-current-directory nnmh-current-directory) |
|---|
| | 658 | |
|---|
| | 659 | This means that `nnml-current-directory' will be set to |
|---|
| | 660 | `nndir-directory' when an `nnml' function is called on behalf of |
|---|
| | 661 | `nndir'. (The same with `nnmh'.) |
|---|
| | 662 | |
|---|
| | 663 | `nnoo-define-basics' |
|---|
| | 664 | This macro defines some common functions that almost all backends |
|---|
| | 665 | should have. |
|---|
| | 666 | |
|---|
| | 667 | (nnoo-define-basics nndir) |
|---|
| | 668 | |
|---|
| | 669 | `deffoo' |
|---|
| | 670 | This macro is just like `defun' and takes the same parameters. In |
|---|
| | 671 | addition to doing the normal `defun' things, it registers the |
|---|
| | 672 | function as being public so that other backends can inherit it. |
|---|
| | 673 | |
|---|
| | 674 | `nnoo-map-functions' |
|---|
| | 675 | This macro allows mapping of functions from the current backend to |
|---|
| | 676 | functions from the parent backends. |
|---|
| | 677 | |
|---|
| | 678 | (nnoo-map-functions nndir |
|---|
| | 679 | (nnml-retrieve-headers 0 nndir-current-group 0 0) |
|---|
| | 680 | (nnmh-request-article 0 nndir-current-group 0 0)) |
|---|
| | 681 | |
|---|
| | 682 | This means that when `nndir-retrieve-headers' is called, the first, |
|---|
| | 683 | third, and fourth parameters will be passed on to |
|---|
| | 684 | `nnml-retrieve-headers', while the second parameter is set to the |
|---|
| | 685 | value of `nndir-current-group'. |
|---|
| | 686 | |
|---|
| | 687 | `nnoo-import' |
|---|
| | 688 | This macro allows importing functions from backends. It should be |
|---|
| | 689 | the last thing in the source file, since it will only define |
|---|
| | 690 | functions that haven't already been defined. |
|---|
| | 691 | |
|---|
| | 692 | (nnoo-import nndir |
|---|
| | 693 | (nnmh |
|---|
| | 694 | nnmh-request-list |
|---|
| | 695 | nnmh-request-newgroups) |
|---|
| | 696 | (nnml)) |
|---|
| | 697 | |
|---|
| | 698 | This means that calls to `nndir-request-list' should just be passed |
|---|
| | 699 | on to `nnmh-request-list', while all public functions from `nnml' |
|---|
| | 700 | that haven't been defined in `nndir' yet should be defined now. |
|---|
| | 701 | |
|---|
| | 702 | Below is a slightly shortened version of the `nndir' backend. |
|---|
| | 703 | |
|---|
| | 704 | ;;; nndir.el --- single directory newsgroup access for Gnus |
|---|
| | 705 | ;; Copyright (C) 1995,96 Free Software Foundation, Inc. |
|---|
| | 706 | |
|---|
| | 707 | ;;; Code: |
|---|
| | 708 | |
|---|
| | 709 | (require 'nnheader) |
|---|
| | 710 | (require 'nnmh) |
|---|
| | 711 | (require 'nnml) |
|---|
| | 712 | (require 'nnoo) |
|---|
| | 713 | (eval-when-compile (require 'cl)) |
|---|
| | 714 | |
|---|
| | 715 | (nnoo-declare nndir |
|---|
| | 716 | nnml nnmh) |
|---|
| | 717 | |
|---|
| | 718 | (defvoo nndir-directory nil |
|---|
| | 719 | "Where nndir will look for groups." |
|---|
| | 720 | nnml-current-directory nnmh-current-directory) |
|---|
| | 721 | |
|---|
| | 722 | (defvoo nndir-nov-is-evil nil |
|---|
| | 723 | "*Non-nil means that nndir will never retrieve NOV headers." |
|---|
| | 724 | nnml-nov-is-evil) |
|---|
| | 725 | |
|---|
| | 726 | (defvoo nndir-current-group "" |
|---|
| | 727 | nil |
|---|
| | 728 | nnml-current-group nnmh-current-group) |
|---|
| | 729 | (defvoo nndir-top-directory nil nil nnml-directory nnmh-directory) |
|---|
| | 730 | (defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail) |
|---|
| | 731 | |
|---|
| | 732 | (defvoo nndir-status-string "" nil nnmh-status-string) |
|---|
| | 733 | (defconst nndir-version "nndir 1.0") |
|---|
| | 734 | |
|---|
| | 735 | ;;; Interface functions. |
|---|
| | 736 | |
|---|
| | 737 | (nnoo-define-basics nndir) |
|---|
| | 738 | |
|---|
| | 739 | (deffoo nndir-open-server (server &optional defs) |
|---|
| | 740 | (setq nndir-directory |
|---|
| | 741 | (or (cadr (assq 'nndir-directory defs)) |
|---|
| | 742 | server)) |
|---|
| | 743 | (unless (assq 'nndir-directory defs) |
|---|
| | 744 | (push `(nndir-directory ,server) defs)) |
|---|
| | 745 | (push `(nndir-current-group |
|---|
| | 746 | ,(file-name-nondirectory |
|---|
| | 747 | (directory-file-name nndir-directory))) |
|---|
| | 748 | defs) |
|---|
| | 749 | (push `(nndir-top-directory |
|---|
| | 750 | ,(file-name-directory (directory-file-name nndir-directory))) |
|---|
| | 751 | defs) |
|---|
| | 752 | (nnoo-change-server 'nndir server defs)) |
|---|
| | 753 | |
|---|
| | 754 | (nnoo-map-functions nndir |
|---|
| | 755 | (nnml-retrieve-headers 0 nndir-current-group 0 0) |
|---|
| | 756 | (nnmh-request-article 0 nndir-current-group 0 0) |
|---|
| | 757 | (nnmh-request-group nndir-current-group 0 0) |
|---|
| | 758 | (nnmh-close-group nndir-current-group 0)) |
|---|
| | 759 | |
|---|
| | 760 | (nnoo-import nndir |
|---|
| | 761 | (nnmh |
|---|
| | 762 | nnmh-status-message |
|---|
| | 763 | nnmh-request-list |
|---|
| | 764 | nnmh-request-newgroups)) |
|---|
| | 765 | |
|---|
| | 766 | (provide 'nndir) |
|---|
| | 767 | |
|---|
| | 768 | |
|---|
| | 769 | File: gnus, Node: Hooking New Backends Into Gnus, Next: Mail-like Backends, Prev: Writing New Backends, Up: Backend Interface |
|---|
| | 770 | |
|---|
| | 771 | Hooking New Backends Into Gnus |
|---|
| | 772 | .............................. |
|---|
| | 773 | |
|---|
| | 774 | Having Gnus start using your new backend is rather easy--you just |
|---|
| | 775 | declare it with the `gnus-declare-backend' functions. This will enter |
|---|
| | 776 | the backend into the `gnus-valid-select-methods' variable. |
|---|
| | 777 | |
|---|
| | 778 | `gnus-declare-backend' takes two parameters--the backend name and an |
|---|
| | 779 | arbitrary number of "abilities". |
|---|
| | 780 | |
|---|
| | 781 | Here's an example: |
|---|
| | 782 | |
|---|
| | 783 | (gnus-declare-backend "nnchoke" 'mail 'respool 'address) |
|---|
| | 784 | |
|---|
| | 785 | The abilities can be: |
|---|
| | 786 | |
|---|
| | 787 | `mail' |
|---|
| | 788 | This is a mailish backend--followups should (probably) go via mail. |
|---|
| | 789 | |
|---|
| | 790 | `post' |
|---|
| | 791 | This is a newsish backend--followups should (probably) go via news. |
|---|
| | 792 | |
|---|
| | 793 | `post-mail' |
|---|
| | 794 | This backend supports both mail and news. |
|---|
| | 795 | |
|---|
| | 796 | `none' |
|---|
| | 797 | This is neither a post nor mail backend--it's something completely |
|---|
| | 798 | different. |
|---|
| | 799 | |
|---|
| | 800 | `respool' |
|---|
| | 801 | It supports respooling--or rather, it is able to modify its source |
|---|
| | 802 | articles and groups. |
|---|
| | 803 | |
|---|
| | 804 | `address' |
|---|
| | 805 | The name of the server should be in the virtual server name. This |
|---|
| | 806 | is true for almost all backends. |
|---|
| | 807 | |
|---|
| | 808 | `prompt-address' |
|---|
| | 809 | The user should be prompted for an address when doing commands like |
|---|
| | 810 | `B' in the group buffer. This is true for backends like `nntp', |
|---|
| | 811 | but not `nnmbox', for instance. |
|---|
| | 812 | |
|---|
| | 813 | |
|---|
| | 814 | File: gnus, Node: Mail-like Backends, Prev: Hooking New Backends Into Gnus, Up: Backend Interface |
|---|
| | 815 | |
|---|
| | 816 | Mail-like Backends |
|---|
| | 817 | .................. |
|---|
| | 818 | |
|---|
| | 819 | One of the things that separate the mail backends from the rest of |
|---|
| | 820 | the backends is the heavy dependence by the mail backends on common |
|---|
| | 821 | functions in `nnmail.el'. For instance, here's the definition of |
|---|
| | 822 | `nnml-request-scan': |
|---|
| | 823 | |
|---|
| | 824 | (deffoo nnml-request-scan (&optional group server) |
|---|
| | 825 | (setq nnml-article-file-alist nil) |
|---|
| | 826 | (nnmail-get-new-mail 'nnml 'nnml-save-nov nnml-directory group)) |
|---|
| | 827 | |
|---|
| | 828 | It simply calls `nnmail-get-new-mail' with a few parameters, and |
|---|
| | 829 | `nnmail' takes care of all the moving and splitting of the mail. |
|---|
| | 830 | |
|---|
| | 831 | This function takes four parameters. |
|---|
| | 832 | |
|---|
| | 833 | METHOD |
|---|
| | 834 | This should be a symbol to designate which backend is responsible |
|---|
| | 835 | for the call. |
|---|
| | 836 | |
|---|
| | 837 | EXIT-FUNCTION |
|---|
| | 838 | This function should be called after the splitting has been |
|---|
| | 839 | performed. |
|---|
| | 840 | |
|---|
| | 841 | TEMP-DIRECTORY |
|---|
| | 842 | Where the temporary files should be stored. |
|---|
| | 843 | |
|---|
| | 844 | GROUP |
|---|
| | 845 | This optional argument should be a group name if the splitting is |
|---|
| | 846 | to be performed for one group only. |
|---|
| | 847 | |
|---|
| | 848 | `nnmail-get-new-mail' will call BACKEND`-save-mail' to save each |
|---|
| | 849 | article. BACKEND`-active-number' will be called to find the article |
|---|
| | 850 | number assigned to this article. |
|---|
| | 851 | |
|---|
| | 852 | The function also uses the following variables: |
|---|
| | 853 | BACKEND`-get-new-mail' (to see whether to get new mail for this |
|---|
| | 854 | backend); and BACKEND`-group-alist' and BACKEND`-active-file' to |
|---|
| | 855 | generate the new active file. BACKEND`-group-alist' should be a |
|---|
| | 856 | group-active alist, like this: |
|---|
| | 857 | |
|---|
| | 858 | (("a-group" (1 . 10)) |
|---|
| | 859 | ("some-group" (34 . 39))) |
|---|
| | 860 | |
|---|
| | 861 | |
|---|
| | 862 | File: gnus, Node: Score File Syntax, Next: Headers, Prev: Backend Interface, Up: Gnus Reference Guide |
|---|
| | 863 | |
|---|
| | 864 | Score File Syntax |
|---|
| | 865 | ----------------- |
|---|
| | 866 | |
|---|
| | 867 | Score files are meant to be easily parseable, but yet extremely |
|---|
| | 868 | mallable. It was decided that something that had the same read syntax |
|---|
| | 869 | as an Emacs Lisp list would fit that spec. |
|---|
| | 870 | |
|---|
| | 871 | Here's a typical score file: |
|---|
| | 872 | |
|---|
| | 873 | (("summary" |
|---|
| | 874 | ("win95" -10000 nil s) |
|---|
| | 875 | ("Gnus")) |
|---|
| | 876 | ("from" |
|---|
| | 877 | ("Lars" -1000)) |
|---|
| | 878 | (mark -100)) |
|---|
| | 879 | |
|---|
| | 880 | BNF definition of a score file: |
|---|
| | 881 | |
|---|
| | 882 | score-file = "" / "(" *element ")" |
|---|
| | 883 | element = rule / atom |
|---|
| | 884 | rule = string-rule / number-rule / date-rule |
|---|
| | 885 | string-rule = "(" quote string-header quote space *string-match ")" |
|---|
| | 886 | number-rule = "(" quote number-header quote space *number-match ")" |
|---|
| | 887 | date-rule = "(" quote date-header quote space *date-match ")" |
|---|
| | 888 | quote = <ascii 34> |
|---|
| | 889 | string-header = "subject" / "from" / "references" / "message-id" / |
|---|
| | 890 | "xref" / "body" / "head" / "all" / "followup" |
|---|
| | 891 | number-header = "lines" / "chars" |
|---|
| | 892 | date-header = "date" |
|---|
| | 893 | string-match = "(" quote <string> quote [ "" / [ space score [ "" / |
|---|
| | 894 | space date [ "" / [ space string-match-t ] ] ] ] ] ")" |
|---|
| | 895 | score = "nil" / <integer> |
|---|
| | 896 | date = "nil" / <natural number> |
|---|
| | 897 | string-match-t = "nil" / "s" / "substring" / "S" / "Substring" / |
|---|
| | 898 | "r" / "regex" / "R" / "Regex" / |
|---|
| | 899 | "e" / "exact" / "E" / "Exact" / |
|---|
| | 900 | "f" / "fuzzy" / "F" / "Fuzzy" |
|---|
| | 901 | number-match = "(" <integer> [ "" / [ space score [ "" / |
|---|
| | 902 | space date [ "" / [ space number-match-t ] ] ] ] ] ")" |
|---|
| | 903 | number-match-t = "nil" / "=" / "<" / ">" / ">=" / "<=" |
|---|
| | 904 | date-match = "(" quote <string> quote [ "" / [ space score [ "" / |
|---|
| | 905 | space date [ "" / [ space date-match-t ] ] ] ] ")" |
|---|
| | 906 | date-match-t = "nil" / "at" / "before" / "after" |
|---|
| | 907 | atom = "(" [ required-atom / optional-atom ] ")" |
|---|
| | 908 | required-atom = mark / expunge / mark-and-expunge / files / |
|---|
| | 909 | exclude-files / read-only / touched |
|---|
| | 910 | optional-atom = adapt / local / eval |
|---|
| | 911 | mark = "mark" space nil-or-number |
|---|
| | 912 | nil-or-number = "nil" / <integer> |
|---|
| | 913 | expunge = "expunge" space nil-or-number |
|---|
| | 914 | mark-and-expunge = "mark-and-expunge" space nil-or-number |
|---|
| | 915 | files = "files" *[ space <string> ] |
|---|
| | 916 | exclude-files = "exclude-files" *[ space <string> ] |
|---|
| | 917 | read-only = "read-only" [ space "nil" / space "t" ] |
|---|
| | 918 | adapt = "adapt" [ space "ignore" / space "t" / space adapt-rule ] |
|---|
| | 919 | adapt-rule = "(" *[ <string> *[ "(" <string> <integer> ")" ] ")" |
|---|
| | 920 | local = "local" *[ space "(" <string> space <form> ")" ] |
|---|
| | 921 | eval = "eval" space <form> |
|---|
| | 922 | space = *[ " " / <TAB> / <NEWLINE> ] |
|---|
| | 923 | |
|---|
| | 924 | Any unrecognized elements in a score file should be ignored, but not |
|---|
| | 925 | discarded. |
|---|
| | 926 | |
|---|
| | 927 | As you can see, white space is needed, but the type and amount of |
|---|
| | 928 | white space is irrelevant. This means that formatting of the score |
|---|
| | 929 | file is left up to the programmer--if it's simpler to just spew it all |
|---|
| | 930 | out on one looong line, then that's ok. |
|---|
| | 931 | |
|---|
| | 932 | The meaning of the various atoms are explained elsewhere in this |
|---|
| | 933 | manual (*note Score File Format::). |
|---|
| | 934 | |
|---|
| | 935 | |
|---|
| | 936 | File: gnus, Node: Headers, Next: Ranges, Prev: Score File Syntax, Up: Gnus Reference Guide |
|---|
| | 937 | |
|---|
| | 938 | Headers |
|---|
| | 939 | ------- |
|---|
| | 940 | |
|---|
| | 941 | Internally Gnus uses a format for storing article headers that |
|---|
| | 942 | corresponds to the NOV format in a mysterious fashion. One could |
|---|
| | 943 | almost suspect that the author looked at the NOV specification and just |
|---|
| | 944 | shamelessly _stole_ the entire thing, and one would be right. |
|---|
| | 945 | |
|---|
| | 946 | "Header" is a severely overloaded term. "Header" is used in RFC |
|---|
| | 947 | 1036 to talk about lines in the head of an article (e.g., `From'). It |
|---|
| | 948 | is used by many people as a synonym for "head"--"the header and the |
|---|
| | 949 | body". (That should be avoided, in my opinion.) And Gnus uses a |
|---|
| | 950 | format internally that it calls "header", which is what I'm talking |
|---|
| | 951 | about here. This is a 9-element vector, basically, with each header |
|---|
| | 952 | (ouch) having one slot. |
|---|
| | 953 | |
|---|
| | 954 | These slots are, in order: `number', `subject', `from', `date', |
|---|
| | 955 | `id', `references', `chars', `lines', `xref', and `extra'. There are |
|---|
| | 956 | macros for accessing and setting these slots--they all have predictable |
|---|
| | 957 | names beginning with `mail-header-' and `mail-header-set-', |
|---|
| | 958 | respectively. |
|---|
| | 959 | |
|---|
| | 960 | All these slots contain strings, except the `extra' slot, which |
|---|
| | 961 | contains an alist of header/value pairs (*note To From Newsgroups::). |
|---|
| | 962 | |
|---|
| | 963 | |
|---|
| | 964 | File: gnus, Node: Ranges, Next: Group Info, Prev: Headers, Up: Gnus Reference Guide |
|---|
| | 965 | |
|---|
| | 966 | Ranges |
|---|
| | 967 | ------ |
|---|
| | 968 | |
|---|
| | 969 | GNUS introduced a concept that I found so useful that I've started |
|---|
| | 970 | using it a lot and have elaborated on it greatly. |
|---|
| | 971 | |
|---|
| | 972 | The question is simple: If you have a large amount of objects that |
|---|
| | 973 | are identified by numbers (say, articles, to take a _wild_ example) |
|---|
| | 974 | that you want to qualify as being "included", a normal sequence isn't |
|---|
| | 975 | very useful. (A 200,000 length sequence is a bit long-winded.) |
|---|
| | 976 | |
|---|
| | 977 | The solution is as simple as the question: You just collapse the |
|---|
| | 978 | sequence. |
|---|
| | 979 | |
|---|
| | 980 | (1 2 3 4 5 6 10 11 12) |
|---|
| | 981 | |
|---|
| | 982 | is transformed into |
|---|
| | 983 | |
|---|
| | 984 | ((1 . 6) (10 . 12)) |
|---|
| | 985 | |
|---|
| | 986 | To avoid having those nasty `(13 . 13)' elements to denote a |
|---|
| | 987 | lonesome object, a `13' is a valid element: |
|---|
| | 988 | |
|---|
| | 989 | ((1 . 6) 7 (10 . 12)) |
|---|
| | 990 | |
|---|
| | 991 | This means that comparing two ranges to find out whether they are |
|---|
| | 992 | equal is slightly tricky: |
|---|
| | 993 | |
|---|
| | 994 | ((1 . 5) 7 8 (10 . 12)) |
|---|
| | 995 | |
|---|
| | 996 | and |
|---|
| | 997 | |
|---|
| | 998 | ((1 . 5) (7 . 8) (10 . 12)) |
|---|
| | 999 | |
|---|
| | 1000 | are equal. In fact, any non-descending list is a range: |
|---|
| | 1001 | |
|---|
| | 1002 | (1 2 3 4 5) |
|---|
| | 1003 | |
|---|
| | 1004 | is a perfectly valid range, although a pretty long-winded one. This |
|---|
| | 1005 | is also valid: |
|---|
| | 1006 | |
|---|
| | 1007 | (1 . 5) |
|---|
| | 1008 | |
|---|
| | 1009 | and is equal to the previous range. |
|---|
| | 1010 | |
|---|
| | 1011 | Here's a BNF definition of ranges. Of course, one must remember the |
|---|
| | 1012 | semantic requirement that the numbers are non-descending. (Any number |
|---|
| | 1013 | of repetition of the same number is allowed, but apt to disappear in |
|---|
| | 1014 | range handling.) |
|---|
| | 1015 | |
|---|
| | 1016 | range = simple-range / normal-range |
|---|
| | 1017 | simple-range = "(" number " . " number ")" |
|---|
| | 1018 | normal-range = "(" start-contents ")" |
|---|
| | 1019 | contents = "" / simple-range *[ " " contents ] / |
|---|
| | 1020 | number *[ " " contents ] |
|---|
| | 1021 | |
|---|
| | 1022 | Gnus currently uses ranges to keep track of read articles and article |
|---|
| | 1023 | marks. I plan on implementing a number of range operators in C if The |
|---|
| | 1024 | Powers That Be are willing to let me. (I haven't asked yet, because I |
|---|
| | 1025 | need to do some more thinking on what operators I need to make life |
|---|
| | 1026 | totally range-based without ever having to convert back to normal |
|---|
| | 1027 | sequences.) |
|---|
| | 1028 | |
|---|
| | 1029 | |
|---|
| | 1030 | File: gnus, Node: Group Info, Next: Extended Interactive, Prev: Ranges, Up: Gnus Reference Guide |
|---|
| | 1031 | |
|---|
| | 1032 | Group Info |
|---|