(defgroup dabbrev nil
"Dynamic Abbreviations."
:tag "Dynamic Abbreviations"
:group 'abbrev
:group 'convenience)
(defcustom dabbrev-backward-only nil
"*If non-nil, `dabbrev-expand' only looks backwards."
:type 'boolean
:group 'dabbrev)
(defcustom dabbrev-limit nil
"*Limits region searched by `dabbrev-expand' to this many chars away."
:type '(choice (const :tag "off" nil)
integer)
:group 'dabbrev)
(defcustom dabbrev-abbrev-skip-leading-regexp nil
"*Regexp for skipping leading characters of an abbreviation.
Example: Set this to \"\\\\$\" for programming languages
in which variable names may appear with or without a leading `$'.
\(For example, in Makefiles.\)
Set this to nil if no characters should be skipped."
:type '(choice regexp
(const :tag "off" nil))
:group 'dabbrev)
(defcustom dabbrev--eliminate-newlines t
"*Non-nil means dabbrev should not insert newlines.
Instead it converts them to spaces."
:type 'boolean
:group 'dabbrev)
(defcustom dabbrev-case-fold-search 'case-fold-search
"*Control whether dabbrev searches should ignore case.
A value of nil means case is significant.
A value of `case-fold-search' means case is significant
if `case-fold-search' is nil.
Any other non-nil version means case is not significant."
:type '(choice (const :tag "off" nil)
(const :tag "like search" case-fold-search)
(other :tag "on" t))
:group 'dabbrev)
(defcustom dabbrev-upcase-means-case-search nil
"*The significance of an uppercase character in an abbreviation.
A nil value means case fold search when searching for possible expansions;
non-nil means case sensitive search.
This variable has an effect only when the value of
`dabbrev-case-fold-search' says to ignore case."
:type 'boolean
:group 'dabbrev)
(defcustom dabbrev-case-distinction 'case-replace
"*Whether dabbrev treats expansions as the same if they differ in case.
A value of nil means treat them as different.
A value of `case-replace' means distinguish them if `case-replace' is nil.
Any other non-nil value means to treat them as the same.
This variable has an effect only when the value of
`dabbrev-case-fold-search' specifies to ignore case."
:type '(choice (const :tag "off" nil)
(const :tag "based on `case-replace'" case-replace)
(other :tag "on" t))
:group 'dabbrev
:version "22.1")
(defcustom dabbrev-case-replace 'case-replace
"*Whether dabbrev applies the abbreviations's case pattern to the expansion.
A value of nil means preserve the expansion's case pattern.
A value of `case-replace' means preserve it if `case-replace' is nil.
Any other non-nil value means modify the expansion
by applying the abbreviation's case pattern to it.
This variable has an effect only when the value of
`dabbrev-case-fold-search' specifies to ignore case."
:type '(choice (const :tag "off" nil)
(const :tag "based on `case-replace'" case-replace)
(other :tag "on" t))
:group 'dabbrev)
(defcustom dabbrev-abbrev-char-regexp nil
"*Regexp to recognize a character in an abbreviation or expansion.
This regexp will be surrounded with \\\\( ... \\\\) when actually used.
Set this variable to \"\\\\sw\" if you want ordinary words or
\"\\\\sw\\\\|\\\\s_\" if you want symbols (including characters whose
syntax is \"symbol\" as well as those whose syntax is \"word\".
The value nil has a special meaning: the abbreviation is from point to
previous word-start, but the search is for symbols.
For instance, if you are programming in Lisp, `yes-or-no-p' is a symbol,
while `yes', `or', `no' and `p' are considered words. If this
variable is nil, then expanding `yes-or-no-' looks for a symbol
starting with or containing `no-'. If you set this variable to
\"\\\\sw\\\\|\\\\s_\", that expansion looks for a symbol starting with
`yes-or-no-'. Finally, if you set this variable to \"\\\\sw\", then
expanding `yes-or-no-' signals an error because `-' is not part of a word;
but expanding `yes-or-no' looks for a word starting with `no'.
The recommended value is \"\\\\sw\\\\|\\\\s_\"."
:type '(choice (const nil)
regexp)
:group 'dabbrev)
(defcustom dabbrev-check-all-buffers t
"*Non-nil means dabbrev package should search *all* buffers.
Dabbrev always searches the current buffer first. Then, if
`dabbrev-check-other-buffers' says so, it searches the buffers
designated by `dabbrev-select-buffers-function'.
Then, if `dabbrev-check-all-buffers' is non-nil, dabbrev searches
all the other buffers, except those named in `dabbrev-ignored-buffer-names',
or matched by `dabbrev-ignored-regexps'."
:type 'boolean
:group 'dabbrev)
(defcustom dabbrev-ignored-buffer-names '("*Messages*" "*Buffer List*")
"*List of buffer names that dabbrev should not check.
See also `dabbrev-ignored-buffer-regexps'."
:type '(repeat (string :tag "Buffer name"))
:group 'dabbrev
:version "20.3")
(defcustom dabbrev-ignored-buffer-regexps nil
"*List of regexps matching names of buffers that dabbrev should not check.
See also `dabbrev-ignored-buffer-names'."
:type '(repeat regexp)
:group 'dabbrev
:version "21.1")
(defcustom dabbrev-check-other-buffers t
"*Should \\[dabbrev-expand] look in other buffers?\
nil: Don't look in other buffers.
t: Also look for expansions in the buffers pointed out by
`dabbrev-select-buffers-function'.
Anything else: When we can't find any more expansions in
the current buffer, then ask the user whether to look in other
buffers too.
The default value is t."
:type '(choice (const :tag "off" nil)
(const :tag "on" t)
(other :tag "ask" other))
:group 'dabbrev)
(defvar dabbrev-select-buffers-function 'dabbrev--select-buffers
"A function that selects buffers that should be searched by dabbrev.
The function should take no arguments and return a list of buffers to
search for expansions. See the source of `dabbrev--select-buffers'
for an example.
A mode setting this variable should make it buffer local.")
(defcustom dabbrev-friend-buffer-function 'dabbrev--same-major-mode-p
"*A function to decide whether dabbrev should search OTHER-BUFFER.
The function should take one argument, OTHER-BUFFER, and return
non-nil if that buffer should be searched. Have a look at
`dabbrev--same-major-mode-p' for an example.
The value of `dabbrev-friend-buffer-function' has an effect only if
the value of `dabbrev-select-buffers-function' uses it. The function
`dabbrev--select-buffers' is one function you can use here.
A mode setting this variable should make it buffer local."
:type 'function
:group 'dabbrev)
(defcustom dabbrev-search-these-buffers-only nil
"If non-nil, a list of buffers which dabbrev should search.
If this variable is non-nil, dabbrev will only look in these buffers.
It will not even look in the current buffer if it is not a member of
this list."
:group 'dabbrev)
(defvar dabbrev--last-obarray nil)
(defvar dabbrev--last-table nil)
(defvar dabbrev--last-abbreviation nil)
(defvar dabbrev--last-abbrev-location nil)
(defvar dabbrev--last-direction 0)
(defvar dabbrev--last-expansion nil)
(defvar dabbrev--last-expansion-location nil)
(defvar dabbrev--friend-buffer-list nil)
(defvar dabbrev--last-buffer nil)
(defvar dabbrev--last-buffer-found nil)
(defvar dabbrev--last-completion-buffer nil)
(defvar dabbrev--last-case-pattern nil)
(defvar dabbrev--check-other-buffers dabbrev-check-other-buffers)
(defvar dabbrev--abbrev-char-regexp nil)
(defsubst dabbrev--minibuffer-origin ()
(car (cdr (buffer-list))))
(defmacro dabbrev-filter-elements (element list condition)
`(let (dabbrev-result dabbrev-tail ,element)
(setq dabbrev-tail ,list)
(while dabbrev-tail
(setq ,element (car dabbrev-tail))
(if ,condition
(setq dabbrev-result (cons ,element dabbrev-result)))
(setq dabbrev-tail (cdr dabbrev-tail)))
(nreverse dabbrev-result)))
(defun dabbrev-completion (&optional arg)
"Completion on current word.
Like \\[dabbrev-expand] but finds all expansions in the current buffer
and presents suggestions for completion.
With a prefix argument, it searches all buffers accepted by the
function pointed out by `dabbrev-friend-buffer-function' to find the
completions.
If the prefix argument is 16 (which comes from C-u C-u),
then it searches *all* buffers."
(interactive "*P")
(dabbrev--reset-global-variables)
(let* ((dabbrev-check-other-buffers (and arg t))
(dabbrev-check-all-buffers
(and arg (= (prefix-numeric-value arg) 16)))
(abbrev (dabbrev--abbrev-at-point))
(ignore-case-p (and (if (eq dabbrev-case-fold-search 'case-fold-search)
case-fold-search
dabbrev-case-fold-search)
(or (not dabbrev-upcase-means-case-search)
(string= abbrev (downcase abbrev)))))
(my-obarray dabbrev--last-obarray)
init)
(save-excursion
(setq dabbrev--last-abbreviation abbrev)
(let ((completion-list
(dabbrev--find-all-expansions abbrev ignore-case-p))
(completion-ignore-case ignore-case-p))
(setq my-obarray (make-vector (length completion-list) 0))
(or (> (length my-obarray) 0)
(error "No dynamic expansion for \"%s\" found%s"
abbrev
(if dabbrev--check-other-buffers "" " in this-buffer")))
(cond
((or (not ignore-case-p)
(not dabbrev-case-replace))
(mapc (function (lambda (string)
(intern string my-obarray)))
completion-list))
((string= abbrev (upcase abbrev))
(mapc (function (lambda (string)
(intern (upcase string) my-obarray)))
completion-list))
((string= (substring abbrev 0 1)
(upcase (substring abbrev 0 1)))
(mapc (function (lambda (string)
(intern (capitalize string) my-obarray)))
completion-list))
(t
(mapc (function (lambda (string)
(intern (downcase string) my-obarray)))
completion-list)))
(setq dabbrev--last-obarray my-obarray)
(setq dabbrev--last-completion-buffer (current-buffer))
(setq init (try-completion abbrev my-obarray))))
(or (stringp init)
(setq init abbrev))
(cond
((and (not (string-equal init ""))
(not (string-equal (downcase init) (downcase abbrev))))
(if (> (length (all-completions init my-obarray)) 1)
(message "Repeat `%s' to see all completions"
(key-description (this-command-keys)))
(message "The only possible completion"))
(dabbrev--substitute-expansion nil abbrev init nil))
(t
(message "Making completion list...")
(with-output-to-temp-buffer "*Completions*"
(display-completion-list (all-completions init my-obarray)
init))
(message "Making completion list...done")))
(and (window-minibuffer-p (selected-window))
(message nil))))
(defun dabbrev-expand (arg)
"Expand previous word \"dynamically\".
Expands to the most recent, preceding word for which this is a prefix.
If no suitable preceding word is found, words following point are
considered. If still no suitable word is found, then look in the
buffers accepted by the function pointed out by variable
`dabbrev-friend-buffer-function'.
A positive prefix argument, N, says to take the Nth backward *distinct*
possibility. A negative argument says search forward.
If the cursor has not moved from the end of the previous expansion and
no argument is given, replace the previously-made expansion
with the next possible expansion not yet tried.
The variable `dabbrev-backward-only' may be used to limit the
direction of search to backward if set non-nil.
See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
(interactive "*P")
(let (abbrev record-case-pattern
expansion old direction (orig-point (point)))
(save-excursion
(if (and (null arg)
(markerp dabbrev--last-abbrev-location)
(marker-position dabbrev--last-abbrev-location)
(or (eq last-command this-command)
(and (window-minibuffer-p (selected-window))
(= dabbrev--last-abbrev-location
(point)))))
(progn
(setq abbrev dabbrev--last-abbreviation)
(setq old dabbrev--last-expansion)
(setq direction dabbrev--last-direction))
(if (and (eq (preceding-char) ?\s)
(markerp dabbrev--last-abbrev-location)
(marker-position dabbrev--last-abbrev-location)
(= (point) (1+ dabbrev--last-abbrev-location)))
(progn
(setq abbrev " ")
(save-excursion
(save-restriction
(widen)
(if dabbrev--last-buffer
(set-buffer dabbrev--last-buffer))
(if (or (eq dabbrev--last-direction 1)
(and (eq dabbrev--last-direction 0)
(< dabbrev--last-expansion-location (point))))
(setq dabbrev--last-expansion-location
(+ dabbrev--last-expansion-location
(length dabbrev--last-expansion))))
(goto-char dabbrev--last-expansion-location)
(re-search-forward
(concat "\\(?:" dabbrev--abbrev-char-regexp "\\)+"))
(setq expansion (buffer-substring-no-properties
dabbrev--last-expansion-location (point)))
(setq dabbrev--last-expansion-location (point))))
(setq dabbrev--last-direction -1))
(dabbrev--reset-global-variables)
(setq direction (if (null arg)
(if dabbrev-backward-only 1 0)
(prefix-numeric-value arg)))
(setq abbrev (dabbrev--abbrev-at-point))
(setq record-case-pattern t)
(setq old nil)))
(or expansion
(setq expansion
(dabbrev--find-expansion abbrev direction
(and (if (eq dabbrev-case-fold-search 'case-fold-search)
case-fold-search
dabbrev-case-fold-search)
(or (not dabbrev-upcase-means-case-search)
(string= abbrev (downcase abbrev))))))))
(cond
((not expansion)
(dabbrev--reset-global-variables)
(if old
(save-excursion
(setq buffer-undo-list (cons orig-point buffer-undo-list))
(search-backward old)
(insert abbrev)
(delete-region (point) (+ (point) (length old)))))
(error "No%s dynamic expansion for `%s' found"
(if old " further" "") abbrev))
(t
(if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found)
(minibuffer-window-active-p (selected-window))))
(progn
(message "Expansion found in '%s'"
(buffer-name dabbrev--last-buffer))
(setq dabbrev--last-buffer-found dabbrev--last-buffer))
(message nil))
(if (and (or (eq (current-buffer) dabbrev--last-buffer)
(null dabbrev--last-buffer))
(numberp dabbrev--last-expansion-location)
(and (> dabbrev--last-expansion-location (point))))
(setq dabbrev--last-expansion-location
(copy-marker dabbrev--last-expansion-location)))
(setq buffer-undo-list (cons orig-point buffer-undo-list))
(dabbrev--substitute-expansion old abbrev expansion
record-case-pattern)
(setq dabbrev--last-expansion expansion)
(setq dabbrev--last-abbreviation abbrev)
(setq dabbrev--last-abbrev-location (point-marker))))))
(defun dabbrev--same-major-mode-p (other-buffer)
(eq major-mode
(save-excursion
(set-buffer other-buffer)
major-mode)))
(defun dabbrev--goto-start-of-abbrev ()
(save-match-data
(when (> (point) (minibuffer-prompt-end))
(forward-char -1)
(while (and (looking-at dabbrev--abbrev-char-regexp)
(> (point) (minibuffer-prompt-end))
(not (= (point) (field-beginning (point) nil
(1- (point))))))
(forward-char -1))
(or (looking-at dabbrev--abbrev-char-regexp)
(forward-char 1)))
(and dabbrev-abbrev-skip-leading-regexp
(while (looking-at dabbrev-abbrev-skip-leading-regexp)
(forward-char 1)))))
(defun dabbrev--abbrev-at-point ()
(if (bobp)
(error "No possible abbreviation preceding point"))
(save-excursion
(setq dabbrev--last-abbrev-location (point))
(save-match-data
(if (save-excursion
(forward-char -1)
(not (looking-at (concat "\\("
(or dabbrev-abbrev-char-regexp
"\\sw\\|\\s_")
"\\)+"))))
(if (re-search-backward (or dabbrev-abbrev-char-regexp
"\\sw\\|\\s_")
nil t)
(forward-char 1)
(error "No possible abbreviation preceding point"))))
(dabbrev--goto-start-of-abbrev)
(buffer-substring-no-properties
dabbrev--last-abbrev-location (point))))
(defun dabbrev--reset-global-variables ()
(setq dabbrev--last-table nil
dabbrev--last-abbreviation nil
dabbrev--last-abbrev-location nil
dabbrev--last-direction nil
dabbrev--last-expansion nil
dabbrev--last-expansion-location nil
dabbrev--friend-buffer-list nil
dabbrev--last-buffer nil
dabbrev--last-buffer-found nil
dabbrev--abbrev-char-regexp (or dabbrev-abbrev-char-regexp
"\\sw\\|\\s_")
dabbrev--check-other-buffers dabbrev-check-other-buffers))
(defun dabbrev--select-buffers ()
"Return a list of other buffers to search for a possible abbrev.
The current buffer is not included in the list.
This function makes a list of all the buffers returned by `buffer-list',
then discards buffers whose names match `dabbrev-ignored-buffer-names'
or `dabbrev-ignored-buffer-regexps'. It also discards buffers for which
`dabbrev-friend-buffer-function', if it is bound, returns nil when called
with the buffer as argument.
It returns the list of the buffers that are not discarded."
(dabbrev-filter-elements
buffer (buffer-list)
(and (not (eq (current-buffer) buffer))
(not (dabbrev--ignore-buffer-p buffer))
(boundp 'dabbrev-friend-buffer-function)
(funcall dabbrev-friend-buffer-function buffer))))
(defun dabbrev--try-find (abbrev reverse n ignore-case)
"Search for ABBREV, backwards if REVERSE, N times.
If IGNORE-CASE is non-nil, ignore case while searching.
Return the expansion found, and save the location of the start
of the expansion in `dabbrev--last-expansion-location'."
(save-excursion
(save-restriction
(widen)
(let ((expansion nil))
(and dabbrev--last-expansion-location
(goto-char dabbrev--last-expansion-location))
(let ((case-fold-search ignore-case)
(count n))
(while (and (> count 0)
(setq expansion (dabbrev--search abbrev
reverse
(and ignore-case
(if (eq dabbrev-case-distinction 'case-replace)
case-replace
dabbrev-case-distinction))
)))
(setq count (1- count))))
(and expansion
(setq dabbrev--last-expansion-location (point)))
expansion))))
(defun dabbrev--find-all-expansions (abbrev ignore-case)
"Return a list of all possible expansions of ABBREV.
If IGNORE-CASE is non-nil, accept matches which differ in case."
(let ((all-expansions nil)
expansion)
(save-excursion
(goto-char (point-min))
(while (setq expansion (dabbrev--find-expansion abbrev -1 ignore-case))
(setq all-expansions (cons expansion all-expansions))))
all-expansions))
(defun dabbrev--scanning-message ()
(unless (window-minibuffer-p (selected-window))
(message "Scanning `%s'" (buffer-name (current-buffer)))))
(defun dabbrev--ignore-buffer-p (buffer)
"Return non-nil if BUFFER should be ignored by dabbrev."
(let ((bn (buffer-name buffer)))
(or (member bn dabbrev-ignored-buffer-names)
(let ((tail dabbrev-ignored-buffer-regexps)
(match nil))
(while (and tail (not match))
(setq match (string-match (car tail) bn)
tail (cdr tail)))
match))))
(defun dabbrev--find-expansion (abbrev direction ignore-case)
"Find one occurrence of ABBREV, and return the expansion.
DIRECTION > 0 means look that many times backwards.
DIRECTION < 0 means look that many times forward.
DIRECTION = 0 means try both backward and forward.
IGNORE-CASE non-nil means ignore case when searching.
This sets `dabbrev--last-direction' to 1 or -1 according
to the direction in which the occurrence was actually found.
It sets `dabbrev--last-expansion-location' to the location
of the start of the occurrence."
(save-excursion
(when dabbrev--last-buffer
(set-buffer dabbrev--last-buffer)
(dabbrev--scanning-message))
(or
(and (not dabbrev-search-these-buffers-only)
(>= direction 0)
(setq dabbrev--last-direction (min 1 direction))
(dabbrev--try-find abbrev t
(max 1 direction)
ignore-case))
(and (or (not dabbrev-search-these-buffers-only)
dabbrev--last-buffer)
(<= direction 0)
(setq dabbrev--last-direction -1)
(dabbrev--try-find abbrev nil
(max 1 (- direction))
ignore-case))
(progn
(setq dabbrev--last-direction -1)
(unless dabbrev--last-buffer
(or dabbrev--friend-buffer-list
(setq dabbrev--friend-buffer-list
(dabbrev--make-friend-buffer-list))))
(let (expansion)
(while (and (not expansion) dabbrev--friend-buffer-list)
(setq dabbrev--last-buffer (pop dabbrev--friend-buffer-list))
(set-buffer dabbrev--last-buffer)
(dabbrev--scanning-message)
(setq dabbrev--last-expansion-location (point-min))
(setq expansion (dabbrev--try-find abbrev nil 1 ignore-case)))
expansion)))))
(defun dabbrev--make-friend-buffer-list ()
(let ((list (mapcar (function get-buffer)
dabbrev-search-these-buffers-only)))
(when (and (null dabbrev-search-these-buffers-only)
dabbrev--check-other-buffers
(or (eq dabbrev--check-other-buffers t)
(setq dabbrev--check-other-buffers
(y-or-n-p "Scan other buffers also? "))))
(setq list (funcall dabbrev-select-buffers-function))
(if dabbrev-check-all-buffers
(setq list
(append list
(dabbrev-filter-elements
buffer (buffer-list)
(and (not (memq buffer list))
(not (dabbrev--ignore-buffer-p buffer)))))))
(setq list (delq (current-buffer) list)))
(if list
(walk-windows (lambda (w)
(unless (eq w (selected-window))
(if (memq (window-buffer w) list)
(setq list
(cons (window-buffer w)
(delq (window-buffer w)
list))))))))
(if (and (window-minibuffer-p (selected-window))
(not dabbrev-search-these-buffers-only))
(setq list
(cons (dabbrev--minibuffer-origin)
(delq (dabbrev--minibuffer-origin) list))))
list))
(defun dabbrev--safe-replace-match (string &optional fixedcase literal)
(if (eq major-mode 'picture-mode)
(with-no-warnings
(picture-replace-match string fixedcase literal))
(replace-match string fixedcase literal)))
(defun dabbrev--substitute-expansion (old abbrev expansion record-case-pattern)
"Replace OLD with EXPANSION in the buffer.
OLD is text currently in the buffer, perhaps the abbreviation
or perhaps another expansion that was tried previously.
ABBREV is the abbreviation we are expanding.
It is \" \" if we are copying subsequent words.
EXPANSION is the expansion substring to be used this time.
RECORD-CASE-PATTERN, if non-nil, means set `dabbrev--last-case-pattern'
to record whether we upcased the expansion, downcased it, or did neither."
(let ((use-case-replace (and (if (eq dabbrev-case-fold-search 'case-fold-search)
case-fold-search
dabbrev-case-fold-search)
(or (not dabbrev-upcase-means-case-search)
(string= abbrev (downcase abbrev)))
(if (eq dabbrev-case-replace 'case-replace)
case-replace
dabbrev-case-replace))))
(when (equal abbrev " ")
(if dabbrev--last-case-pattern
(setq expansion
(funcall dabbrev--last-case-pattern expansion)))
(setq use-case-replace nil))
(let ((expansion-rest (substring expansion 1))
(first-letter-position (string-match "[[:alpha:]]" abbrev)))
(if (or (null first-letter-position)
(and (not (and (or (string= expansion-rest (downcase expansion-rest))
(string= expansion-rest (upcase expansion-rest)))
(or (string= abbrev (downcase abbrev))
(and (string= abbrev (upcase abbrev))
(> (- (length abbrev) first-letter-position)
1)))))
(string= abbrev
(substring expansion 0 (length abbrev)))))
(setq use-case-replace nil)))
(if (and (string= expansion (downcase expansion))
(string= abbrev (downcase abbrev)))
(setq use-case-replace nil))
(if use-case-replace
(setq expansion (downcase expansion)))
(and record-case-pattern
(setq dabbrev--last-case-pattern
(and use-case-replace
(cond ((equal abbrev (upcase abbrev)) 'upcase)
((equal abbrev (downcase abbrev)) 'downcase)))))
(if dabbrev--eliminate-newlines
(let ((pos (length abbrev)))
(while (string-match "[\n \t]+" expansion pos)
(setq pos (1+ (match-beginning 0)))
(setq expansion (replace-match " " nil nil expansion)))))
(if old
(save-excursion
(search-backward old))
(search-backward abbrev)
(search-forward abbrev))
(dabbrev--safe-replace-match expansion
(not use-case-replace)
t)))
(defun dabbrev--search (abbrev reverse ignore-case)
"Search for something that could be used to expand ABBREV.
Second arg, REVERSE, is t for reverse search, nil for forward.
The variable `dabbrev-limit' controls the maximum search region size.
Third argument IGNORE-CASE non-nil means treat case as insignificant while
looking for a match and when comparing with previous matches. Also if
that's non-nil and the match is found at the beginning of a sentence
and is in lower case except for the initial then it is converted to
all lower case for return.
Table of expansions already seen is examined in buffer
`dabbrev--last-table' so that only distinct possibilities are found
by dabbrev-re-expand.
Returns the expansion found, or nil if not found.
Leaves point at the location of the start of the expansion."
(save-match-data
(let ((pattern1 (concat (regexp-quote abbrev)
"\\(" dabbrev--abbrev-char-regexp "\\)"))
(pattern2 (concat (regexp-quote abbrev)
"\\(\\(" dabbrev--abbrev-char-regexp "\\)+\\)"))
(inhibit-point-motion-hooks t)
found-string result)
(save-restriction
(and dabbrev-limit
(narrow-to-region dabbrev--last-expansion-location
(+ (point)
(if reverse (- dabbrev-limit) dabbrev-limit))))
(while (and (not found-string)
(if reverse
(re-search-backward pattern1 nil t)
(re-search-forward pattern1 nil t)))
(goto-char (match-beginning 0))
(dabbrev--goto-start-of-abbrev)
(if (not (looking-at pattern1))
nil
(re-search-forward pattern2)
(setq found-string (match-string-no-properties 0))
(setq result found-string)
(and ignore-case (setq found-string (downcase found-string)))
(if (dabbrev-filter-elements
table-string dabbrev--last-table
(string= found-string table-string))
(setq found-string nil)))
(goto-char (if reverse (match-beginning 0) (match-end 0))))
(when found-string
(setq dabbrev--last-table
(cons found-string dabbrev--last-table))
result)))))
(dolist (mess '("^No dynamic expansion for .* found$"
"^No further dynamic expansion for .* found$"
"^No possible abbreviation preceding point$"))
(add-to-list 'debug-ignored-errors mess))
(provide 'dabbrev)