
(provide (quote cheapcite))

(defvar sc-nested-citation-p nil "\
*Controls whether to use nested or non-nested citation style.")

(defvar sc-citation-leader "" "\
*String used at the front of a composed citation.")

(defvar sc-citation-delimiter ">" "\
*String to use at the end of a composed citation.  
This string is used in both nested and non-nested citations.  For best
results, use a single character with no trailing space.")

(defvar sc-citation-separator " " "\
*String used to separate the composed citation and the cited line.
Normally this character is a single space character though often a
single tab character is used.")

(defvar sc-cite-regexp "\\s *[a-zA-Z0-9]*\\s *>+\\s *" "\
*Regular expression describing how a already cited line begins.
The regexp is only used at the beginning of a line, so it doesn't need
to start with a '^'.")

(defvar sc-fill-paragraph-hook (quote sc-fill-paragraph) "\
*Hook for filling a paragraph.  
This hook gets executed when you fill a paragraph either manually or
automagically. It expects point to be within the extent of the
paragraph that is going to be filled.")

(defvar sc-auto-fill-region-p nil "\
*If non-nil, automatically fill each paragraph after it has been cited.")

(defvar sc-fixup-whitespace-p nil "\
*If non-nil, delete all leading white space before citing.")

(defvar sc-nuke-mail-headers-p t "\
*Nuke or don't nuke mail headers.
If non-nil, nuke mail headers after gleaning useful information form
them. If nil, don't nuke mail headers.")

(defvar sc-run-hook nil "\
*User definable hook.
Runs after sc-cite-original executes.")

(defvar sc-load-hook nil "\
*User definable hook.
Runs after cheapcite is loaded. Set your customizations here.")

(defvar sc-rewrite-header-hook (quote sc-standard-header) "\
*User definable hook.
Runs before original mail headers are nuked.  Set it to a function
which will write a header for you.  See sc-mail-fetch-field for how to
include information in your header, and sc-standard-header for an
example function.

NOTE: do not use 'insert' in your function.  Use 'insert-before-markers`.")

(defvar sc-default-keymap (quote (lambda nil (local-set-key "" (quote sc-cite)) (local-set-key "" (quote sc-recite)) (local-set-key "" (quote sc-uncite)) (local-set-key "	" (quote sc-insert-citation)) (local-set-key "" (quote sc-open-line)) (local-set-key "" (quote sc-fill-paragraph-manually)) (local-set-key "q" (quote sc-fill-paragraph-manually)) (local-set-key "" (quote sc-version)) (local-set-key "?" (quote sc-describe)))) "\
*Variable which contains function to set keymap.")

(defconst sc-version-number "2.1")

(setq news-reply-header-hook nil)

(make-variable-buffer-local (quote sc-fill-arg))

(make-variable-buffer-local (quote sc-attribution-string))

(make-variable-buffer-local (quote sc-citation-string))

(setq-default sc-fill-arg nil)

(setq-default sc-attribution-string "")

(setq-default sc-citation-string "")

(setq sc-mail-yank-ignored-headers (concat "^via:\\|^origin:\\|^status:\\|^received:\\|^remailed\\|" "^[a-z-]*message-id:\\|^\\(summary-\\)?line[s]?:\\|^cc:\\|" "^subject:\\|^\\(\\(in-\\)?reply-\\)?to:\\|^sender:\\|^replied:\\|" "^\\(\\(return\\|reply\\)-\\)?path:\\|^\\(posted-\\)?date:\\|" "^\\(mail-\\)?from:\\|^newsgroup[s]?:\\|^organization:\\|^keywords:\\|" "^distribution:\\|^xref:\\|^references:\\|^x-mailer:\\|" "^\\(x-\\)?followup-to:\\|^x-vm-attributes:\\|^expires:\\|" "^approved:\\|^apparently-to:\\|^summary:\\|" "^x-vm-attributes:\\|^x-vm-v[0-9]+-data:"))

(defun sc-mail-yank-clear-headers (start end) "\
Nuke mail headers between START and END. 
Use sc-mail-yank-ignored-headers to determine which headers to nuke." (byte-code "b	#4 `\"b#)3  `!!`\" ))" [start end t case-fold-search sc-mail-yank-ignored-headers nil search-forward "

" narrow-to-region re-search-forward beginning-of-line delete-region "
[^ 	]" forward-char -1] 10))

(defun sc-mail-fetch-field (field) "\
Return the value of the header field FIELD.
The buffer is expected to be narrowed to just the headers of the
message." (byte-code "eb!Qeb
#0 `!!) Ĉ `S\")*)" [case-fold-search t name field nil opoint "^" regexp-quote "[ 	]*:[ 	]*" re-search-forward forward-line 1 looking-at "[ 	]" buffer-substring] 7))

(defun sc-standard-header nil "\
Write a standard reference header." (byte-code "!	 #" [insert-before-markers ">>>>> " sc-mail-fetch-field "from" "Some anonymous person" " writes:

"] 5))

(defun sc-query (default) "\
Query for an attribution string with the DEFAULT choice.
Returns the string entered by the user, if non-empty and non-nil, or
DEFAULT otherwise." (byte-code "	=
 Ƃ 	= Ȃ !\"?$ QQ!?3 \": ; *" [prompt sc-cite-context t default query citing "Cite" reciting "Recite" error "Cheapcite Error: sc-cite-context invalid!" " with attribution string: " string= "" "(default " ") " read-string] 7))

(defun sc-guess-fill-prefix nil "\
Guess the fill prefix used on the current line.
Use various heuristics to find the fill prefix. Search begins on first
non-blank line in the region delineated by point and mark.

     1) If fill-prefix is already bound to the empty string, return
        nil.

     2) If fill-prefix is already bound, but not to the empty
        string, return the value of fill-prefix.

     3) If the current line starts with the last chosen citation
        string, then that string is returned.

     4) If the current line starts with a string matching the regular
        expression, sc-cite-regexp, then that string is returned.

     5) Nil is returned." (byte-code " ` W l ! 	
\"$ Âa 
a !!4 a !I `Pd#`\"a Q!` `Q!`\"a ))" [citation sc-citation-string fill-prefix nil sc-cite-regexp sc-citation-delimiter t beginning-of-line mark forward-line 1 string= "" looking-at regexp-quote buffer-substring re-search-forward "\\s *" ".*"] 16))

(defun sc-consistant-cite-p (prefix) "\
Check current paragraph for consistant citation.
Scans to paragraph delineated by (forward|backward)-paragraph to see
if all lines start with PREFIX. Returns t if entire paragraph is
consistantly cited, nil otherwise." (byte-code "  l? !`  l? !`	b `W2 
B !!+ 
+)" [end start badline t prefix forward-paragraph beginning-of-line forward-char -1 backward-paragraph 1 looking-at forward-line] 11))

(defun sc-fill-start (fill-prefix) "\
Find buffer position of start of region which begins with FILL-PREFIX.
Restrict scan to current paragraph." (byte-code "  l? !`)? `
V/ !!? *!`)" [badline nil top fill-prefix backward-paragraph beginning-of-line forward-char 1 forward-line -1 looking-at] 8))

(defun sc-fill-end (fill-prefix) "\
Find the buffer position of end of region which begins with FILL-PREFIX.
Restrict scan to current paragraph." (byte-code "  l? !`)? `
W2  !?! *!`)" [badline nil bot fill-prefix forward-paragraph beginning-of-line forward-char -1 looking-at forward-line 1] 8))

(defun sc-fill-paragraph nil "\
Cheapcite's paragraph fill function.
Fill the paragraph containing or following point. Use
sc-guess-fill-prefix to find the fill-prefix for the paragraph.

If the paragraph is inconsistantly cited (mixed fill-prefix), then the
user is queried to restrict the the fill to only those lines around
point which begin with the fill prefix.

The variable sc-fill-arg is passed to fill-paragraph and
fill-region-as-paragraph which controls justification of the
paragraph.  sc-fill-arg is set by sc-fill-paragraph-manually." (byte-code "` 	? 
!D 	! 
!D !9 !b	!b	!
#D !
!*)" [pnt fill-prefix sc-fill-arg t sc-citation-string sc-guess-fill-prefix fill-paragraph sc-consistant-cite-p y-or-n-p "Inconsistent citation found. Restrict? " message "" fill-region-as-paragraph sc-fill-start sc-fill-end] 12))

(defun sc-cite-region (start end) "\
Cite the region between START and END." (byte-code "!	b ``` Wm   lH 
U? ?? !
#\"b!)``a !?Z V ca a 	`! *)" [end start fstart fend sc-fixup-whitespace-p sc-auto-fill-region-p sc-cite-regexp sc-citation-string sc-nested-citation-p sc-citation-delimiter set-mark beginning-of-line mark fixup-whitespace / + 1 2 run-hooks sc-fill-paragraph-hook looking-at "" forward-line] 12))

(defun sc-uncite-region (start end cite-regexp) "\
Uncite the previously cited region between START and END.
CITE-REGEXP describes how a cited line of texts starts.  Unciting also
auto-fills paragraph if sc-auto-fill-region-p is non-nil." (byte-code "!	b ``` Wq lA 
U8 ?8 !
#\"b!)``e !e  ` `\" ed#!\"))`! *)" [end start fstart fend sc-auto-fill-region-p cite-regexp t set-mark beginning-of-line mark / + 1 2 run-hooks sc-fill-paragraph-hook looking-at narrow-to-region end-of-line delete-region re-search-forward match-end 0 forward-line] 19))

(defun sc-cite nil "\
Cite the region of text between point and mark.

The mail header lines should be at the top of the region, with the
body of the reply following.  These mail header lines will be parse
first for useful information, then deleted." (interactive) (byte-code "  `V   !R` \"` WC 	@ A !?M !. T  *" [xchange nil t sc-cite-context sc-attribution-string sc-citation-string sc-citation-leader sc-citation-delimiter sc-citation-separator sc-nested-citation-p undo-boundary mark exchange-point-and-mark citing sc-query sc-cite-region looking-at forward-line 1] 11))

(defun sc-uncite nil "\
Uncite the region between point and mark." (interactive) (byte-code "  `V     ` !#+  *" [xchange nil t fp undo-boundary mark exchange-point-and-mark sc-guess-fill-prefix "" sc-uncite-region regexp-quote] 10))

(defun sc-recite nil "\
Recite the region by first unciting then citing the text." (interactive) (byte-code "  `V   !`  !#R` \">  *" [xchange nil t sc-cite-context sc-attribution-string sc-citation-string sc-citation-leader sc-citation-delimiter sc-citation-separator undo-boundary mark exchange-point-and-mark reciting sc-query sc-uncite-region regexp-quote sc-guess-fill-prefix sc-cite-region] 12))

(defun sc-insert-citation nil "\
Insert citation string at beginning of current line." (interactive) (byte-code " c)" [sc-attribution-string nil beginning-of-line] 2))

(defun sc-open-line (arg) "\
Insert a newline and leave point before it.
Also inserts the guessed prefix at the beginning of the new line. With
numeric ARG, inserts that many newlines." (interactive "p") (byte-code "È` 
!b!
W) 	c!
Z *)" [start string arg nil sc-guess-fill-prefix open-line forward-line 1 0] 7))

(defun sc-fill-paragraph-manually (arg) "\
Fill current cited paragraph.
Really just runs the hook sc-fill-paragraph-hook, however it does set
the global variable sc-fill-arg to the value of ARG.  This is
currently the only way to pass an argument to a hookified function." (interactive "P") (byte-code "	!" [sc-fill-arg arg nil run-hooks sc-fill-paragraph-hook] 2))

(defun sc-version nil "\
Show cheapcite version." (interactive) (byte-code "\"" [sc-version-number nil message "Using Cheapcite %s"] 3))

(defun sc-append-current-keymap nil "\
Append some useful key bindings to the current local key map." (byte-code "! " [sc-leached-keymap run-hooks sc-default-keymap current-local-map] 4))

(defun sc-snag-all-keybindings nil "\
Snag all keybindings in major-modes current keymap." (byte-code " !
GW 	
#4 
!!OP! ." [curkeymap symregexp docstring start maxend spooge current-local-map ".*sc-.*
" substitute-command-keys "\\{curkeymap}" 0 "" string-match match-beginning match-end] 10))

(defun sc-spoogify-docstring nil "\
Modifies (makes into spooge) the docstring for the current major mode.
This will leach the keybinding descriptions for cheapcite onto the end
of the current major mode's docstring.  If major mode is preloaded,
this function will first make a copy of the list associated with the
mode, then modify this copy." (byte-code "	K\"	!;?$ \"$  QϏ)+" [symfunc major-mode doc-cdr doc-str t newdoc-str nthcdr 2 documentation string-match "Cheapcite" "

The major mode for this buffer has been modified to include the
Cheapcite 2.1 package for handling attributions and citations of
original messages in email replies.  For more information on this
package, type \"\\[sc-describe]\" (see below).  The following keys are
bound to Cheapcite commands:

" sc-snag-all-keybindings nil (byte-code "	\"" [doc-cdr newdoc-str setcar] 3) ((error (byte-code "	K!\"
\"	M" [symfunc major-mode doc-cdr newdoc-str copy-sequence nthcdr 2 setcar] 5)))] 7))

(defun sc-cite-original nil "\
Hook version of sc-cite.

This is callable from the various mail and news readers' reply
function according to the predefined standard. Type
\"\\[sc-describe]\" for more details.  Sc-cite-original does not do
any yanking of the original message but it does require a few things:

     1) The reply buffer is the current buffer.

     2) The original message has been yanked and inserted into the
        reply buffer.

     3) Verbose mail headers from the original message have been
        inserted into the reply buffer directly before the text of the
        original message.

     4) Point is at the beginning of the verbose headers.

     5) Mark is at the  end of the body of text to be cited." (byte-code " !b)   	
\"   !*" [headers start end sc-nuke-mail-headers-p point-marker run-hooks sc-rewrite-header-hook region-beginning region-end sc-mail-yank-clear-headers sc-cite sc-append-current-keymap sc-spoogify-docstring sc-run-hook] 10))

(defun sc-describe nil "\
Describe the Cheapcite 2.1 package.

This package provides a subset of the features provided by the
supercite 2.1 package.  Cheapcite is mainly intended for folks who
want to have more control over citations of original mail/news
messages, but don't like the complexity and/or size of supercite. Some
folks will undoubtably think cheapcite is too complex for its
functionality and they can easily ignore both supercite and cheapcite.

This help string basically outlines the differences between cheapcite
and supercite.  You should be familiar with supercite's concepts
before you read this help string.

Author:

NAME: Barry A. Warsaw            USMAIL: National Institute of
TELE: (301) 975-3460                     Standards and Technology
UUCP: uunet!cme.nist.gov!warsaw          Rm. B-124, Bldg. 220
INET: warsaw@cme.nist.gov                Gaithersburg, MD 20899

Get on the Supercite mailing list:

Send articles to:
          INET: supercite@cme.nist.gov
          UUCP: uunet!cme.nist.gov!supercite

Send administrivia (additions/deletions to list, etc) to:
          INET: supercite-request@cme.nist.gov
          UUCP: uunet!cme.nist.gov!supercite-request

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

Cheapcite understands these supercite variables, which have almost
identical function within the cheapcite package:

     sc-nested-citation-p
     sc-citation-leader
     sc-citation-delimiter
     sc-citation-separator
     sc-cite-regexp
     sc-fill-paragraph-hook
     sc-auto-fill-region-p
     sc-fixup-whitespace-p
     sc-nuke-mail-headers-p
     sc-run-hook
     sc-load-hook
     sc-default-keymap

Cheapcite has no concept of global alists (gal's) and no information
is gleaned from mail headers before they are nuked.  Cheapcite does
not attempt to decipher an attribution string from mail headers,
instead, it queries the user for an attribution string every time it
tries to cite a body of text.  Cheapcite does remember the last
attribution string entered by you and will use that as a default.

Since no information is gleaned from mail headers, cheapcite can't
really rewrite reference headers. Instead, a hook is executed before
the mail headers are nuked:

     Variable: sc-rewrite-header-hook
          Hook which executes a reference header rewrite function on
          the buffer *before* the original mail headers are nuked.

          NOTE: be sure to use 'insert-before-markers' instead of
          'insert' in the function set in this hook.
          Default: 'sc-standard-header.

You can use sc-mail-fetch-field to get coarse information from the
original mail headers.

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

Cheapcite provides these commands with similar functionality to their
supercite equivalents:

     sc-cite
     sc-uncite
     sc-recite
     sc-insert-citation
     sc-open-line
     sc-fill-paragraph-manually
     sc-version

Cheapcite will also leach onto the current local keymap in a manner
similar to supercite, however cheapcite has no notion of a
per-interface keymap.  It will only use sc-default-keymap to set the
desired keybindings.


-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

If this explanation of cheapcite seems terse, you're right.  But then,
that's the purpose of cheapcite.  I've really attempted to pair down
supercite as much as I could, while maintaining the flavor of the
package.

Enjoy, and please send the author your compliments, questions,
suggestions and bug reports.  Don't forget, if you're interested in
discussing supercite and/or cheapcite, join the mailing list by
sending mail to the request line mentioned above." (interactive) (byte-code "!" [nil describe-function sc-describe] 2))

(run-hooks (quote sc-load-hook))
