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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  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. (describe "Within the `ido-completing-read+' package"
  93. ;; Reset all of these variables to their standard values before each
  94. ;; test, saving the previous values for later restoration.
  95. (before-each
  96. (shadow-vars
  97. ((ido-mode t)
  98. (ido-ubiquitous-mode t)
  99. ido-cr+-debug-mode
  100. ido-cr+-auto-update-blacklist
  101. ido-cr+-fallback-function
  102. ido-cr+-max-items
  103. ido-cr+-function-blacklist
  104. ido-cr+-function-whitelist
  105. ido-cr+-nil-def-alternate-behavior-list
  106. ido-cr+-replace-completely
  107. ido-confirm-unique-completion
  108. ido-enable-flex-matching)))
  109. ;; Restore the saved values after each test
  110. (after-each
  111. (fully-unshadow-all-vars))
  112. (describe "the `ido-completing-read+' function"
  113. (it "should complete with a matching item on RET"
  114. (expect
  115. (with-simulated-input "g RET"
  116. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  117. :to-equal "green"))
  118. (it "should complete with the first match when multiple matches are available"
  119. (expect
  120. (with-simulated-input "b RET"
  121. (ido-completing-read+ "Prompt: " '("brown" "blue" "yellow" "green")))
  122. :to-equal "brown"))
  123. (it "should allow <left> and <right> to cycle completions, with wrap-around"
  124. (expect
  125. (with-simulated-input "b <right> <right> <right> <right> <left> RET"
  126. (ido-completing-read+ "Prompt: " '("brown" "blue" "yellow" "green")))
  127. :to-equal
  128. "blue"))
  129. (it "should return \"\" when RET or C-j is pressed on an empty input even when REQUIRE-MATCH is non-nil"
  130. ;; No REQUIRE-MATCH
  131. (expect
  132. (with-simulated-input "RET"
  133. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  134. :to-equal "blue")
  135. (expect
  136. (with-simulated-input "C-j"
  137. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  138. :to-equal "")
  139. ;; Again, with REQUIRE-MATCH
  140. (expect
  141. (with-simulated-input "RET"
  142. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t))
  143. :to-equal "")
  144. (expect
  145. (with-simulated-input "C-j"
  146. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t))
  147. :to-equal ""))
  148. ;; Verify that DEF works, whether or not it is an element of
  149. ;; COLLECTION
  150. (it "should accept all the same forms of DEF as `completing-read-default'"
  151. (expect
  152. (with-simulated-input "RET"
  153. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil nil nil "green"))
  154. :to-equal "green")
  155. (expect
  156. (with-simulated-input "RET"
  157. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil t nil nil "green"))
  158. :to-equal "green")
  159. (expect
  160. (with-simulated-input "RET"
  161. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil nil nil nil "brown"))
  162. :to-equal "brown")
  163. (expect
  164. (with-simulated-input "RET"
  165. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil "brown"))
  166. :to-equal "brown")
  167. (expect
  168. (with-simulated-input "RET"
  169. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil '("brown" "green")))
  170. :to-equal "brown"))
  171. ;; Verify that INITIAL-INPUT works
  172. (it "should work with INITIAL-INPUT"
  173. (expect
  174. (with-simulated-input "RET"
  175. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr"))
  176. :to-equal "green"))
  177. ;; Verify that INITIAL-INPUT and DEF don't interfere with each other
  178. (it "should properly handle both INITIAL-INPUT and DEF at the same time"
  179. (expect
  180. (with-simulated-input "RET"
  181. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr" nil "blue"))
  182. :to-equal "green")
  183. (expect
  184. (with-simulated-input "DEL DEL RET"
  185. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green") nil nil "gr" nil "blue"))
  186. :to-equal "blue"))
  187. ;; Verify that ido-cr+ works on function collections
  188. (it "should work when COLLECTION is a function"
  189. (expect
  190. (with-simulated-input "g RET"
  191. (ido-completing-read+ "Prompt: " (collection-as-function '("blue" "yellow" "green"))))
  192. :to-equal "green"))
  193. (describe "when `ido-cr+-max-items' is set"
  194. (it "should not trigger a fallback for small collections"
  195. (expect
  196. (with-simulated-input "g RET"
  197. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  198. :to-equal "green"))
  199. (it "should trigger a fallback for large collections"
  200. (expect
  201. ;; With max-items negative, all collections are considered "too
  202. ;; large"
  203. (let ((ido-cr+-max-items -1))
  204. (with-simulated-input "g RET"
  205. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green"))))
  206. :to-equal "g")))
  207. (describe "when REQUIRE-MATCH is non-nil"
  208. (it "should still allow exiting with an empty string if DEF is nil"
  209. (expect
  210. (with-simulated-input "C-j"
  211. (ido-completing-read+
  212. "Prompt: "
  213. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  214. :to-equal ""))
  215. ;; "C-j" should NOT be allowed to return an empty string if
  216. ;; require-match and default are both non-nil.
  217. (it "should not alow exiting with an empty string if DEF is non-nil"
  218. (expect
  219. (with-simulated-input "C-j"
  220. (ido-completing-read+
  221. "Prompt: "
  222. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t nil nil "yellow"))
  223. :to-throw))
  224. (it "shouldn't allow C-j to select an ambiguous match"
  225. (expect
  226. (with-simulated-input "b C-j C-j C-j"
  227. (ido-completing-read+
  228. "Prompt: "
  229. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  230. :to-throw)
  231. ;; First press of C-j should complete to "blue" after the
  232. ;; first b, but then get stuck on the choice for the second b.
  233. (expect
  234. (with-simulated-input "b C-j b C-j C-j C-j"
  235. (ido-completing-read+
  236. "Prompt: "
  237. '("bluebird" "blues" "bluegrass" "blueberry" "yellow" "green") nil t))
  238. :to-throw))
  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
  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. :to-throw)
  264. ;; The first "C-j" should complete to "bluegrass", and the second
  265. ;; should return.
  266. (expect
  267. (with-simulated-input "b l u e g C-j C-j"
  268. (ido-completing-read+
  269. "Prompt: "
  270. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  271. :to-equal "bluegrass"))
  272. ;; Finally, a test for the expected wrong behavior without
  273. ;; ido-cr+. If ido.el ever fixes this bug, it will cause this test
  274. ;; to fail as a signal that the workaround can be phased out.
  275. (it "should return a non-match when ordinary `ido-completing-read' is used"
  276. (expect
  277. (with-simulated-input "b C-j"
  278. (ido-completing-read
  279. "Prompt: "
  280. '("bluebird" "blues" "bluegrass" "blueberry" "yellow ""green") nil t))
  281. :to-equal "b")))
  282. (describe "with manual fallback shortcuts"
  283. (it "should not fall back when C-b or C-f is used in the middle of the input"
  284. (expect
  285. ;; C-b/f not at beginning/end of input should not fall back
  286. (with-simulated-input "g C-b C-f RET"
  287. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  288. :to-equal "green"))
  289. (it "should fall back on C-f at end of input"
  290. (expect
  291. ;; C-f at end of input should fall back
  292. (with-simulated-input "g C-f RET"
  293. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  294. :to-equal "g"))
  295. (it "should not fall back from repeated C-b that hits the start of input"
  296. (expect
  297. ;; Repeated C-b should not fall back
  298. (with-simulated-input "g C-b C-b C-b C-b RET"
  299. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  300. :to-equal "green"))
  301. (it "should fall back on C-b at beginning of input (if previous action was not C-b)"
  302. (expect
  303. ;; C-b at beginning of line should fall back (if previous action
  304. ;; was not also C-b)
  305. (with-simulated-input "g C-b x DEL C-b RET"
  306. (ido-completing-read+ "Prompt: " '("blue" "yellow" "green")))
  307. :to-equal "g")))
  308. (describe "with a workaround for an bug with non-nil `ido-enable-dot-prefix'"
  309. ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26997
  310. ;; for more information on this bug.
  311. (before-each
  312. (setq ido-enable-dot-prefix t))
  313. (it "should not throw an error when \"\" is in the collection"
  314. (expect
  315. (with-simulated-input "RET"
  316. (ido-completing-read+ "Pick: " '("" "aaa" "aab" "aac")))
  317. :to-equal "")
  318. (expect
  319. (with-simulated-input "a a b RET"
  320. (ido-completing-read+ "Pick: " '("" "aaa" "aab" "aac")))
  321. :to-equal "aab")))
  322. (describe "with dynamic collections"
  323. (before-all
  324. (setq my-dynamic-collection
  325. (completion-table-dynamic
  326. (lambda (text)
  327. (cond
  328. ;; Sub-completions for "hello"
  329. ((s-prefix-p "hello" text)
  330. '("hello" "hello-world" "hello-everyone" "hello-universe"))
  331. ;; Sub-completions for "goodbye"
  332. ((s-prefix-p "goodbye" text)
  333. '("goodbye" "goodbye-world" "goodbye-everyone" "goodbye-universe"))
  334. ;; General completions
  335. (t
  336. '("hello" "goodbye" "helicopter" "helium" "goodness" "goodwill")))))))
  337. (after-all
  338. (setq my-dynamic-collection nil))
  339. (before-each
  340. (setq ido-enable-flex-matching t
  341. ido-confirm-unique-completion nil)
  342. (spy-on 'ido-cr+-update-dynamic-collection
  343. :and-call-through))
  344. (it "should allow selection of dynamically-added completions"
  345. (expect
  346. (with-simulated-input "hello- RET"
  347. (ido-completing-read+ "Say something: " my-dynamic-collection))
  348. :to-equal "hello-world")
  349. (expect 'ido-cr+-update-dynamic-collection
  350. :to-have-been-called))
  351. (it "should allow ido flex-matching of dynamically-added completions"
  352. (expect
  353. (with-simulated-input "hello-ld RET"
  354. (ido-completing-read+ "Say something: " my-dynamic-collection))
  355. :to-equal
  356. "hello-world")
  357. (expect 'ido-cr+-update-dynamic-collection
  358. :to-have-been-called))
  359. (it "should do a dynamic update when pressing TAB"
  360. (expect
  361. (with-simulated-input "h TAB -ld RET"
  362. (ido-completing-read+ "Say something: " my-dynamic-collection))
  363. :to-equal
  364. "hello-world")
  365. (expect 'ido-cr+-update-dynamic-collection
  366. :to-have-been-called))
  367. (it "should do a dynamic update when idle"
  368. (expect
  369. (with-simulated-input
  370. '("h"
  371. (wsi-simulate-idle-time (1+ ido-cr+-dynamic-update-idle-time))
  372. "-ld RET")
  373. (ido-completing-read+ "Say something: " my-dynamic-collection))
  374. :to-equal
  375. "hello-world")
  376. (expect 'ido-cr+-update-dynamic-collection
  377. :to-have-been-called))
  378. (it "should do a dynamic update when there is only one match remaining"
  379. (expect
  380. (with-simulated-input "hell-ld RET"
  381. (ido-completing-read+ "Say something: " my-dynamic-collection))
  382. :to-equal
  383. "hello-world")
  384. (expect 'ido-cr+-update-dynamic-collection
  385. :to-have-been-called))
  386. (it "should not exit with a unique match if new matches are dynamically added"
  387. (expect
  388. (with-simulated-input '("hell TAB -ld RET")
  389. (ido-completing-read+ "Say something: " my-dynamic-collection))
  390. :to-equal
  391. "hello-world")
  392. (expect 'ido-cr+-update-dynamic-collection
  393. :to-have-been-called))
  394. (it "should exit with a match that is still unique after dynamic updating"
  395. (expect
  396. (with-simulated-input '("helic TAB")
  397. (ido-completing-read+ "Say something: " my-dynamic-collection))
  398. :to-equal
  399. "helicopter")
  400. (expect 'ido-cr+-update-dynamic-collection
  401. :to-have-been-called))
  402. (it "should respect `ido-restrict-to-matches' when doing dynamic updates"
  403. (let ((collection
  404. (list "aaa-ddd-ggg" "aaa-eee-ggg" "aaa-fff-ggg"
  405. "bbb-ddd-ggg" "bbb-eee-ggg" "bbb-fff-ggg"
  406. "ccc-ddd-ggg" "ccc-eee-ggg" "ccc-fff-ggg"
  407. "aaa-ddd-hhh" "aaa-eee-hhh" "aaa-fff-hhh"
  408. "bbb-ddd-hhh" "bbb-eee-hhh" "bbb-fff-hhh"
  409. "ccc-ddd-hhh" "ccc-eee-hhh" "ccc-fff-hhh"
  410. "aaa-ddd-iii" "aaa-eee-iii" "aaa-fff-iii"
  411. "bbb-ddd-iii" "bbb-eee-iii" "bbb-fff-iii"
  412. "ccc-ddd-iii" "ccc-eee-iii" "ccc-fff-iii")))
  413. ;; Test the internal function
  414. (expect
  415. (ido-cr+-apply-restrictions
  416. collection
  417. (list (cons nil "bbb")
  418. (cons nil "eee")))
  419. :to-equal '("bbb-eee-ggg" "bbb-eee-hhh" "bbb-eee-iii"))
  420. ;; First verify it without a dynamic collection
  421. (expect
  422. (with-simulated-input "eee C-SPC bbb C-SPC ggg RET"
  423. (ido-completing-read+
  424. "Pick: " collection nil t nil nil (car collection)))
  425. :to-equal "bbb-eee-ggg")
  426. ;; Now test the same with a dynamic collection
  427. (expect
  428. (with-simulated-input "eee C-SPC bbb C-SPC ggg RET"
  429. (ido-completing-read+
  430. "Pick: " (collection-as-function collection) nil t nil nil (car collection)))
  431. :to-equal "bbb-eee-ggg"))))
  432. (describe "with unusual inputs"
  433. (it "should accept a COLLECTION of symbols"
  434. (expect
  435. (with-simulated-input "g RET"
  436. (ido-completing-read+ "Prompt: " '(blue yellow green)))
  437. :to-equal "green"))
  438. (it "should accept a mix of strings and symbols in COLLECTION"
  439. (expect
  440. (with-simulated-input "g RET"
  441. (ido-completing-read+ "Prompt: " '(blue "yellow" green)))
  442. :to-equal "green"))
  443. (it "should accept symbols in DEF"
  444. (expect
  445. (with-simulated-input "RET"
  446. (ido-completing-read+ "Prompt: " '("blue" "yellow" "brown") nil t nil nil '(brown "green")))
  447. :to-equal "brown"))
  448. (it "should accept an alist COLLECTION"
  449. (expect
  450. (with-simulated-input "RET"
  451. (ido-completing-read+
  452. "Prompt: "
  453. '(("blue" . blue-value)
  454. ("yellow" . yellow-value)
  455. (green . green-value))
  456. nil nil nil nil "green"))
  457. :to-equal "green"))
  458. (it "should accept a hash table COLLECTION"
  459. (expect
  460. (with-simulated-input "RET"
  461. (let ((collection (make-hash-table)))
  462. (puthash "blue" 'blue-value collection)
  463. (puthash "yellow" 'yellow-value collection)
  464. (puthash 'green 'green-value collection)
  465. (ido-completing-read+ "Prompt: " collection nil nil nil nil "green")))
  466. :to-equal "green"))
  467. (it "should accept an obarray COLLECTION"
  468. (expect
  469. (with-simulated-input "forward-char RET"
  470. (ido-completing-read+ "Prompt: " obarray #'commandp
  471. t nil nil "backward-char"))
  472. :to-equal "forward-char"))))
  473. (describe "ido-ubiquitous-mode"
  474. ;; Set up a test command that calls `completing-read'
  475. (before-all
  476. (setf (symbol-function 'test-command)
  477. (lambda ()
  478. (interactive)
  479. (completing-read "Prompt: " '("blue" "yellow" "green")))))
  480. ;; Delete the test command
  481. (after-all
  482. (setf (symbol-function 'test-command) nil))
  483. ;; Verify that the mode can be activated
  484. (it "should enable itself properly"
  485. (expect
  486. (progn
  487. (ido-ubiquitous-mode 1)
  488. (with-simulated-input "g RET"
  489. (command-execute 'test-command)))
  490. :to-equal "green"))
  491. (it "should disable itself properly"
  492. (expect
  493. (progn
  494. (ido-ubiquitous-mode 0)
  495. (with-simulated-input "g RET"
  496. (command-execute 'test-command)))
  497. :to-equal "g"))
  498. (describe "with `ido-cr+-function-blacklist'"
  499. (before-all
  500. (setf (symbol-function 'blacklisted-command)
  501. (lambda (arg)
  502. (interactive (list (completing-read "Prompt: " '("blue" "yellow" "green"))))
  503. arg)
  504. (symbol-function 'blacklisted-function)
  505. (lambda ()
  506. (completing-read "Prompt: " '("blue" "yellow" "green")))
  507. (symbol-function 'cmd-that-calls-blacklisted-function)
  508. (lambda ()
  509. (interactive)
  510. (funcall 'blacklisted-function))
  511. (symbol-function 'blacklisted-collection)
  512. (collection-as-function '("blue" "yellow" "green"))))
  513. (after-all
  514. (setf (symbol-function 'blacklisted-command) nil
  515. (symbol-function 'blacklisted-function) nil
  516. (symbol-function 'cmd-that-calls-blacklisted-function) nil
  517. (symbol-function 'blacklisted-collection) nil))
  518. ;; First verify that they work normally before blacklisting them
  519. (describe "when the blacklist is empty"
  520. (it "should not affect a non-blacklisted command"
  521. (expect
  522. (with-simulated-input "g RET"
  523. (call-interactively 'blacklisted-command))
  524. :to-equal "green"))
  525. (it "should not affect a non-blacklisted function"
  526. (expect
  527. (with-simulated-input "g RET"
  528. (call-interactively 'cmd-that-calls-blacklisted-function))
  529. :to-equal "green"))
  530. (it "should not affect a non-blacklisted collection"
  531. (expect
  532. (with-simulated-input "g RET"
  533. (ido-completing-read+ "Prompt: " 'blacklisted-collection))
  534. :to-equal "green")))
  535. (describe "when the specified functions are blacklisted"
  536. (before-each
  537. (setq ido-cr+-function-blacklist
  538. (append '(blacklisted-command
  539. blacklisted-function
  540. blacklisted-collection)
  541. ido-cr+-function-blacklist)))
  542. (it "should prevent ido in a blacklisted command"
  543. (expect
  544. (with-simulated-input "g RET"
  545. (call-interactively 'blacklisted-command))
  546. :to-equal "g"))
  547. (it "should prevent ido in a blacklisted function"
  548. (expect
  549. (with-simulated-input "g RET"
  550. (call-interactively 'cmd-that-calls-blacklisted-function))
  551. :to-equal "g"))
  552. (it "should prevent ido with a blacklisted collection"
  553. (expect
  554. (with-simulated-input "g RET"
  555. (ido-completing-read+ "Prompt: " 'blacklisted-collection))
  556. :to-equal "g"))))
  557. (describe "with `ido-cr+-function-whitelist'"
  558. (before-all
  559. (setf (symbol-function 'whitelisted-command)
  560. (lambda (arg)
  561. (interactive
  562. (list
  563. (completing-read "Prompt: " '("blue" "yellow" "green"))))
  564. arg)
  565. (symbol-function 'whitelisted-function)
  566. (lambda ()
  567. (completing-read "Prompt: " '("blue" "yellow" "green")))
  568. (symbol-function 'cmd-that-calls-whitelisted-function)
  569. (lambda ()
  570. (interactive)
  571. (funcall 'whitelisted-function))
  572. (symbol-function 'whitelisted-collection)
  573. (lambda (string pred action)
  574. (complete-with-action action '("blue" "yellow" "green") string pred))))
  575. (after-all
  576. (setf (symbol-function 'whitelisted-command) nil
  577. (symbol-function 'whitelisted-function) nil
  578. (symbol-function 'cmd-that-calls-whitelisted-function) nil
  579. (symbol-function 'whitelisted-collection) nil))
  580. (describe "when the whitelist is inactive (i.e. everything is whitelisted)"
  581. (before-each
  582. (setq ido-cr+-function-whitelist nil))
  583. (it "should enable ido in a command"
  584. (expect
  585. (with-simulated-input "g RET"
  586. (call-interactively 'whitelisted-command))
  587. :to-equal "green"))
  588. (it "should enable ido in a function"
  589. (expect
  590. (with-simulated-input "g RET"
  591. (call-interactively 'cmd-that-calls-whitelisted-function))
  592. :to-equal "green"))
  593. (it "should enable ido for a collection"
  594. (expect
  595. (with-simulated-input "g RET"
  596. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  597. :to-equal "green")))
  598. (describe "when the specified functions are whitelisted"
  599. (before-each
  600. (setq ido-cr+-function-whitelist
  601. (append '(whitelisted-command
  602. whitelisted-function
  603. whitelisted-collection)
  604. ido-cr+-function-whitelist)))
  605. (it "should enable ido in a whitelisted command"
  606. (expect
  607. (with-simulated-input "g RET"
  608. (call-interactively 'whitelisted-command))
  609. :to-equal "green"))
  610. (it "should enable ido in a whitelisted function"
  611. (expect
  612. (with-simulated-input "g RET"
  613. (call-interactively 'cmd-that-calls-whitelisted-function))
  614. :to-equal "green"))
  615. (it "should enable ido for a whitelisted collection"
  616. (expect
  617. (with-simulated-input "g RET"
  618. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  619. :to-equal "green")))
  620. (describe "when the whitelist is active but empty (i.e. nothing whitelisted)"
  621. (before-each
  622. (setq ido-cr+-function-whitelist (list nil)))
  623. (it "should prevent ido in a command"
  624. (expect
  625. (with-simulated-input "g RET"
  626. (call-interactively 'whitelisted-command))
  627. :to-equal "g"))
  628. (it "should prevent ido in a function"
  629. (expect
  630. (with-simulated-input "g RET"
  631. (call-interactively 'cmd-that-calls-whitelisted-function))
  632. :to-equal "g"))
  633. (it "should prevent ido for a collection"
  634. (expect
  635. (with-simulated-input "g RET"
  636. (ido-completing-read+ "Prompt: " 'whitelisted-collection))
  637. :to-equal "g"))))
  638. (describe "with `ido-cr+-nil-def-alternate-behavior-list'"
  639. (before-all
  640. (setf (symbol-function 'def-nil-command)
  641. (lambda (arg)
  642. (interactive
  643. (list
  644. (completing-read "Prompt: " '("blue" "yellow" "green") nil t)))
  645. arg)
  646. (symbol-function 'def-nil-function)
  647. (lambda ()
  648. (completing-read "Prompt: " '("blue" "yellow" "green") nil t))
  649. (symbol-function 'cmd-that-calls-def-nil-function)
  650. (lambda ()
  651. (interactive)
  652. (funcall 'def-nil-function))
  653. (symbol-function 'def-nil-collection)
  654. (lambda (string pred action)
  655. (complete-with-action action '("blue" "yellow" "green") string pred))))
  656. (after-all
  657. (setf (symbol-function 'def-nil-command) nil
  658. (symbol-function 'def-nil-function) nil
  659. (symbol-function 'cmd-that-calls-def-nil-function) nil
  660. (symbol-function 'def-nil-collection) nil))
  661. (describe "when the specified functions are not in the list"
  662. (before-each
  663. (setq ido-cr+-nil-def-alternate-behavior-list nil))
  664. (it "should use empty string default in a command"
  665. (expect
  666. (with-simulated-input "RET"
  667. (call-interactively 'def-nil-command))
  668. :to-equal ""))
  669. (it "should use empty string default in a function"
  670. (expect
  671. (with-simulated-input "RET"
  672. (call-interactively 'cmd-that-calls-def-nil-function))
  673. :to-equal ""))
  674. (it "should use empty string default for a collection"
  675. (expect
  676. (with-simulated-input "RET"
  677. (ido-completing-read+ "Prompt: " 'def-nil-collection nil t))
  678. :to-equal "")))
  679. (describe "when the specified functions are in the list"
  680. (before-each
  681. (setq ido-cr+-nil-def-alternate-behavior-list
  682. (append '(def-nil-command
  683. def-nil-function
  684. def-nil-collection)
  685. ido-cr+-nil-def-alternate-behavior-list)))
  686. (it "should not use empty string default in a command"
  687. (expect
  688. (with-simulated-input "RET"
  689. (call-interactively 'def-nil-command))
  690. :to-equal "blue"))
  691. (it "should not use empty string default in a function"
  692. (expect
  693. (with-simulated-input "RET"
  694. (call-interactively 'cmd-that-calls-def-nil-function))
  695. :to-equal "blue"))
  696. (it "should not use empty string default for a collection"
  697. (expect
  698. (with-simulated-input "RET"
  699. (ido-completing-read+ "Prompt: " 'def-nil-collection nil t))
  700. :to-equal "blue"))))))
  701. ;; (defun ido-cr+-run-all-tests ()
  702. ;; (interactive)
  703. ;; (ert "^ido-cr\\+-"))
  704. ;;; test-ido-completing-read+.el ends here