Mercurial > hg > xemacs-beta
comparison tests/automated/completion-tests.el @ 5634:2014ff433daf
Support hash COLLECTIONs, #'{all,try}-completion{s,}; add #'test-completion
src/ChangeLog addition:
2012-01-01 Aidan Kehoe <kehoea@parhasard.net>
Add #'test-completion, API from GNU.
Accept hash table COLLECTIONs in it and in the other
completion-oriented functions, #'try-completion,
#'all-completions, and those Lisp functions implemented in terms
of them.
* lisp.h: Update the prototype of map_obarray(), making FN
compatible with the FUNCTION argument of elisp_maphash();
* abbrev.c (abbrev_match_mapper):
* abbrev.c (record_symbol):
* doc.c (verify_doc_mapper):
* symbols.c (mapatoms_1):
* symbols.c (apropos_mapper):
Update these mapper functions to reflect the new argument to
map_obarray().
* symbols.c (map_obarray):
Call FN with two arguments, the string name of the symbol, and the
symbol itself, for API (mapper) compatibility with
elisp_maphash().
* minibuf.c (map_completion): New. Map a maphash_function_t across
a non function COLLECTION, as appropriate for #'try-completion and
friends.
* minibuf.c (map_completion_list): New. Map a maphash_function_t
across a pseudo-alist, as appropriate for the completion
functions.
* minibuf.c (ignore_completion_p): PRED needs to be called with
two args if and only if the collection is a hash table. Implement
this.
* minibuf.c (try_completion_mapper): New. The loop body of
#'try-completion, refactored out.
* minibuf.c (Ftry_completion): Use try_completion_mapper(),
map_completion().
* minibuf.c (all_completions_mapper): New. The loop body of
#'all-completions, refactored out.
* minibuf.c (Fall_completions): Use all_completions_mapper(),
map_completion().
* minibuf.c (test_completion_mapper): New. The loop body of
#'test-completion.
* minibuf.c (Ftest_completion): New, API from GNU.
* minibuf.c (syms_of_minibuf): Make Ftest_completion available.
tests/ChangeLog addition:
2012-01-01 Aidan Kehoe <kehoea@parhasard.net>
* automated/completion-tests.el: New.
Test #'try-completion, #'all-completion and #'test-completion with
list, vector and hash-table COLLECTION arguments.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sun, 01 Jan 2012 15:18:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5633:49c36ed998b6 | 5634:2014ff433daf |
---|---|
1 ;; Copyright (C) 2012 Free Software Foundation, Inc. | |
2 | |
3 ;; Author: Aidan Kehoe <kehoea@parhasard.net> | |
4 ;; Maintainers: Aidan Kehoe <kehoea@parhasard.net> | |
5 ;; Created: 2012 | |
6 ;; Keywords: tests | |
7 | |
8 ;; This file is part of XEmacs. | |
9 | |
10 ;; XEmacs is free software: you can redistribute it and/or modify it | |
11 ;; under the terms of the GNU General Public License as published by the | |
12 ;; Free Software Foundation, either version 3 of the License, or (at your | |
13 ;; option) any later version. | |
14 | |
15 ;; XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 ;; for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
21 ;; along with XEmacs. If not, see <http://www.gnu.org/licenses/>. | |
22 | |
23 ;;; Synched up with: Not in FSF. | |
24 | |
25 ;; This file tests pseudo-alist, obarray and hash-table arguments to | |
26 ;; #'try-completion, #'all-completions and #'test-completion. It doesn't | |
27 ;; test function arguments as COLLECTION. | |
28 | |
29 (require 'cl) | |
30 | |
31 (or (featurep 'xemacs) | |
32 (defmacro Assert (assertion &optional failing-case) | |
33 ;; This file can actually execute on GNU, though it exposes some bugs | |
34 ;; as of So 1 Jan 2012 14:41:32 GMT, described in | |
35 ;; http://mid.gmane.org/20224.27302.821804.284656@parhasard.net . | |
36 `(condition-case err | |
37 (assert ,assertion nil | |
38 ,@(if (memq (car-safe assertion) | |
39 '(eq eql equal equalp = string= < <= > >=)) | |
40 (list | |
41 (concat (if failing-case | |
42 (concat failing-case ", ") | |
43 "") | |
44 "%S should be `" | |
45 (symbol-name (car assertion)) | |
46 "' to %S but isn't") | |
47 (cadr assertion) | |
48 (caddr assertion)) | |
49 (list failing-case))) | |
50 (error | |
51 (message "error executing %S, %S, %S" ',assertion ,failing-case | |
52 err))))) | |
53 | |
54 (let* ((strings '("del-alist" "delay-mode-hooks" "delete" "delete*" | |
55 "delete-and-extract-region" "delete-annotation" | |
56 "delete-auto-save-file-if-necessary" "delete-backward-char" | |
57 "delete-blank-lines" "delete-char" | |
58 "delete-completion-window" "delete-console" | |
59 "delete-debug-class-to-check" "delete-device" | |
60 "delete-directory" "delete-duplicates" "delete-dups" | |
61 "delete-extent" "delete-extract-rectangle" "delete-field" | |
62 "delete-file" "delete-forward-p" "delete-frame" | |
63 "delete-horizontal-space" "delete-if" "delete-if-not" | |
64 "delete-indentation" "delete-itimer" "delete-matching-lines" | |
65 "delete-menu-item" "delete-non-matching-lines" | |
66 "delete-other-frames" "delete-other-windows" | |
67 "delete-overlay" "delete-primary-selection" "delete-process" | |
68 "delete-rectangle" "delete-region" "delete-selection-mode" | |
69 "delete-text-in-column" "delete-to-left-margin" | |
70 "delete-window" "delete-windows-on" "delq" "remote-compile" | |
71 "remote-path-file-handler-function" "remove" "remove*" | |
72 "remove-alist" "remove-char-table" "remove-database" | |
73 "remove-directory" "remove-duplicates" | |
74 "remove-face-property" "remove-from-invisibility-spec" | |
75 "remove-glyph-property" "remove-gutter-element" | |
76 "remove-hook" "remove-if" "remove-if-not" | |
77 "remove-local-hook" "remove-message" | |
78 "remove-progress-feedback" "remove-range-table" | |
79 "remove-specifier" | |
80 "remove-specifier-specs-matching-tag-set-cdrs" | |
81 "remove-text-properties" "sublis" | |
82 "submenu-generate-accelerator-spec" "subr-arity" | |
83 "subr-interactive" "subr-max-args" "subr-min-args" | |
84 "subr-name" "subregexp-context-p" "subrp" "subseq" "subsetp" | |
85 "subsidiary-coding-system" "subst" "subst-char-in-region" | |
86 "subst-char-in-string" "subst-if" "subst-if-not" | |
87 "substitute" "substitute-command-keys" "substitute-env-vars" | |
88 "substitute-if" "substitute-if-not" | |
89 "substitute-in-file-name" "substitute-key-definition" | |
90 "substring" "substring-no-properties" "subtract-time" | |
91 "subwindow-height" "subwindow-image-instance-p" | |
92 "subwindow-width" "subwindow-xid" "subwindowp")) | |
93 (list (let ((count -1)) | |
94 (mapcar #'(lambda (string) | |
95 (incf count) | |
96 (case (% count 3) | |
97 (0 string) | |
98 (1 (cons (make-symbol string) nil)) | |
99 (2 (cons string (make-symbol string))))) strings))) | |
100 (vector (loop | |
101 for string in strings | |
102 with vector = (make-vector 511 0) | |
103 with count = -1 | |
104 with symbol = nil | |
105 do | |
106 (setq symbol (intern string vector) | |
107 count (1+ count)) | |
108 (case (% count 3) | |
109 (0 (set symbol nil)) | |
110 (1 (fset symbol (symbol-function 'ignore))) | |
111 (2 (setf (symbol-plist symbol) 'hello))) | |
112 finally return vector)) | |
113 (init-hash-table | |
114 #'(lambda () | |
115 (loop | |
116 for string in strings | |
117 with hash-table = (make-hash-table :test #'equal) | |
118 with count = -1 | |
119 do | |
120 (incf count) | |
121 (case (% count 3) | |
122 (0 (setf (gethash (make-symbol string) hash-table) | |
123 'hello)) | |
124 (1 (setf (gethash string hash-table) 'everyone)) | |
125 (2 (setf (gethash string hash-table) nil))) | |
126 finally return hash-table))) | |
127 (hash-table (funcall init-hash-table)) | |
128 ;; The following three could be circular lists, but that's not | |
129 ;; portable to GNU. | |
130 (list-list (make-list (length strings) list)) | |
131 (vector-list (make-list (length strings) vector)) | |
132 (hash-table-list (make-list (length strings) hash-table)) | |
133 scratch-hash-table cleared) | |
134 (macrolet | |
135 ((Assert-with-collections (assertion failing-case) | |
136 `(progn | |
137 (Assert ,(subst 'list 'collection assertion :test #'eq) | |
138 ,(replace-regexp-in-string "collection" "list" failing-case)) | |
139 (Assert ,(subst 'vector 'collection assertion :test #'eq) | |
140 ,(replace-regexp-in-string "collection" "vector" | |
141 failing-case)) | |
142 (Assert ,(subst 'hash-table 'collection assertion :test #'eq) | |
143 ,(replace-regexp-in-string "collection" "hash-table" | |
144 failing-case))))) | |
145 ;; #'try-completion. | |
146 (Assert (every #'try-completion strings list-list) | |
147 "check #'try-completion gives no false negatives, list") | |
148 (Assert (every #'try-completion strings vector-list) | |
149 "check #'try-completion gives no false negatives, vector") | |
150 (Assert (every #'try-completion strings hash-table-list) | |
151 "check #'try-completion gives no false negatives, hash-table") | |
152 (Assert-with-collections | |
153 (null (try-completion "iX/ZXLwiOU+a " collection)) | |
154 "check #'try-completion with no match, collection") | |
155 (Assert-with-collections | |
156 (eq t (try-completion "delq" collection)) | |
157 "check #'try-completion with an exact match, collection") | |
158 (Assert-with-collections | |
159 (equal "delq" | |
160 (let ((completion-ignore-case t)) | |
161 (try-completion "DElq" collection))) | |
162 "check #'try-completion with a case-insensitive match, collection") | |
163 (Assert-with-collections | |
164 (equal "del" (try-completion "de" collection)) | |
165 "check #'try-completion where it needs to complete, collection") | |
166 (Assert (equal "del" (try-completion "de" list #'consp)) | |
167 "check #'try-completion, list, it needs to complete, predicate") | |
168 (Assert | |
169 (equal "del" (try-completion "de" vector #'fboundp)) | |
170 "check #'try-completion, vector, it needs to complete, predicate") | |
171 (Assert | |
172 (equal "del" (try-completion "de" hash-table #'(lambda (key value) | |
173 (eq 'everyone value)))) | |
174 "check #'try-completion, hash-table, it needs to complete, predicate") | |
175 (Assert | |
176 ;; The actual result here is undefined, the important thing is we don't | |
177 ;; segfault. | |
178 (prog1 | |
179 t | |
180 (try-completion "de" | |
181 (setq cleared nil | |
182 scratch-hash-table (funcall init-hash-table)) | |
183 #'(lambda (key value) | |
184 (if cleared | |
185 (eq 'everyone value) | |
186 (clrhash scratch-hash-table) | |
187 (garbage-collect) | |
188 (setq cleared t))))) | |
189 "check #'try-completion doesn't crash when hash table modified") | |
190 | |
191 ;; #'all-completions | |
192 (Assert (every #'all-completions strings list-list) | |
193 "check #'all-completions gives no false negatives, list") | |
194 (Assert (every #'all-completions strings vector-list) | |
195 "check #'all-completions gives no false negatives, vector") | |
196 (Assert (every #'all-completions strings hash-table-list) | |
197 "check #'all-completions gives no false negatives, hash-table") | |
198 (Assert-with-collections | |
199 (null (all-completions "iX/ZXLwiOU+a " collection)) | |
200 "check #'all-completion with no match, collection") | |
201 (Assert-with-collections | |
202 (equal '("delq") (all-completions "delq" collection)) | |
203 "check #'all-completions with an exact match, collection") | |
204 (Assert-with-collections | |
205 (equal '("delq") (let ((completion-ignore-case t)) | |
206 (all-completions "dElQ" collection))) | |
207 "check #'all-completions with a case-insensitive match, collection") | |
208 (Assert | |
209 (equal | |
210 '("delay-mode-hooks" "delete-and-extract-region" | |
211 "delete-backward-char" "delete-completion-window" "delete-device" | |
212 "delete-dups" "delete-field" "delete-frame" "delete-if-not" | |
213 "delete-matching-lines" "delete-other-frames" | |
214 "delete-primary-selection" "delete-region" "delete-to-left-margin" | |
215 "delq") | |
216 (sort (all-completions "de" vector #'fboundp) #'string-lessp)) | |
217 "check #'all-completions where it need to complete, vector") | |
218 (Assert | |
219 (eql (length (all-completions "de" hash-table #'(lambda (key value) | |
220 (eq 'everyone value)))) | |
221 15) | |
222 "check #'all-completions gives enough results with predicate, hash") | |
223 (Assert | |
224 (equal (sort | |
225 (all-completions | |
226 "de" list #'(lambda (object) (and (consp object) | |
227 (null (cdr object))))) | |
228 #'string-lessp) | |
229 (sort | |
230 (all-completions | |
231 "de" hash-table #'(lambda (key value) | |
232 (eq 'everyone value))) | |
233 #'string-lessp)) | |
234 "check #'all-completion with complex predicates behaves well") | |
235 (Assert-with-collections | |
236 (equal (sort* (all-completions "" collection) #'string-lessp) strings) | |
237 "check #'all-completions, empty string, with collection") | |
238 (Assert | |
239 ;; The actual result here is undefined, the important thing is we don't | |
240 ;; segfault. | |
241 (prog1 | |
242 t | |
243 (all-completions "de" | |
244 (setq cleared nil | |
245 scratch-hash-table (funcall init-hash-table)) | |
246 #'(lambda (key value) | |
247 (if cleared | |
248 (eq 'everyone value) | |
249 (clrhash scratch-hash-table) | |
250 (garbage-collect) | |
251 (setq cleared t))))) | |
252 "check #'all-completions doesn't crash when hash table modified") | |
253 ;; #'test-completion | |
254 (Assert (every #'test-completion strings list-list) | |
255 "check #'test-completion gives no false negatives, list") | |
256 (Assert (every #'test-completion strings vector-list) | |
257 "check #'test-completion gives no false negatives, vector") | |
258 (Assert (every #'test-completion strings hash-table-list) | |
259 "check #'test-completion gives no false negatives, hash-table") | |
260 (Assert-with-collections | |
261 (null (test-completion "iX/ZXLwiOU+a " collection)) | |
262 "check #'test-completion with no match, collection") | |
263 (Assert-with-collections | |
264 (eq t (test-completion "delq" collection)) | |
265 "check #'test-completion with an exact match, collection") | |
266 (Assert-with-collections | |
267 (null (let (completion-ignore-case) (test-completion "DElq" collection))) | |
268 "check #'test-completion fails correctly if case-sensitive, collection") | |
269 (Assert-with-collections | |
270 (eq t (let ((completion-ignore-case t)) | |
271 (test-completion "DElq" collection))) | |
272 "check #'test-completion with a case-insensitive match, collection") | |
273 (Assert-with-collections | |
274 (null (test-completion "de" collection)) | |
275 "check #'test-completion gives nil if no exact match, collection") | |
276 (Assert (null (test-completion "de" list #'consp)) | |
277 "check #'test-completion, list, no exact match, predicate") | |
278 (Assert (eq t (test-completion "delete-matching-lines" list #'consp)) | |
279 "check #'test-completion, list, exact match, predicate") | |
280 (Assert (null (test-completion "de" vector #'fboundp)) | |
281 "check #'test-completion, vector, no exact match, predicate") | |
282 (Assert (eq t (test-completion "delete-to-left-margin" vector #'fboundp)) | |
283 "check #'test-completion, vector, exact match, predicate") | |
284 (Assert | |
285 (null (test-completion "de" hash-table #'(lambda (key value) | |
286 (eq 'everyone value)))) | |
287 "check #'test-completion, hash-table, it needs to complete, predicate") | |
288 (Assert | |
289 (eq t (test-completion "delete-frame" hash-table | |
290 #'(lambda (key value) (eq 'everyone value)))) | |
291 "check #'test-completion, hash-table, exact match, predicate") | |
292 (Assert | |
293 ;; The actual result here is undefined, the important thing is we don't | |
294 ;; segfault. | |
295 (prog1 | |
296 t | |
297 (test-completion "delete-frame" | |
298 (setq cleared nil | |
299 scratch-hash-table (funcall init-hash-table)) | |
300 #'(lambda (key value) | |
301 (if cleared | |
302 (eq 'everyone value) | |
303 (clrhash scratch-hash-table) | |
304 (garbage-collect) | |
305 (setq cleared t))))) | |
306 "check #'all-completions doesn't crash when hash table modified"))) | |
307 |