test-ido-completing-read+.el 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. ;;; -*- lexical-binding: t -*-
  2. (require 'ido)
  3. (require 'ido-completing-read+)
  4. (require 'buttercup)
  5. (require 'cl-lib)
  6. (require 'with-simulated-input)
  7. (defun collection-as-function (collection)
  8. "Return a function equivalent to COLLECTION.
  9. The returned function will work equivalently to COLLECTION when
  10. passed to `all-completions' and `try-completion'."
  11. (completion-table-dynamic (lambda (string) (all-completions string collection))))
  12. (defun shadow-var (var &optional temp-value)
  13. "Shadow the value of VAR.
  14. This will push the current value of VAR to VAR's
  15. `shadowed-values' property, and then set it to TEMP-VALUE. To
  16. reverse this process, call `unshadow-var' on VAR. Vars can
  17. be shadowed recursively, and must be unshadowed once for each
  18. shadowing in order to restore the original value. You can think
  19. of shadowing as dynamic binding with `let', but with manual
  20. control over when bindings start and end.
  21. If VAR is a Custom variable (see `custom-variable-p'), it will be
  22. set using `customize-set-variable', and if TEMP-VALUE is nil it
  23. will be replaces with VAR's standard value.
  24. Other variables will be set with `set-default', and a TEMP-VALUE
  25. of nil will not be treated specially.
  26. `shadow-var' only works on variables declared as special (i.e.
  27. using `defvar' or similar). It will not work on lexically bound
  28. variables."
  29. (unless (special-variable-p var)
  30. (error "Cannot shadow lexical var `%s'" var))
  31. (let* ((use-custom (custom-variable-p var))
  32. (setter (if use-custom 'customize-set-variable 'set-default))
  33. (temp-value (or temp-value
  34. (and use-custom
  35. (eval (car (get var 'standard-value)))))))
  36. ;; Push the current value on the stack
  37. (push (symbol-value var) (get var 'shadowed-values))
  38. (funcall setter var temp-value)))
  39. (defun var-shadowed-p (var)
  40. "Return non-nil if VAR is shadowed by `shadow-var'."
  41. ;; We don't actually want to return that list if it's non-nil.
  42. (and (get var 'shadowed-values) t))
  43. (defun unshadow-var (var)
  44. "Reverse the last call to `shadow-var' on VAR."
  45. (if (var-shadowed-p var)
  46. (let* ((use-custom (custom-variable-p var))
  47. (setter (if use-custom 'customize-set-variable 'set-default))
  48. (value (pop (get var 'shadowed-values))))
  49. (funcall setter var value))
  50. (error "Var is not shadowed: %s" var)))
  51. (defun fully-unshadow-var (var)
  52. "Reverse *all* calls to `shadow-var' on VAR."
  53. (when (var-shadowed-p var)
  54. (let* ((use-custom (custom-variable-p var))
  55. (setter (if use-custom 'customize-set-variable 'set-default))
  56. (value (car (last (get var 'shadowed-values)))))
  57. (put var 'shadowed-values nil)
  58. (funcall setter var value))))
  59. (defun fully-unshadow-all-vars (&optional vars)
  60. "Reverse *all* calls to `shadow-var' on VARS.
  61. If VARS is nil, unshadow *all* variables."
  62. (if vars
  63. (mapc #'fully-unshadow-var vars)
  64. (mapatoms #'fully-unshadow-var))
  65. nil)
  66. (defmacro shadow-vars (varlist)
  67. "Shadow a list of vars with new values.
  68. VARLIST describes the variables to be shadowed with the same
  69. syntax as `let'.
  70. See `shadow-var'."
  71. (declare (indent 0))
  72. (cl-loop
  73. with var = nil
  74. with value = nil
  75. for binding in varlist
  76. if (symbolp binding)
  77. do (setq var binding
  78. value nil)
  79. else
  80. do (setq var (car binding)
  81. value (cadr binding))
  82. collect `(shadow-var ',var ,value) into exprs
  83. finally return `(progn ,@exprs)))
  84. (defmacro unshadow-vars (vars)
  85. "Un-shadow a list of VARS.
  86. This is a macro for consistency with `shadow-vars', but it will
  87. also accept a quoted list for the sake of convenience."
  88. (declare (indent 0))
  89. (when (eq (car vars) 'quote)
  90. (setq vars (eval vars)))
  91. `(mapc #'unshadow-var ',vars))
  92. (cl-defmacro expect-error (expr &key (error-symbol 'error))
  93. "Shortcut for `(expect (lambda () ...) :to-throw)'"
  94. `(expect (lambda () ,expr) :to-throw ',error-symbol))
  95. (describe "Within the `ido-completing-read+' package"
  96. ;; Reset all of these variables to their standard values before each
  97. ;; test, saving the previous values for later restoration.
  98. (before-each
  99. (shadow-vars
  100. ((ido-mode t)
  101. (ido-ubiquitous-mode t)
  102. ido-cr+-debug-mode
  103. ido-cr+-auto-update-blacklist
  104. ido-cr+-fallback-function
  105. ido-cr+-max-items
  106. ido-cr+-function-blacklist
  107. ido-cr+-function-whitelist
  108. ido-cr+-nil-def-alternate-behavior-list
  109. ido-cr+-replace-completely
  110. ido-confirm-unique-completion
  111. ido-enable-flex-matching)))
  112. ;; Restore the saved values after each test
  113. (after-each
  114. (fully-unshadow-all-vars))
  115. (describe "the `ido-completing-read+' function"
  116. (it "should complete with a matching item on RET"
  117. (expect
  118. (with-simulated-input "g RET"
  119. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  120. :to-equal "green"))
  121. (it "should complete with the first match when multiple matches are available"
  122. (expect
  123. (with-simulated-input "b RET"
  124. (ido-completing-read+ "Prompt: " '("brown" "blue" "yellow" "green")))
  125. :to-equal "brown"))
  126. (it "should allow <left> and <right> to cycle completions, with wrap-around"
  127. (expect
  128. (with-simulated-input "b <right> <right> <right> <right> <left> RET"
  129. (ido-completing-read+ "Prompt: " '("brown" "blue" "yellow" "green")))
  130. :to-equal
  131. "blue"))
  132. (it "should return \"\" when RET or C-j is pressed on an empty input even when REQUIRE-MATCH is non-nil"
  133. ;; No REQUIRE-MATCH
  134. (expect
  135. (with-simulated-input "RET"
  136. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  137. :to-equal "blue")
  138. (expect
  139. (with-simulated-input "C-j"
  140. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  141. :to-equal "")
  142. ;; Again, with REQUIRE-MATCH
  143. (expect
  144. (with-simulated-input "RET"
  145. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t))
  146. :to-equal "")
  147. (expect
  148. (with-simulated-input "C-j"
  149. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t))
  150. :to-equal ""))
  151. ;; Verify that DEF works, whether or not it is an element of
  152. ;; COLLECTION
  153. (it "should accept all the same forms of DEF as `completing-read-default'"
  154. (expect
  155. (with-simulated-input "RET"
  156. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil nil nil "green"))
  157. :to-equal "green")
  158. (expect
  159. (with-simulated-input "RET"
  160. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t nil nil "green"))
  161. :to-equal "green")
  162. (expect
  163. (with-simulated-input "RET"
  164. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil nil nil nil "brown"))
  165. :to-equal "brown")
  166. (expect
  167. (with-simulated-input "RET"
  168. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil "brown"))
  169. :to-equal "brown")
  170. (expect
  171. (with-simulated-input "RET"
  172. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil '("brown" "green")))
  173. :to-equal "brown"))
  174. ;; Verify that INITIAL-INPUT works
  175. (it "should work with INITIAL-INPUT"
  176. (expect
  177. (with-simulated-input "RET"
  178. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr"))
  179. :to-equal "green"))
  180. ;; Verify that INITIAL-INPUT and DEF don't interfere with each other
  181. (it "should properly handle both INITIAL-INPUT and DEF at the same time"
  182. (expect
  183. (with-simulated-input "RET"
  184. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr" nil "blue"))
  185. :to-equal "green")
  186. (expect
  187. (with-simulated-input "DEL DEL RET"
  188. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr" nil "blue"))
  189. :to-equal "blue"))
  190. ;; Verify that ido-cr+ works on function collections
  191. (it "should work when COLLECTION is a function"
  192. (expect
  193. (with-simulated-input "g RET"
  194. (ido-completing-read+ "Prompt: " (collection-as-function '("blue" "yellow" "green"))))
  195. :to-equal "green"))
  196. (describe "when `ido-cr+-max-items' is set"
  197. (it "should not trigger a fallback for small collections"
  198. (expect
  199. (with-simulated-input "g RET"
  200. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  201. :to-equal "green"))
  202. (it "should trigger a fallback for large collections"
  203. (expect
  204. ;; With max-items negative, all collections are considered "too
  205. ;; large"
  206. (let ((ido-cr+-max-items -1))
  207. (with-simulated-input "g RET"
  208. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green"))))
  209. :to-equal "g")))
  210. (describe "when REQUIRE-MATCH is non-nil"
  211. (it "should still allow exiting with an empty string if DEF is nil"
  212. (expect
  213. (with-simulated-input "C-j"
  214. (ido-completing-read+
  215. "Prompt: "
  216. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  217. :to-equal ""))
  218. ;; "C-j" should NOT be allowed to return an empty string if
  219. ;; require-match and default are both non-nil.
  220. (it "should not alow exiting with an empty string if DEF is non-nil"
  221. (expect-error
  222. (with-simulated-input "C-j"
  223. (ido-completing-read+
  224. "Prompt: "
  225. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t nil nil "yellow"))))
  226. (it "shouldn't allow C-j to select an ambiguous match"
  227. (expect-error
  228. (with-simulated-input "b C-j C-j C-j"
  229. (ido-completing-read+
  230. "Prompt: "
  231. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t)))
  232. ;; First press of C-j should complete to "blue" after the
  233. ;; first b, but then get stuck on the choice for the second b.
  234. (expect-error
  235. (with-simulated-input "b C-j b C-j C-j C-j"
  236. (ido-completing-read+
  237. "Prompt: "
  238. '("bluebird" "blues" "bluegrass" "blueberry" "yellow" "green") nil t))))
  239. (it "should allow exiting with an unambiguous match"
  240. (expect
  241. (with-simulated-input "b C-j b C-j e C-j C-j"
  242. (ido-completing-read+
  243. "Prompt: "
  244. '("bluebird" "blues" "bluegrass" "blueberry" "yellow" "green") nil t))
  245. :to-equal "blueberry")
  246. ;; The "C-j" should complete to "bluegrass" and return, because
  247. ;; `ido-confirm-unique-completion is nil.
  248. (expect
  249. (with-simulated-input "b l u e g C-j"
  250. (ido-completing-read+
  251. "Prompt: "
  252. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  253. :to-equal "bluegrass"))
  254. (it "should require an extra C-j to exit when `ido-confirm-unique-completion' is non-nil"
  255. (setq ido-confirm-unique-completion t)
  256. ;; Now the first "C-j" should complete to "bluegrass" but should
  257. ;; not return.
  258. (expect-error
  259. (with-simulated-input "b l u e g C-j"
  260. (ido-completing-read+
  261. "Prompt: "
  262. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t)))
  263. ;; The first "C-j" should complete to "bluegrass", and the second
  264. ;; should return.
  265. (expect
  266. (with-simulated-input "b l u e g C-j C-j"
  267. (ido-completing-read+
  268. "Prompt: "
  269. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  270. :to-equal "bluegrass"))
  271. ;; Finally, a test for the expected wrong behavior without
  272. ;; ido-cr+. If ido.el ever fixes this bug, it will cause this test
  273. ;; to fail as a signal that the workaround can be phased out.
  274. (it "should return a non-match when ordinary `ido-completing-read' is used"
  275. (expect
  276. (with-simulated-input "b C-j"
  277. (ido-completing-read
  278. "Prompt: "
  279. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  280. :to-equal "b")))
  281. (describe "with manual fallback shortcuts"
  282. (it "should not fall back when C-b or C-f is used in the middle of the input"
  283. (expect
  284. ;; C-b/f not at beginning/end of input should not fall back
  285. (with-simulated-input "g C-b C-f RET"
  286. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  287. :to-equal "green"))
  288. (it "should fall back on C-f at end of input"
  289. (expect
  290. ;; C-f at end of input should fall back
  291. (with-simulated-input "g C-f RET"
  292. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  293. :to-equal "g"))
  294. (it "should not fall back from repeated C-b that hits the start of input"
  295. (expect
  296. ;; Repeated C-b should not fall back
  297. (with-simulated-input "g C-b C-b C-b C-b RET"
  298. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  299. :to-equal "green"))
  300. (it "should fall back on C-b at beginning of input (if previous action was not C-b)"
  301. (expect
  302. ;; C-b at beginning of line should fall back (if previous action
  303. ;; was not also C-b)
  304. (with-simulated-input "g C-b x DEL C-b RET"
  305. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  306. :to-equal "g")))
  307. (describe "with a work workaround for an bug with `ido-enable-dot-prefix'"
  308. ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26997
  309. ;; for more information on this bug.
  310. (before-each
  311. (setq ido-enable-dot-prefix t))
  312. (it "should not throw an error when `ido-enable-dot-prefix' is non-nil and \"\" is in the collection"
  313. (expect
  314. (with-simulated-input "RET"
  315. (ido-completing-read+ "Pick: " '("" "aaa" "aab" "aac")))
  316. :to-equal "")
  317. (expect
  318. (with-simulated-input "a a b RET"
  319. (ido-completing-read+ "Pick: " '("" "aaa" "aab" "aac")))
  320. :to-equal "aab")))
  321. (describe "with dynamic collections"
  322. (before-all
  323. (setq my-dynamic-collection
  324. (completion-table-dynamic
  325. (lambda (text)
  326. (cond
  327. ;; Sub-completions for "hello"
  328. ((s-prefix-p "hello" text)
  329. '("hello" "hello-world" "hello-everyone" "hello-universe"))
  330. ;; Sub-completions for "goodbye"
  331. ((s-prefix-p "goodbye" text)
  332. '("goodbye" "goodbye-world" "goodbye-everyone" "goodbye-universe"))
  333. ;; General completions
  334. (t
  335. '("hello" "goodbye" "helicopter" "helium" "goodness" "goodwill")))))))
  336. (after-all
  337. (setq my-dynamic-collection nil))
  338. (before-each
  339. (setq ido-enable-flex-matching t
  340. ido-confirm-unique-completion nil)
  341. (spy-on 'ido-cr+-update-dynamic-collection
  342. :and-call-through))
  343. (it "should allow selection of dynamically-added completions"
  344. (expect
  345. (with-simulated-input "hello- RET"
  346. (ido-completing-read+ "Say something: " my-dynamic-collection))
  347. :to-equal "hello-world")
  348. (expect 'ido-cr+-update-dynamic-collection
  349. :to-have-been-called))
  350. (it "should allow ido flex-matching of dynamically-added completions"
  351. (expect
  352. (with-simulated-input "hello-ld RET"
  353. (ido-completing-read+ "Say something: " my-dynamic-collection))
  354. :to-equal
  355. "hello-world")
  356. (expect 'ido-cr+-update-dynamic-collection
  357. :to-have-been-called))
  358. (it "should do a dynamic update when pressing TAB"
  359. (expect
  360. (with-simulated-input "h TAB -ld RET"
  361. (ido-completing-read+ "Say something: " my-dynamic-collection))
  362. :to-equal
  363. "hello-world")
  364. (expect 'ido-cr+-update-dynamic-collection
  365. :to-have-been-called))
  366. (it "should do a dynamic update when idle"
  367. (expect
  368. (with-simulated-input
  369. '("h"
  370. (wsi-simulate-idle-time (1+ ido-cr+-dynamic-update-idle-time))
  371. "-ld RET")
  372. (ido-completing-read+ "Say something: " my-dynamic-collection))
  373. :to-equal
  374. "hello-world")
  375. (expect 'ido-cr+-update-dynamic-collection
  376. :to-have-been-called))
  377. (it "should do a dynamic update when there is only one match remaining"
  378. (expect
  379. (with-simulated-input "hell-ld RET"
  380. (ido-completing-read+ "Say something: " my-dynamic-collection))
  381. :to-equal
  382. "hello-world")
  383. (expect 'ido-cr+-update-dynamic-collection
  384. :to-have-been-called))
  385. (it "should not exit with a unique match if new matches are dynamically added"
  386. (expect
  387. (with-simulated-input '("hell TAB -ld RET")
  388. (ido-completing-read+ "Say something: " my-dynamic-collection))
  389. :to-equal
  390. "hello-world")
  391. (expect 'ido-cr+-update-dynamic-collection
  392. :to-have-been-called))
  393. (it "should exit with a match that is still unique after dynamic updating"
  394. (expect
  395. (with-simulated-input '("helic TAB")
  396. (ido-completing-read+ "Say something: " my-dynamic-collection))
  397. :to-equal
  398. "helicopter")
  399. (expect 'ido-cr+-update-dynamic-collection
  400. :to-have-been-called)))
  401. (describe "with unusual inputs"
  402. (it "should accept a COLLECTION of symbols"
  403. (expect
  404. (with-simulated-input "g RET"
  405. (ido-completing-read+ "Prompt: " '(blue yellow green)))
  406. :to-equal "green"))
  407. (it "should accept a mix of strings and symbols in COLLECTION"
  408. (expect
  409. (with-simulated-input "g RET"
  410. (ido-completing-read+ "Prompt: " '(blue "yellow" green)))
  411. :to-equal "green"))
  412. (it "should accept symbols in DEF"
  413. (expect
  414. (with-simulated-input "RET"
  415. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil '(brown "green")))
  416. :to-equal "brown"))
  417. (it "should accept an alist COLLECTION"
  418. (expect
  419. (with-simulated-input "RET"
  420. (ido-completing-read+
  421. "Prompt: "
  422. '(("blue" . blue-value)
  423. ("yellow" . yellow-value)
  424. (green . green-value))
  425. nil nil nil nil "green"))
  426. :to-equal "green"))
  427. (it "should accept a hash table COLLECTION"
  428. (expect
  429. (with-simulated-input "RET"
  430. (let ((collection (make-hash-table)))
  431. (puthash "blue" 'blue-value collection)
  432. (puthash "yellow" 'yellow-value collection)
  433. (puthash 'green 'green-value collection)
  434. (ido-completing-read+ "Prompt: " collection nil nil nil nil "green")))
  435. :to-equal "green"))
  436. (it "should accept an obarray COLLECTION"
  437. (expect
  438. (with-simulated-input "forward-char RET"
  439. (ido-completing-read+ "Prompt: " obarray #'commandp
  440. t nil nil "backward-char"))
  441. :to-equal "forward-char"))))
  442. (describe "ido-ubiquitous-mode"
  443. ;; Set up a test command that calls `completing-read'
  444. (before-all
  445. (setf (symbol-function 'test-command)
  446. (lambda ()
  447. (interactive)
  448. (completing-read "Prompt: " '("blue" "yellow" "green")))))
  449. ;; Delete the test command
  450. (after-all
  451. (setf (symbol-function 'test-command) nil))
  452. ;; Verify that the mode can be activated
  453. (it "should enable itself properly"
  454. (expect
  455. (progn
  456. (ido-ubiquitous-mode 1)
  457. (with-simulated-input "g RET"
  458. (command-execute 'test-command)))
  459. :to-equal "green"))
  460. (it "should disable itself properly"
  461. (expect
  462. (progn
  463. (ido-ubiquitous-mode 0)
  464. (with-simulated-input "g RET"
  465. (command-execute 'test-command)))
  466. :to-equal "g"))
  467. (describe "with `ido-cr+-function-blacklist'"
  468. (before-all
  469. (setf (symbol-function 'blacklisted-command)
  470. (lambda (arg)
  471. (interactive (list (completing-read "Prompt: " '("blue" "yellow" "green"))))
  472. arg)
  473. (symbol-function 'blacklisted-function)
  474. (lambda ()
  475. (completing-read "Prompt: " '("blue" "yellow" "green")))
  476. (symbol-function 'cmd-that-calls-blacklisted-function)
  477. (lambda ()
  478. (interactive)
  479. (funcall 'blacklisted-function))
  480. (symbol-function 'blacklisted-collection)
  481. (collection-as-function '("blue" "yellow" "green"))))
  482. (after-all
  483. (setf (symbol-function 'blacklisted-command) nil
  484. (symbol-function 'blacklisted-function) nil
  485. (symbol-function 'cmd-that-calls-blacklisted-function) nil
  486. (symbol-function 'blacklisted-collection) nil))
  487. ;; First verify that they work normally before blacklisting them
  488. (describe "when the blacklist is empty"
  489. (it "should not affect a non-blacklisted command"
  490. (expect
  491. (with-simulated-input "g RET"
  492. (call-interactively 'blacklisted-command))
  493. :to-equal "green"))
  494. (it "should not affect a non-blacklisted function"
  495. (expect
  496. (with-simulated-input "g RET"
  497. (call-interactively 'cmd-that-calls-blacklisted-function))
  498. :to-equal "green"))
  499. (it "should not affect a non-blacklisted collection"
  500. (expect
  501. (with-simulated-input "g RET"
  502. (ido-completing-read+ "Prompt: " 'blacklisted-collection))
  503. :to-equal "green")))
  504. (describe "when the specified functions are blacklisted"
  505. (before-each
  506. (setq ido-cr+-function-blacklist
  507. (append '(blacklisted-command
  508. blacklisted-function
  509. blacklisted-collection)
  510. ido-cr+-function-blacklist)))
  511. (it "should prevent ido in a blacklisted command"
  512. (expect
  513. (with-simulated-input "g RET"
  514. (call-interactively 'blacklisted-command))
  515. :to-equal "g"))
  516. (it "should prevent ido in a blacklisted function"
  517. (expect
  518. (with-simulated-input "g RET"
  519. (call-interactively 'cmd-that-calls-blacklisted-function))
  520. :to-equal "g"))
  521. (it "should prevent ido with a blacklisted collection"
  522. (expect
  523. (with-simulated-input "g RET"
  524. (ido-completing-read+ "Prompt: " 'blacklisted-collection))
  525. :to-equal "g"))))
  526. (describe "with `ido-cr+-function-whitelist'"
  527. (before-all
  528. (setf (symbol-function 'whitelisted-command)
  529. (lambda (arg)
  530. (interactive
  531. (list
  532. (completing-read "Prompt: " '("blue" "yellow" "green"))))
  533. arg)
  534. (symbol-function 'whitelisted-function)
  535. (lambda ()
  536. (completing-read "Prompt: " '("blue" "yellow" "green")))
  537. (symbol-function 'cmd-that-calls-whitelisted-function)
  538. (lambda ()
  539. (interactive)
  540. (funcall 'whitelisted-function))
  541. (symbol-function 'whitelisted-collection)
  542. (lambda (string pred action)
  543. (complete-with-action action '("blue" "yellow" "green") string pred))))
  544. (after-all
  545. (setf (symbol-function 'whitelisted-command) nil
  546. (symbol-function 'whitelisted-function) nil
  547. (symbol-function 'cmd-that-calls-whitelisted-function) nil
  548. (symbol-function 'whitelisted-collection) nil))
  549. (describe "when the whitelist is inactive (i.e. everything is whitelisted)"
  550. (before-each
  551. (setq ido-cr+-function-whitelist nil))
  552. (it "should enable ido in a command"
  553. (expect
  554. (with-simulated-input "g RET"
  555. (call-interactively 'whitelisted-command))
  556. :to-equal "green"))
  557. (it "should enable ido in a function"
  558. (expect
  559. (with-simulated-input "g RET"
  560. (call-interactively 'cmd-that-calls-whitelisted-function))
  561. :to-equal "green"))
  562. (it "should enable ido for a collection"
  563. (expect
  564. (with-simulated-input "g RET"
  565. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  566. :to-equal "green")))
  567. (describe "when the specified functions are whitelisted"
  568. (before-each
  569. (setq ido-cr+-function-whitelist
  570. (append '(whitelisted-command
  571. whitelisted-function
  572. whitelisted-collection)
  573. ido-cr+-function-whitelist)))
  574. (it "should enable ido in a whitelisted command"
  575. (expect
  576. (with-simulated-input "g RET"
  577. (call-interactively 'whitelisted-command))
  578. :to-equal "green"))
  579. (it "should enable ido in a whitelisted function"
  580. (expect
  581. (with-simulated-input "g RET"
  582. (call-interactively 'cmd-that-calls-whitelisted-function))
  583. :to-equal "green"))
  584. (it "should enable ido for a whitelisted collection"
  585. (expect
  586. (with-simulated-input "g RET"
  587. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  588. :to-equal "green")))
  589. (describe "when the whitelist is active but empty (i.e. nothing whitelisted)"
  590. (before-each
  591. (setq ido-cr+-function-whitelist (list nil)))
  592. (it "should prevent ido in a command"
  593. (expect
  594. (with-simulated-input "g RET"
  595. (call-interactively 'whitelisted-command))
  596. :to-equal "g"))
  597. (it "should prevent ido in a function"
  598. (expect
  599. (with-simulated-input "g RET"
  600. (call-interactively 'cmd-that-calls-whitelisted-function))
  601. :to-equal "g"))
  602. (it "should prevent ido for a collection"
  603. (expect
  604. (with-simulated-input "g RET"
  605. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  606. :to-equal "g"))))
  607. (describe "with `ido-cr+-nil-def-alternate-behavior-list'"
  608. (before-all
  609. (setf (symbol-function 'def-nil-command)
  610. (lambda (arg)
  611. (interactive
  612. (list
  613. (completing-read "Prompt: " '("blue" "yellow" "green") nil t)))
  614. arg)
  615. (symbol-function 'def-nil-function)
  616. (lambda ()
  617. (completing-read "Prompt: " '("blue" "yellow" "green") nil t))
  618. (symbol-function 'cmd-that-calls-def-nil-function)
  619. (lambda ()
  620. (interactive)
  621. (funcall 'def-nil-function))
  622. (symbol-function 'def-nil-collection)
  623. (lambda (string pred action)
  624. (complete-with-action action '("blue" "yellow" "green") string pred))))
  625. (after-all
  626. (setf (symbol-function 'def-nil-command) nil
  627. (symbol-function 'def-nil-function) nil
  628. (symbol-function 'cmd-that-calls-def-nil-function) nil
  629. (symbol-function 'def-nil-collection) nil))
  630. (describe "when the specified functions are not in the list"
  631. (before-each
  632. (setq ido-cr+-nil-def-alternate-behavior-list nil))
  633. (it "should use empty string default in a command"
  634. (expect
  635. (with-simulated-input "RET"
  636. (call-interactively 'def-nil-command))
  637. :to-equal ""))
  638. (it "should use empty string default in a function"
  639. (expect
  640. (with-simulated-input "RET"
  641. (call-interactively 'cmd-that-calls-def-nil-function))
  642. :to-equal ""))
  643. (it "should use empty string default for a collection"
  644. (expect
  645. (with-simulated-input "RET"
  646. (ido-completing-read+ "Prompt: " 'def-nil-collection nil t))
  647. :to-equal "")))
  648. (describe "when the specified functions are in the list"
  649. (before-each
  650. (setq ido-cr+-nil-def-alternate-behavior-list
  651. (append '(def-nil-command
  652. def-nil-function
  653. def-nil-collection)
  654. ido-cr+-nil-def-alternate-behavior-list)))
  655. (it "should not use empty string default in a command"
  656. (expect
  657. (with-simulated-input "RET"
  658. (call-interactively 'def-nil-command))
  659. :to-equal "blue"))
  660. (it "should not use empty string default in a function"
  661. (expect
  662. (with-simulated-input "RET"
  663. (call-interactively 'cmd-that-calls-def-nil-function))
  664. :to-equal "blue"))
  665. (it "should not use empty string default for a collection"
  666. (expect
  667. (with-simulated-input "RET"
  668. (ido-completing-read+ "Prompt: " 'def-nil-collection nil t))
  669. :to-equal "blue"))))))
  670. ;; (defun ido-cr+-run-all-tests ()
  671. ;; (interactive)
  672. ;; (ert "^ido-cr\\+-"))
  673. ;;; test-ido-completing-read+.el ends here