Compare commits

...

461 Commits

Author SHA1 Message Date
Eric Freese
0e810e5afa
Merge pull request #813 from tesar-tech/patch-1
Some checks failed
/ determine-versions (push) Has been cancelled
/ test (push) Has been cancelled
Fixes link for nixos package
2024-11-25 20:07:39 -07:00
Jan Tesař
f9526195c5
Fixes link for nixos package 2024-11-25 18:04:58 +01:00
Eric Freese
e52ee8ca55
Merge pull request #811 from zsh-users/develop
Some checks failed
/ determine-versions (push) Failing after 15s
/ test (push) Has been skipped
v0.7.1
2024-11-15 12:47:51 -07:00
Eric Freese
f8907cf32b v0.7.1
Some checks failed
/ determine-versions (push) Failing after 16s
/ test (push) Has been skipped
2024-11-15 12:36:08 -07:00
Eric Freese
a50468ef4b Update changelog for v0.7.1 release 2024-11-15 12:35:58 -07:00
Eric Freese
9aceef9646 Remove circle ci reference left over from switch to github actions 2024-11-15 12:28:27 -07:00
Joe Schaefer
11d17e7fea Clear POSTDISPLAY instead of unsetting
We don't have any particular reason to unset. Clearing should be good
enough, and avoid any errors using unset parameters.

Cherry-picked from PR #634
2023-09-07 09:54:04 -06:00
Eric Freese
a593f4dfec
Merge pull request #630 from codicodi/reset-fd
Always reset file descriptor after consuming it
2023-09-07 09:39:17 -06:00
Eric Freese
2c9e57fd50
Merge pull request #628 from jeebak/develop
Ensure that we're using the builtin exec
2023-09-07 09:31:03 -06:00
Eric Freese
c3d4e576c9
Merge pull request #687 from japanese-goblinn/master
fix: Makefile SRC_DIR spacing
2023-09-07 08:58:48 -06:00
Pablo Speciale
23f2943455 Add more common widgets to list of clear widgets
Cherry-picked from PR #706 and updates made to src/config.zsh.

Fixes issues #678
2023-09-07 08:49:25 -06:00
Eric Freese
95602e2dea
Merge pull request #723 from migimigi/migimigi-patch-1
Create .gitignore for *.zwc
2023-09-07 08:46:09 -06:00
Eric Freese
39aa7bed3a
Merge pull request #671 from jirutka/patch-1
Install: Add Alpine Linux package
2023-09-04 09:56:08 -06:00
Eric Freese
27c298cf1a
Merge pull request #711 from dpthegrey/patch-1
Update Install.md
2023-09-04 09:54:44 -06:00
Eric Freese
a84d78f8b5
Merge pull request #758 from mjperrone/patch-1
Update INSTALL link for Mac OS - homebrew moved under z/
2023-09-04 09:53:24 -06:00
Mike Perrone
309d32ac9e
Update INSTALL link for Mac OS - homebrew moved under z/ 2023-09-03 10:00:21 -07:00
Eric Freese
9908eb49a3
Merge pull request #755 from rweir/master
Update README.md
2023-08-17 20:15:04 -06:00
Rob Weir
2b97cf3b30
Update README.md
Clarify where to get `zpty` from.

Info from https://apple.stackexchange.com/a/416099 and https://zsh.sourceforge.io/releases.html .
2023-08-17 23:42:12 +01:00
Eric Freese
9b0272944f Add support for 5.9 2023-05-26 19:57:30 -06:00
Eric Freese
c5044edd48 Support latest minor version of 5.8 2023-05-26 19:57:14 -06:00
Eric Freese
2cc34c015e Switch from Circle CI to GitHub Actions
The testing docker image has been split up. Instead of having one image
with all supported versions of zsh installed, we now have a separate
image for each supported zsh version.

We use GitHub Action matrices to run jobs in parallel for all of the
supported versions.

We no longer need to publish images to Docker Hub. The images are just
built by CI (or developers) as needed from the Dockerfile in the repo.
2023-05-26 19:44:39 -06:00
migimigi
f29bb7f032
Create .gitignore for *.zwc 2023-02-14 01:08:57 +09:00
D
c14ad9fc46
Update Install.md
Adds steps to install zsh-autosuggestions via Homebrew Formulae.
2022-10-12 13:10:21 +05:30
japanese-goblinn
fc391d6bf6 fix: Makefile SRC_DIR spacing 2022-05-16 22:11:12 +03:00
Jakub Jirutka
7795a357e6
Install: Add Alpine Linux package 2022-03-15 22:52:50 +01:00
Robert Cegliński
56f10c3b5d Always reset file descriptor after consuming it
This prevents the request cancelling logic from closing an unrelated fd that happens to reuse the same number.
2021-09-17 00:15:07 +02:00
JeeBak Kim
8072e52d96 Run: make 2021-08-28 22:15:54 -07:00
JeeBak Kim
69bf058c23 Ensure we're using the builtin exec 2021-08-28 22:15:54 -07:00
Eric Freese
a411ef3e09
Merge pull request #613 from zsh-users/develop
v0.7.0
2021-06-04 16:05:04 -06:00
Eric Freese
fcca87555f v0.7.0 2021-06-04 16:02:12 -06:00
Eric Freese
74ba3739bb Update changelog for v0.7.0 release 2021-06-04 16:02:12 -06:00
Eric Freese
3ecc53dfe2 Update license copyright year 2021-06-04 16:02:12 -06:00
Eric Freese
aa05920a4a Merge remote-tracking branch 'origin/pull/541' into develop 2021-06-04 15:33:29 -06:00
Eric Freese
89c600c873 Support new zsh version: 5.8 2021-06-04 14:42:16 -06:00
Eric Freese
3474c87d67
Merge pull request #612 from abcdw/develop
Disable ^C async workaround for zsh version 5.8 and later
2021-06-04 14:30:13 -06:00
Andrew Tropin
590c1cd84c
Disable ^C async workaround for zsh version 5.8 and later 2021-06-03 19:42:58 +03:00
Eric Freese
58c98a7739
Merge pull request #588 from keskinsaf/#587-fix-installation-aside-other-plugins
Update INSTALL.md
2021-03-09 06:38:25 -07:00
keskinsaf
bb18c4f677
Update INSTALL.md 2021-03-09 11:08:18 +03:00
keskinsaf
9ad305c906
Update INSTALL.md
[fix] install this plugin aside other plugins
2021-03-08 14:44:01 +03:00
Eric Freese
eff0894a13
Merge pull request #530 from zsh-users/fixes/flaky-ci
Fixes/flaky ci
2020-06-05 14:51:33 -06:00
Roman Perepelitsa
e0b96e1bd6 fix a bug in partial acceptance of suggestions
To reproduce:

1. Run `zsh -f`.
2. Run this:
  function bye() { BUFFER=bye }
  zle -N bye
  bindkey '^B' bye
  print -s 'hibye unexpected'
  source ~/zsh-autosuggestions/zsh-autosuggestions.zsh
3. Type `hi` and press Ctrl-B.

Expected: POSTBUFFER is empty.

Actual: POSTBUFFER is " unexpected".
2020-05-29 09:41:39 +02:00
Eric Freese
05f22fa8a3 Fix flaky special char specs by not using with_history twice per test
There's something funny occasionally happening when `with_history` is
used twice in the same test. It seems to be happening more frequently
since asynchronous mode was enabled by default. My guess is it has
something to do with the `C-c` keys being sent toward the end not
consistently terminating the prompt. But I'm really not sure how it
would ever get into a `then` block like it seems to:

```
Failure/Error: wait_for { session.content }.to eq('echo "hello\nworld"')

  expected: "echo \"hello\\nworld\""
       got: "then> echo \"hello\\"
```

Sticking to only one `with_history` per terminal session (per test)
seems to fix the flakiness.

I also removed an old test case because I could not understand why it
was necessary and so couldn't write a good description for it. Could be
we'll need to add it back in at some point.
2020-05-06 23:43:26 -06:00
Eric Freese
e715ffb1ae Rewrite with_history test helper to be more robust
Write mock history to a temp file and load it directly with `fc -R`
instead of running each command individually to build up the history.
2020-05-06 07:31:37 -06:00
Eric Freese
9ad039443f
Merge pull request #504 from zsh-users/ef/async-by-default
Enable async mode by default in newer versions of zsh
2020-01-29 20:54:46 -07:00
Eric Freese
a32fe24acc
Merge pull request #502 from zsh-users/cleanup/idiomatic-check-if-set
cleanup: Use more idiomatic method of checking if var is set
2020-01-27 21:46:14 -07:00
Eric Freese
e3897c25c0
Merge pull request #501 from zsh-users/fixes/more-specific-widget-ignore
Be more specific about the built-in widgets we want to avoid wrapping
2020-01-27 21:45:44 -07:00
Eric Freese
ee18c7ce24
Merge pull request #505 from zsh-users/ef/readme-glob-links
Add links to documentation on zsh glob patterns to the readme
2020-01-27 21:40:40 -07:00
Eric Freese
a83c7cf9d6 Add links to documentation on zsh glob patterns to the readme
See GitHub issue #503
2020-01-26 21:26:38 -07:00
Eric Freese
6c634c1e35 Enable async mode by default in newer versions of zsh
Allow users to override the default by unsetting (or setting) the
ZSH_AUTOSUGGEST_USE_ASYNC variable.

See GitHub issue #498.
2020-01-26 21:18:49 -07:00
Eric Freese
19e375bbc8 cleanup: Consolidate autoloads 2020-01-26 21:15:47 -07:00
Eric Freese
c114bd2298 Be more specific about the built-in widgets we want to avoid wrapping
To avoid wrapping the built-in widgets (e.g. `autosuggest-fetch`,
`autosuggest-toggle`), we were ignoring all widgets whose names start
with `autosuggest-`. This had the downside of preventing wrapping of
user-defined widgets whose names happened to also start with that
prefix.

By being more specific about the exact built-in widgets we want to avoid
wrapping, we can allow users to define widgets whose names start with
`autosuggest-`.

See GitHub issue #496.
2020-01-25 08:01:37 -07:00
Eric Freese
7682c13860 cleanup: Pull built-in widget actions into global variable 2020-01-25 08:01:37 -07:00
Eric Freese
f90d040784 cleanup: Use more idiomatic method of checking if var is set
We are already using this method in other places.

For example: `ZSH_AUTOSUGGEST_USE_ASYNC`
2020-01-25 07:46:20 -07:00
Eric Freese
ae315ded4d
Merge pull request #494 from zsh-users/develop
v0.6.4
2020-01-06 21:12:21 -07:00
Eric Freese
ff298e57c0 completion suggestion strategy seems pretty stable 2020-01-06 21:11:31 -07:00
Eric Freese
a5affac6f1 v0.6.4 2020-01-06 21:06:16 -07:00
Eric Freese
03f59df502 Update changelog for v0.6.4 release 2020-01-06 21:04:43 -07:00
Eric Freese
cf445d08b0
Merge pull request #487 from zsh-users/features/completion-ignore
Allow skipping completion suggestions when buffer matches a pattern
2020-01-04 16:52:35 -07:00
Eric Freese
0d2c9de2ea
Merge pull request #488 from zsh-users/fixes/run-orig-before-move-cursor
Call original widget before moving cursor when accepting suggestion
2020-01-04 16:52:18 -07:00
Eric Freese
8f3f59542a
Merge pull request #473 from zsh-users/refactor-null-byte-split
cleanup: Split on null bytes instead of pattern matching
2019-12-15 10:41:02 -05:00
Eric Freese
6ec95379fa Call original widget before moving cursor when accepting suggestion
The check on length of `$POSTDISPLAY` is in support of the test for
`vi-delete` on the last char of the buffer with `dl`.

Fixes issue #482.
2019-12-15 08:33:20 -07:00
Eric Freese
7afb7364f1 Allow skipping completion suggestions when buffer matches a pattern
Set ZSH_AUTOSUGGEST_COMPLETION_IGNORE to a glob pattern to have the
completion suggestion strategy never make suggestions when the buffer
matches the pattern.

This can be helpful when some completion routines you have are
particularly expensive and you want to prevent them from running
automatically on every keystroke.

See GitHub issue #463.
2019-12-15 08:13:54 -07:00
Eric Freese
54d7a9a84c cleanup: Switch to guard clause in accept widget handler 2019-12-15 07:01:39 -07:00
Eric Freese
5217ed5269 cleanup: Switch to arithmetic comparison 2019-12-15 07:01:39 -07:00
Eric Freese
ef657cb38c cleanup: Combine two arithmetic conditionals 2019-12-15 07:01:39 -07:00
Eric Freese
d43c309f88
Merge pull request #476 from gregrickaby/patch-1
(README) Link to 256 color chart
2019-10-16 10:07:12 -06:00
Greg Rickaby
c6b636ea4f
(README) Link to 256 color chart
Easy to see and choose a color, and then copy it over from the chart.
2019-10-10 09:15:15 -05:00
Eric Freese
0f0f221180 cleanup: Split on null bytes instead of pattern matching
Follow-up to technique tried in commit d94475c after I learned about the
`@` flag to keep empty strings in the array.
2019-09-30 12:12:52 -06:00
Eric Freese
4016ff795b Fix circle ci build issues
We are getting errors on circle ci builds (e.g. see [1]):

```
CircleCI was unable to run the job runner because we were unable to
execute commands in build container.

This typically means that the build container entrypoint or command is
terminating the container prematurely, or interfering with executed
commands.  Consider clearing entrypoint/command values and try again.
```

Folks in this thread [2] suggest removing the `command: /sbin/init` line
initially added by the v1 => v2 migration script.

---

1: https://circleci.com/gh/zsh-users/zsh-autosuggestions/381
2: https://discuss.circleci.com/t/circleci-was-unable-to-run-the-job-runner/31894/18
2019-09-30 12:11:41 -06:00
Eric Freese
bdbe43e667
Merge pull request #474 from zsh-users/fixes/circle-ci-image
Fix circle ci build issues
2019-09-30 12:10:08 -06:00
Eric Freese
eab0e9b574 Fix circle ci build issues
We are getting errors on circle ci builds (e.g. see [1]):

```
CircleCI was unable to run the job runner because we were unable to
execute commands in build container.

This typically means that the build container entrypoint or command is
terminating the container prematurely, or interfering with executed
commands.  Consider clearing entrypoint/command values and try again.
```

Folks in this thread [2] suggest removing the `command: /sbin/init` line
initially added by the v1 => v2 migration script.

---

1: https://circleci.com/gh/zsh-users/zsh-autosuggestions/381
2: https://discuss.circleci.com/t/circleci-was-unable-to-run-the-job-runner/31894/18
2019-09-26 09:58:36 -06:00
Eric Freese
24655d9328 Merge branch 'master' into develop 2019-09-25 15:30:35 -06:00
Eric Freese
43f3bc4010 Add gitter badge (#461) 2019-07-15 11:39:10 -06:00
Eric Freese
fdc4292a7f Switch to shields badges 2019-07-15 11:18:31 -06:00
Eric Freese
3baf9468c2
Merge pull request #459 from zsh-users/meta/package-installation-links
Add package links to install docs (#222)
2019-07-07 10:30:05 -06:00
Eric Freese
3da421aa47
Merge pull request #456 from zsh-users/features/history-ignore
Allow configuring to ignore history entries matching a pattern
2019-07-02 23:00:27 -06:00
Eric Freese
b87a4972c8 Allow configuring to ignore history entries matching a pattern
Set ZSH_AUTOSUGGEST_HISTORY_IGNORE to a glob pattern to have the history
and match_prev_cmd suggestion strategies never make suggestions matching
that pattern.

For example, set to "cd *" to never suggest any `cd` commands from
history (see issues #340 and #425). Or set to "?(#c50,)" to never
suggest anything 50 characters or longer (see issue #429).
2019-07-02 21:46:17 -06:00
Eric Freese
01dce8999f Add package links to install docs (#222)
Copied from zsh-users/zsh-completions. Removed missing packages for
Gentoo, Slackware, and MacPorts.
2019-07-02 21:26:52 -06:00
Eric Freese
ac4f0b2418
Merge pull request #458 from zsh-users/meta/github-templates
Add issue templates
2019-07-02 21:06:21 -06:00
Eric Freese
324aad0ac9 Add issue templates
Configured through https://github.com/zsh-users/zsh-autosuggestions/issues/templates/edit
2019-07-02 21:03:58 -06:00
Eric Freese
146020d9b2
Merge pull request #454 from zsh-users/develop
v0.6.3
2019-06-24 09:13:46 -06:00
Eric Freese
0636a39b51 0.6.3 2019-06-24 09:10:42 -06:00
Eric Freese
6769c941ba Update changelog for v0.6.3 release 2019-06-24 09:10:42 -06:00
Eric Freese
371d6441c0
Merge pull request #453 from zsh-users/fixes/move-cursor-on-accept
Fix moving cursor to end of buffer when suggestion accepted
2019-06-24 07:16:35 -06:00
Eric Freese
78e4379711 Fix moving cursor to end of buffer when suggestion accepted
$max_cursor_pos in this case was not the correct value to use. It was
calculated based on the old length of the $BUFFER. After the suggestion
is accepted, we need to recalculate the new max cursor length and use it
to set the $CURSOR.

Fixes issue #452. Follow-up to issue #302 (PR #450).
2019-06-23 12:37:08 -06:00
Eric Freese
c80605595c
Merge pull request #451 from zsh-users/develop
v0.6.2
2019-06-22 16:57:19 -06:00
Eric Freese
cb52adf429 v0.6.2 2019-06-22 16:54:32 -06:00
Eric Freese
cdf6be4f06 Update readme description to reference new completion strategy 2019-06-22 16:54:03 -06:00
Eric Freese
66a6de3fb5 Update changelog for v0.6.2 release 2019-06-22 16:52:42 -06:00
Eric Freese
2498dbab75
Merge pull request #450 from zsh-users/fixes/vi-delete
Fix deleting last character in vi mode (#302)
2019-06-22 16:42:52 -06:00
Eric Freese
676aebdf44 Fix deleting last character in vi mode (#302)
Typing `d` and then `l` runs `vi-delete` and then `vi-forward-char`.  However,
by default, `vi-forward-char` is configured to accept the suggestion. So in
that case, the suggestion was being accepted and the cursor set to the end of
the buffer before the deletion was run.

The reason the user doesn't see the suggestion accepted is that `vi-delete`
doesn't finish until the movement widget is run, so we're already inside of a
`modify` when `accept` is called. `modify` unsets `POSTDISPLAY` before calling
the original widget so when we get to the accept function, `POSTDISPLAY` is
empty and thus accepting the suggestion is a no-op.

The fix is to make sure we reset the cursor to the correct place before running
the original widget.

We skip the test for versions of zsh below 5.0.8 since there was a bug in
earlier versions where deleting the last char did not work.

See http://www.zsh.org/mla/workers/2014/msg01316.html
2019-06-22 16:34:42 -06:00
Eric Freese
ec43fcfccf
Merge pull request #449 from Warkst/i416
Possible fix for #416
2019-06-22 10:56:34 -06:00
Eric Freese
f5236c4351
Merge pull request #448 from ondrej-fabry/patch-1
Update INSTALL.md
2019-06-22 10:50:17 -06:00
Eric Freese
d27983b7ca
Merge pull request #447 from zsh-users/features/without-system-module
Degrade gracefully on systems missing zsh/system module
2019-06-22 10:46:26 -06:00
Robin De Mol
d14b17fb09 Possible fix for #416
* Added a note for iTerm2 users under readme/configuration/highlight
style.

* Changed the link to the issue list under troubleshooting so that the
default filters (only open issues) are not applied.
2019-06-20 09:32:47 +02:00
Ondrej Fabry
b24b607fbf
Update INSTALL.md
- minor formatting change for better readability
2019-06-19 23:30:36 +02:00
Eric Freese
a437544cc5 Degrade gracefully on systems missing zsh/system module
When using async mode, stale background processes will not be cancelled
when a new one starts. This shouldn't cause any real issues since the
processes should eventually finish and be cleaned up anyway, and
removing the handler with `zle -F` means that stale suggestions should
never be shown.
2019-06-19 13:41:43 -06:00
Eric Freese
112dd3e3c7
Merge pull request #446 from zsh-users/develop
v0.6.1
2019-06-18 11:11:59 -06:00
Eric Freese
8a812bdfd2 v0.6.1 2019-06-18 11:04:24 -06:00
Eric Freese
f178efb847 Update changelog for v0.6.1 release 2019-06-18 11:04:04 -06:00
Eric Freese
48ffc1bf92
Merge pull request #443 from zsh-users/fixes/alias-parse-error
Prefix custom `_complete` implementation with "function" keyword
2019-06-18 07:50:07 -06:00
Eric Freese
adb02c44a2 Prefix custom _complete implementation with "function" keyword
For some reason, when `_complete` is aliased before sourcing the plugin,
zsh was blowing up with a parse error. Adding "function" keyword makes
it parse successfully.

See similar issue: https://github.com/robbyrussell/oh-my-zsh/issues/6723#issuecomment-381220834

Fixes GitHub #442
2019-06-17 22:04:31 -06:00
Eric Freese
3654b83ec0 Update license copyright year in built plugin file
Should have been committed with 19c976f
2019-06-17 21:58:31 -06:00
Eric Freese
b3b34eab49
Merge pull request #440 from zsh-users/develop
v0.6.0
2019-06-15 21:46:24 -06:00
Eric Freese
19c976f62a Update license copyright year 2019-06-15 21:40:39 -06:00
Eric Freese
3250778ce8 v0.6.0 2019-06-15 21:39:57 -06:00
Eric Freese
43ba841742 Update changelog for v0.6.0 release 2019-06-15 21:39:10 -06:00
Eric Freese
86f64c30ca
Merge pull request #420 from zsh-users/fixes/completion-newline-issues
Fixes/completion newline issues
2019-06-15 21:24:01 -06:00
Eric Freese
f543ba08c3 Fix cr/lf handling in completion strategy 2019-06-15 21:17:58 -06:00
Eric Freese
68343c8de4 Allow suggestions to suggest trailing newlines
Command substitution via $() trims trailing newlines so the old approach
to reading everything from the fd was preventing suggestions from ending
with newlines.

Found the read solution here: https://stackoverflow.com/a/15184414/154703
2019-06-15 21:17:58 -06:00
Eric Freese
e263845bed Add an extra completion to better exercise choosing first 2019-06-15 21:17:58 -06:00
Eric Freese
d94475ca1b Simplify logic to extract suggestion from between null bytes
Just remove up to and including the first null byte and after and
including the last null byte.

I also looked into using `${${(0)line}[2]}`, but it fails when `$line`
starts with a null byte, since the first split string will be empty and
thus not included in the resulting array.
2019-06-15 21:17:58 -06:00
Eric Freese
c04e015d13 Add to explanation of extra stuff after zpty -r 2019-06-15 21:17:58 -06:00
Eric Freese
e9ce05c4c1 Ensure that kill succeeds even in older buggy versions of zsh
See https://unix.stackexchange.com/a/477647/156673
2019-06-15 21:17:58 -06:00
Eric Freese
fdf4502c5c We need to autoload is-at-least for it to be available
This error was hidden inside the zpty
2019-06-15 21:17:58 -06:00
Eric Freese
7e048c3f53 Fix error that was hidden in zpty
Without the quotes, this was blowing up with:
  _zsh_autosuggest_capture_postcompletion:unset:5: not enough arguments
2019-06-15 21:17:58 -06:00
Eric Freese
2b05f5ed2d Add a comment explaining post-completion hook 2019-06-15 21:17:58 -06:00
Eric Freese
5339d2703d
Merge pull request #432 from zsh-users/features/wrap-zle-line-init
Wrap zle-line-init to support fetching suggestions on line init
2019-06-14 21:04:02 -06:00
Eric Freese
0d3bbaf8e6 Remove hard-coded ignore of zle-* widgets and add to default config
Use case suggested by @romkatv uses zle-line-init to restore buffer
after running a widget to cd up one level (GitHub #431).

As far as I can tell, the ignoring of zle-line-* was added in commit
9788c2e to support some deprecation warnings that were removed some time
ago.

The pattern was then widened in commit 0c940e7 to zle-* to fix problems
encountered when wrapping zle-isearch-update.

This commit removes the hard coded ignore of all zle-* widgets and adds
zle-* to the default list of widgets to be ignored. Users who want the
plugin to wrap zle-line-init or zle-line-finish can override the
default.
2019-06-14 16:38:28 -06:00
Eric Freese
848aa741f4 Revert "Merge pull request #439 from zsh-users/fixes/copy-earlier-word"
This reverts commit 1c3e3fd939, reversing
changes made to 733abd4af0.

This PR should have been merged to develop instead of master.
2019-06-14 13:21:27 -06:00
Henré Botha
15bcfd7126 Don't fetch suggestions after copy-earlier-word
Like {up,down}-line-or-beginning-search, this widget relies on
`$LASTWIDGET` being set to function correctly on subsequent invocations.

When asynchronous suggestions are enabled, and the widget triggers a
suggestion to be fetched, `autosuggest-suggest` will be called and
$LASTWIDGET will be set to it.
2019-06-14 13:19:07 -06:00
Eric Freese
9ceeacc797 Try to make async ^C spec less flaky
Was intermittently failing, sleep for a little longer to increase
chances of false negatives.
2019-06-14 13:19:07 -06:00
Eric Freese
1c3e3fd939
Merge pull request #439 from zsh-users/fixes/copy-earlier-word
Don't fetch suggestions after copy-earlier-word
2019-06-14 13:17:34 -06:00
Henré Botha
527fd17ffc Don't fetch suggestions after copy-earlier-word
Like {up,down}-line-or-beginning-search, this widget relies on
`$LASTWIDGET` being set to function correctly on subsequent invocations.

When asynchronous suggestions are enabled, and the widget triggers a
suggestion to be fetched, `autosuggest-suggest` will be called and
$LASTWIDGET will be set to it.
2019-06-14 12:51:27 -06:00
Eric Freese
1912726460 Try to make async ^C spec less flaky
Was intermittently failing, sleep for a little longer to increase
chances of false negatives.
2019-06-14 12:50:44 -06:00
Eric Freese
de266574d3
Merge pull request #434 from zsh-users/meta/improve-highlight-style-docs
Improve documentation for configuring highlight style
2019-05-29 01:40:20 -06:00
Eric Freese
48d04447cc
Merge pull request #433 from zsh-users/fixes/ignore-empty-max-size
Allow setting max size to empty string (GitHub #422)
2019-05-29 01:39:24 -06:00
Eric Freese
b714f6667c Improve documentation for configuring highlight style
Supersedes PR #430 and gives additional info.

https://stackoverflow.com/questions/47310537/how-to-change-zsh-autosuggestions-color
2019-05-27 14:56:19 -06:00
Eric Freese
474c577f3c Allow setting max size to empty string (GitHub #422)
Some people have gotten used to setting ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE
to an empty string rather than leaving it unset. This lets them continue
to do that without getting any warnings (e.g. "bad math expression:
operand expected at end of string").
2019-05-27 14:18:21 -06:00
Eric Freese
e9d8231ba7
Merge pull request #401 from zsh-users/features/completion-suggestions
Features/completion suggestions
2019-04-15 12:55:35 -06:00
Eric Freese
ce6ee94f30 Add spec to demonstrate bracketed-paste-magic bug workaround
Add `bracketed-paste` to list of widgets that clear the suggestion as a
workaround for GitHub #351
2019-04-15 12:47:21 -06:00
Eric Freese
e7c7efe2e2 Set options immediately after sourcing the plugin before next precmd
So that you can access defaults to e.g. add elements to an existing
array.
2019-04-15 12:46:21 -06:00
Eric Freese
733abd4af0
Merge pull request #419 from zsh-users/develop
v0.5.2
2019-04-11 10:18:26 -06:00
Eric Freese
152d2c6b31 v0.5.2 2019-04-11 10:15:46 -06:00
Eric Freese
528e338e57 Update changelog for v0.5.2 release 2019-04-11 10:15:13 -06:00
Eric Freese
c1910348c7 Implement completion suggestion strategy (#111)
Based on https://github.com/Valodim/zsh-capture-completion

`zpty -r` with a pattern seems to have some funky behavior on older
versions, giving unpredictable results

Don't use `-s` option to `zmodload`. It is not available in zsh versions
older than 5.3

If running in sync mode and a completion takes a long time, the user can
^C out of it. We need to use `always` in the strategy function or the
pty will not be destroyed in this case and the next time we go to create
it, it will fail, making the shell unusable.

User can have many different completion styles set that will modify what
they've already typed. These styles will result in suggestions that
don't match what the user has already typed. We try our best to unset
some of the more problematic ones, but add some code to fetch to
invalidate suggestions that don't match what the user's already typed.
2019-04-11 09:53:55 -06:00
Eric Freese
937d6fc241
Merge pull request #418 from zsh-users/features/manual-rebind
Allow disabling of automatic widget re-binding
2019-04-10 13:53:37 -06:00
Eric Freese
b9fee8a324 Allow disabling of automatic widget re-binding
Addresses github #411
2019-04-10 11:43:21 -06:00
Eric Freese
db290c518b cleanup: Leave max size config unset by default to match other options 2019-04-10 11:43:20 -06:00
Eric Freese
d8ba53678e cleanup: Use + param expansion flag in arithmetic context 2019-04-10 11:42:25 -06:00
Eric Freese
4cd210b70d Fix async suggestions when SH_WORD_SPLIT is set 2019-04-10 09:51:33 -06:00
Eric Freese
586b51366b
Merge pull request #417 from zsh-users/features/async-process-substitution
Refactor async mode to no longer use zpty
2019-04-10 08:06:52 -06:00
Eric Freese
e405afab29 Refactor async mode to no longer use zpty
See technique used in `fast-syntax-highlighting`:
- ca2e18bbc9
- http://www.zsh.org/mla/users/2018/msg00424.html

Also see http://www.zsh.org/mla/users/2018/msg00432.html

In async response handler:
- We only want to read data in case of POLLIN or POLLHUP. Not POLLNVAL
  or select error.
- We always want to remove the handler, so it doesn't get called in an
  infinite loop when error is nval or err.

There is an upstream bug that prevents ctrl-c from resetting the prompt
immediately after a suggestion has been fetched asynchronously. A patch
has been submitted, but a workaround for now is to add `command true`
after the exec.

See https://github.com/zsh-users/zsh-autosuggestions/issues/364
2019-04-09 14:45:22 -06:00
Eric Freese
a5dc4a8db4 Fix version in compiled plugin script 2019-04-09 14:43:48 -06:00
Eric Freese
543f2b5477 Support new zsh version 2019-04-09 14:12:35 -06:00
Eric Freese
a36a9aca44 Enable tcsetpgrp to support job control
See https://github.com/zsh-users/zsh-docker/pull/15
2019-04-09 13:14:34 -06:00
Eric Freese
cbf0e24b18
Merge pull request #415 from zsh-users/develop
v0.5.1
2019-04-03 10:58:45 -06:00
Eric Freese
f94e667f59 v0.5.1 2019-04-03 10:52:43 -06:00
Eric Freese
3ee91c731c Update changelog for v0.5.1 release 2019-04-03 10:51:48 -06:00
Eric Freese
0b13f663da
Merge pull request #413 from zsh-users/features/faster-prompts
Features/faster prompts
2019-04-02 07:39:55 -06:00
romkatv
4a82ff1ead speed up widget rebinding by removing redundant array subscripts 2019-04-01 14:56:53 -06:00
Eric Freese
f76472272e cleanup: Remove unnecessary braces 2019-04-01 14:36:31 -06:00
Eric Freese
50579b3371 Move widget definitions inside anonymous function 2018-12-21 23:20:08 -07:00
Eric Freese
66b842579a
Merge pull request #403 from okdana/dana/typeset-g
Set global parameters with typeset -g
2018-12-21 23:19:23 -07:00
dana
aee1b10db6 Avoid warn_create_global warnings 2018-12-19 13:38:06 -06:00
Eric Freese
ebc2c07ac8
Merge pull request #402 from zsh-users/fixes/autocd-tab-completion
Respect user's set options when running original widget
2018-12-17 17:59:06 -07:00
Eric Freese
e937e89267 Respect user's set options when running original widget
Fixes GitHub #379
2018-12-16 21:13:02 -07:00
Eric Freese
11251d97ca Merge branch 'master' into develop 2018-12-16 20:50:16 -07:00
Eric Freese
41657e3565 Revert async process substitution & completion strategy
They're not quite ready. Keep them on a feature branch for now.
2018-12-16 20:49:06 -07:00
Eric Freese
70f36c007d Finish renaming "default" strategy to "history" 2018-11-24 15:07:08 -07:00
Eric Freese
a7f0106b31
Merge pull request #393 from zsh-users/releases/v0.5.0
Releases/v0.5.0
2018-11-24 10:00:59 -07:00
Eric Freese
286656635c v0.5.0 2018-11-24 09:56:52 -07:00
Eric Freese
0d994d4732 Update changelog for v0.5.0 release 2018-11-24 09:56:52 -07:00
Eric Nielsen
9e4d3c337f Don't overwrite config with default values
otherwise users are obliged to set the config values *after* sourcing
the plugin. They're not able to do it before. Also, re-sourcing the
plugin will reset the values to the defaults again.

See zimfw/zimfw#301

Fixes #335
2018-11-24 09:56:52 -07:00
Eric Freese
f0f1332e6b Add after_sourcing hook for tests
Is executed immediately after sourcing the plugin
2018-11-24 09:56:52 -07:00
Eric Freese
a78ea16c50 Support fallback strategies by setting array in config 2018-11-24 09:56:30 -07:00
Eric Freese
62f5f14f2f default => history 2018-11-24 09:56:00 -07:00
Eric Freese
4540304fa0 Reset opts in some functions affected by GLOB_SUBST
Should fix GitHub #334
2018-11-19 15:15:48 -07:00
Eric Freese
df6f6f9ff4 Add install directions for Antigen 2018-11-19 15:15:48 -07:00
Eric Freese
4097d6e0ae Support widgets starting with dashes (ex: -a-widget)
Fixes #337
2018-11-19 15:15:48 -07:00
Eric Freese
822a1f30e0 Async is less reliable in zsh versions < 5.0.8
`stty` occasionally hangs (always in CircleCI) inside the async pty.

Disable the tests for now until we can figure out and fix/workaround
this issue.
2018-11-19 15:15:48 -07:00
Eric Freese
0f80f9511d Fix handling of newline + carriage return in async pty (#333) 2018-11-19 15:15:48 -07:00
Eric Freese
4838222dde Merge branch 'master' into develop 2018-11-18 22:32:17 -07:00
Eric Freese
35c286de9a
Merge pull request #390 from zsh-users/features/no-overwrite-config
Features/no overwrite config
2018-11-18 22:19:31 -07:00
Eric Freese
be6b22b864 Add info to the readme about docker testing image 2018-11-18 21:35:52 -07:00
Eric Freese
69d7fa14d3 Build docker image for running tests
Published at `ericfreese/zsh-autosuggestions-test`.

Contains:
- Ruby 2.5.3
- Supported zsh versions 4.3.11 through 5.6.2
- Test ruby dependencies

Also updates Circle CI config to use built docker image.
2018-11-18 21:11:35 -07:00
Eric Nielsen
e61442161e Don't overwrite config with default values
otherwise users are obliged to set the config values *after* sourcing
the plugin. They're not able to do it before. Also, re-sourcing the
plugin will reset the values to the defaults again.

See zimfw/zimfw#301

Fixes #335
2018-11-18 12:39:23 -07:00
Eric Freese
4b28d92e01 Add after_sourcing hook for tests
Is executed immediately after sourcing the plugin
2018-11-10 14:55:13 -07:00
Eric Freese
b512a1b040 Merge branch 'master' into develop 2018-11-10 13:43:47 -07:00
Eric Freese
affe7c687e Run circle-ci upgrade script
From: https://raw.githubusercontent.com/CircleCI-Public/circleci-config-generator/9979b712033a072c3135aafb3c06e252c4e791f1/cci-config-generator.sh
2018-11-10 13:11:25 -07:00
Eric Freese
fa5d9c0ff5
Merge pull request #360 from zsh-users/fixes/glob-subst-bad-pattern
Reset opts in some functions affected by GLOB_SUBST
2018-07-17 22:26:55 -07:00
Eric Freese
681ffc7b28 Reset opts in some functions affected by GLOB_SUBST
Should fix GitHub #334
2018-07-13 22:16:53 -06:00
Eric Freese
b8bf86f6ab
Merge pull request #359 from zsh-users/fixes/async-bad-file-descriptor
Fixes/async bad file descriptor
2018-07-13 20:50:31 -07:00
Eric Freese
7ab2124904 Kill async process by id when job control disabled 2018-07-13 21:48:25 -06:00
Eric Freese
88fe824ddf Add some error handling to async response handler
We only want to read data in case of POLLIN or POLLHUP. Not POLLNVAL or
select error.

We always want to remove the handler, so it doesn't get called in an
infinite loop when error is nval or err.

In zsh source, see main zle event loop in zle_main.c raw_getbyte
function.
2018-07-13 11:26:57 -06:00
Eric Freese
93877f6b76 We also need to remove the handler when cancelling async request
Should fix GitHub #353
2018-07-13 11:25:59 -06:00
Eric Freese
0ee5b0a5c9 Completion strategy no longer requires zutil module 2018-07-02 22:38:20 -06:00
Eric Freese
bd1fd97738 Cleanup unused async pty name 2018-07-02 22:38:20 -06:00
Eric Freese
ebaf409002
Merge pull request #355 from amehmeto/patch-1
Update INSTALL.md
2018-07-02 20:59:14 -06:00
amehmeto
2d0ae6044c
Update INSTALL.md
I lost myself in the internet abyss because of this imprecision. It might be helpful for the new noob trying to install that great tweak. :)
2018-07-03 04:25:20 +02:00
Eric Freese
106bf02d49
Merge pull request #350 from zsh-users/features/improved-completion-suggestions
Improve completion suggestions
2018-07-02 12:28:39 -06:00
Eric Freese
f1c3b98774 Only capture completions at the end of the buffer.
To prevent the suggestion from not starting with the buffer string.

Example:

`ls / /[cursor left][cursor left]b`

Before the patch, suggests `ls /b /ls /bin/ /`

After the patch, suggests `ls /b /bin/`.

https://github.com/zsh-users/zsh-autosuggestions/issues/343#issuecomment-401675712
2018-07-02 12:25:20 -06:00
Eric Freese
4869a757c8 Ensure we always destroy the zpty
If running in sync mode and a completion takes a long time, the user can
^C out of it. Without this patch, the pty will not be destroyed in this
case and the next time we go to create it, it will fail, making the
shell unusable.
2018-07-02 12:25:20 -06:00
Eric Freese
302bd7c059 Setup zshexit hook immediately in both sync/async cases 2018-07-02 12:25:20 -06:00
Eric Freese
245f5d2ba2 Improve completion suggestions
Just insert the first completion directly into the buffer and read the
whole buffer from the zpty.
2018-07-02 12:25:20 -06:00
Martin Väth
8ae0283c90 Do not rely on implicit NULLCMD=cat 2018-07-02 12:21:49 -06:00
Eric Freese
07b37fd9ce
Merge pull request #349 from zsh-users/features/antigen-install-directions
Add install directions for Antigen
2018-07-01 01:54:01 -06:00
Eric Freese
7c83775bc7
Merge pull request #348 from zsh-users/fixes/no-zpty
Fixes/no zpty
2018-06-30 18:07:06 -06:00
Eric Freese
e97d132b3b Add install directions for Antigen 2018-06-30 17:15:31 -06:00
Eric Freese
c0315e96d8 Don't use -s option to zmodload
It is not available in zsh versions older than 5.3
2018-06-30 16:54:33 -06:00
Eric Freese
5529102afc zpty module is only needed for completion strategy 2018-06-30 15:09:24 -06:00
Eric Freese
dad6be4d5e Remove unused feature detection
Not needed after move away from zpty for async
2018-06-30 15:05:37 -06:00
Eric Freese
7d968869e3 Return if no completion found 2018-06-30 15:03:14 -06:00
Eric Freese
8593624996
Merge pull request #330 from zsh-users/features/completion-suggestions
Features/completion suggestions
2018-06-30 14:35:50 -06:00
Eric Freese
1ec43c7291 Fix error when single quote entered into buffer
Error looked something like:

```
% echo 'f(zpty):8: unmatched '
_zsh_autosuggest_capture_completion:zpty:9: no such pty command: zsh_autosuggest_completion_pty
_zsh_autosuggest_capture_completion:zpty:14: no such pty command: zsh_autosuggest_completion_pty
_zsh_autosuggest_capture_completion:zpty:21: no such pty command: zsh_autosuggest_completion_pty
```

According to `man zshmodules`, the args to `zpty` are "concatenated with
spaces between, then executed as a command, as if passed to the eval
builtin." So we need to escape the `$` so that `$1` is passed to eval
instead of the value of `$1`.
2018-06-29 22:08:33 -06:00
Martin Väth
43a011026f Do not leak global variables REPLY and strategy
https://github.com/zsh-users/zsh-autosuggestions/issues/341
2018-06-18 16:39:48 -06:00
Eric Freese
cd81522b30 Attempt to kill async worker process when new request comes in
See http://www.zsh.org/mla/users/2018/msg00432.html
2018-06-12 23:45:29 -06:00
Eric Freese
4a268da1df Fix readme- async no longer uses zpty 2018-06-11 02:39:00 -06:00
Eric Freese
d7171232c3 Merge branch 'develop' into features/completion-suggestions 2018-06-11 02:34:24 -06:00
Eric Freese
faf0f9a698
Merge pull request #338 from zsh-users/fixes/async-refactor
Refactor async mode to no longer use zpty
2018-06-11 02:25:12 -06:00
Eric Freese
9cb0101512 Refactor async mode to no longer use zpty
See technique used in `fast-syntax-highlighting`:
- ca2e18bbc9
- http://www.zsh.org/mla/users/2018/msg00424.html
2018-06-11 02:12:47 -06:00
Eric Freese
b0ffc34fb8 completion should be a local var 2018-06-10 23:35:22 -06:00
Eric Freese
4e466f0e4e Support widgets starting with dashes (ex: -a-widget)
Fixes #337
2018-06-10 22:39:58 -06:00
Eric Freese
bcbdad83e9 Support fallback strategies by setting array in config 2018-06-06 22:03:56 -06:00
Eric Freese
949c374195 Fix completion strategy on older versions of zsh
`zpty -r` with a pattern seems to have some funky behavior on older
versions, giving unpredictable results
2018-05-26 15:42:50 -06:00
Eric Freese
973205005c Add spec for completion strategy 2018-05-26 15:42:50 -06:00
Eric Freese
7d19f8f9b2 Rename default spec to history spec 2018-05-26 15:35:29 -06:00
Eric Freese
cf458d2a3b Fix completion suggestions when compinit is not enabled
Need to make sure compinit is called in the pty or the shell hangs
2018-05-26 15:35:29 -06:00
Eric Freese
3dbd9afaec Fix completion strategy killing other pty's
Only a problem in synchronous mode
2018-05-26 15:35:29 -06:00
Eric Freese
6ffaec725a Allow completion suggestions from current shell
The `zsh -f` running in the PTY doesn't know about the non-exported
variables and functions defined in the original shell, thus can't make
suggestions for them. Run local functions in the PTY instead of a new
`zsh` process.

We have to handle things differently based on whether zle is active or
not (async vs. sync mode).
2018-05-26 15:35:29 -06:00
Eric Freese
0a548c62f4 Forgot to make after small tweak 2018-05-26 15:35:29 -06:00
Eric Freese
4cca26ec84 Modify completion code to better fit our needs
Only need the first completion result
2018-05-26 15:35:29 -06:00
Eric Freese
f63afd5969 Fix async pty name option spec 2018-05-26 15:35:29 -06:00
Eric Freese
c5551daabc Default strategy now tries history first and falls back to completion 2018-05-26 15:35:29 -06:00
Eric Freese
82b08e2dc8 First pass at getting suggestions from completion engine (#111)
Uses https://github.com/Valodim/zsh-capture-completion with some slight
modifications.
2018-05-26 15:35:29 -06:00
Eric Freese
5549b68e6e Async is less reliable in zsh versions < 5.0.8
`stty` occasionally hangs (always in CircleCI) inside the async pty.

Disable the tests for now until we can figure out and fix/workaround
this issue.
2018-05-26 15:34:57 -06:00
Eric Freese
63789e96b5 Fix handling of newline + carriage return in async pty (#333) 2018-05-26 14:16:00 -06:00
Eric Freese
d7c796719e
Merge pull request #332 from zsh-users/develop
v0.4.3
2018-05-21 11:40:10 -06:00
Eric Freese
aa0b10db44 v0.4.3 2018-05-21 11:38:41 -06:00
Eric Freese
72ccee33b4 Pull out separate doc for installation instructions 2018-05-21 11:35:26 -06:00
Eric Freese
c113e49fe2 Update license copyright year 2018-05-21 10:52:41 -06:00
Eric Freese
3b39b9561c Merge branch 'master' into develop 2018-05-21 10:47:20 -06:00
Eric Freese
b003b2238a Update changelog for v0.4.3 release 2018-05-21 10:46:03 -06:00
Eric Freese
df5fb858aa Destroy old pty even if it's no longer running (#249)
For unknown reasons, the pty will occasionally quit running. In these
cases, we still want to remove it so that a fresh one can be created. We
don't actually need this check because error messages from `zle` and
`zpty` are redirected to /dev/null.

One sure way to kill all currently running pty's is to run `exit` in a
subshell. Even without zsh-autosuggestions loaded, the following works:

    % zmodload zsh/zpty
    % zpty -b foo cat
    % zpty -b bar cat
    % zpty
    (31689) bar: cat
    (31666) foo: cat
    % $(exit)
    % zpty
    (finished) bar: cat
    (finished) foo: cat
2018-05-15 13:55:37 -06:00
Eric Freese
726bc4eb5c Create general spec for async behavior 2018-05-15 13:42:18 -06:00
Harm te Hennepe
59c72c6805 Don't break kill ring rotation 2018-05-15 12:54:09 -06:00
Eric Freese
393f7b8bb9 Fix vi-mode partial-accept
Issue #188. PR #324.

Thanks to @toadjaune and @IngoHeimbach.
2018-05-15 11:44:42 -06:00
Eric Freese
42f5a06f7f Need to reset the POSTDISPLAY if exiting early
Specific case where this matters is following:

Be in vi insert mode with some text in the buffer and the cursor at the
end of the buffer. Press `esc` to trigger `vi-cmd-mode widget`, then
before the cursor moves (KEYTIMEOUT), press `h` to trigger
`vi-backward-char` widget. When `vi-cmd-mode` original widget exits,
KEYS_QUEUED_COUNT will be non-zero and the suggestion will be lost.
2018-05-15 11:44:42 -06:00
Eric Freese
51fef255da Add method to connect terminal to tmux session during tests
Useful with `binding.pry` to inspect behavior of tests.
2018-05-15 11:44:18 -06:00
Eric Freese
19ad3ba7cd Add new 5.5.1 version of zsh to CI 2018-05-15 11:44:18 -06:00
Benjamin Denhartog
b2b9bf3b8c update arch linux installation instructions (now available via pacman)
closes #328
2018-05-14 10:43:45 -06:00
Eric Freese
67a364bc17
Merge pull request #321 from babaorum/fix/documentation/oh-my-zsh-install
make Oh my zsh install works without ZSH_CUSTOM defined
2018-04-17 15:00:46 -06:00
babaorum
afc14f79cc make Oh my zsh install works without ZSH_CUSTOM defined 2018-04-16 22:37:54 +02:00
Eric Freese
60aff2d944 Remove unused local $suggestion variable 2018-03-27 14:51:37 -06:00
Eric Freese
6dfe9c8cd8
Merge pull request #319 from zsh-users/fixes/async_history
Don't fetch suggestions after [up,down]-line-or-beginning-search
2018-03-23 16:15:56 -06:00
Eric Freese
3136700ccf Don't fetch suggestions after [up,down]-line-or-beginning-search
These widgets rely on `$LASTWIDGET` being set to restore the cursor
position. When asynchronous suggestions are enabled, and the widget
triggers a suggestion to be fetched, `autosuggest-suggest` will be
called and $LASTWIDGET will be set to it.
2018-03-23 16:08:11 -06:00
Eric Freese
2202ed7bac
Merge pull request #304 from okdana/dana/no-beep
Avoid ringing bell when accepting suggestions
2018-01-16 14:11:06 -07:00
dana
c978004c0e ..._invoke_original_widget: Return 0 when given no arguments
`_zsh_autosuggest_widget_accept()` (&al.) passes this function's return status
on, and ZLE rings the bell if it's >0. Not having an original widget isn't an
error condition, so always returning 0 here should be OK to avoid the bell

Fixes #228
2018-01-16 14:10:29 -06:00
Eric Freese
c7d4a85031
Merge pull request #299 from zsh-users/develop
v0.4.2
2017-12-06 08:31:52 -07:00
Eric Freese
15931f04ff v0.4.2 2017-12-06 08:30:12 -07:00
Eric Freese
9f1046727a
Merge pull request #298 from zsh-users/fixes/support_older_versions
Fixes/support older versions
2017-12-06 08:27:18 -07:00
Eric Freese
f462410b3c Add zsh version requirements to readme 2017-12-06 08:21:27 -07:00
Eric Freese
4ea825faf8 Fix #247 and #248 without using (b) flag
To support older versions of zsh (< 5.0.8).

We were missing the EXTENDED_GLOB option that allows use of `(#m)` flag.
2017-12-06 08:09:14 -07:00
Eric Freese
a1babef972 Revert "Simplify escaping of pattern and fix match_prev_cmd strategy"
This reverts commit 7f8ff2867c.
2017-12-06 08:08:53 -07:00
Eric Freese
be8bba6f38 Run CI on prominent versions of zsh back to 4.3.11
RHEL6 bundles v4.3.11
Ubuntu 14.04 and Amazon Linux bundle v5.0.2
2017-12-06 07:45:45 -07:00
Eric Freese
dda220f140
Merge pull request #295 from zsh-users/develop
v0.4.1
2017-11-28 10:14:41 -07:00
Eric Freese
9f9237ab8a v0.4.1 2017-11-28 10:07:49 -07:00
Eric Freese
29257230fe Add missing issue/pr numbers from last version 2017-11-28 10:07:49 -07:00
Kaleb Elwert
940e10a691 Fix conditionals to use [[ and (( rather than [
This fixes a small issue in src/widgets.zsh which makes it so if you
alias [ to g[ (as is done in prezto if the gnu-utility module is loaded)
autosuggestions would fail.

The documentation for GNU test mentions that -o and -a should be avoided
if possible because it's not very clear. Also, with zsh and [[ -o
actually tests if an option is set, which makes this option even more
confusing.
2017-11-27 08:31:41 -07:00
Eric Freese
9f1f322979 Update comment about KEYS_QUEUED_COUNT support
Now that patch has released
2017-09-27 15:04:42 -06:00
Eric Freese
680ce21f26 Merge pull request #275 from zsh-users/fixes/warn_nested_var_opt
Use typeset -g to avoid warnnestedvar warnings
2017-09-27 15:02:15 -06:00
Eric Freese
256293cbb6 Use typeset -g to avoid warnnestedvar warnings
Fixes github issue #271
2017-09-27 13:24:06 -06:00
Eric Freese
977e70e21b Merge pull request #270 from ssiegel/fix-match_prev_cmd
Simplify escaping of pattern and fix match_prev_cmd strategy
2017-09-26 08:33:14 -06:00
Eric Freese
218acf2fbe Merge branch 'fixes/match_prev_cmd_special_chars' into develop 2017-09-26 08:30:43 -06:00
Eric Freese
0681a1c121 Remove flaky test that doesn't really matter that much
Seems like this would happen on some machines but not on others. Not
sure exactly what's going on, but this is such an edge case I'm just
going to remove the test.
2017-09-26 08:23:00 -06:00
Eric Freese
9e3f1bd359 Use https protocol instead of git in README instructions
https should work more broadly for folks
2017-09-26 07:56:29 -06:00
Eric Freese
ae4c344e82 Merge pull request #267 from isaacwhanson/fixes/match_prev_cmd_special_chars
escape pattern-matching chars on $prefix for match_prev_cmd strategy
2017-09-12 09:19:17 -06:00
Stefan Siegel
7f8ff2867c Simplify escaping of pattern and fix match_prev_cmd strategy
Maybe this is also a fix for #247, #248 and #258. Supersedes #267.

Testcase:
Using match_prev_cmd strategy and with these lines in history:
echo '1^'
echo '2^'
echo '1^'

type:
echo       (unexpected suggestion echo '1^' instead of echo '2^')
echo '1^1  (wrong suggestion echo '1^1echo '1^')
echo '1^#  (error "bad math expression")
2017-09-10 04:35:19 +02:00
Eric Freese
33b91a9dea Merge pull request #268 from thomas-mcdonald/patch-1
replace tabs in Rubocop config with spaces
2017-08-22 19:02:15 -06:00
Thomas McDonald
802f53a10a replace tabs in Rubocop config with spaces
YAML does not permit tabs and many parsers will error when loading a tab-indented file - http://www.yaml.org/faq.html
2017-08-20 23:36:18 +01:00
Isaac W Hanson
5e4487ed4a escape pattern-matching chars on $prefix for match_prev_cmd strategy 2017-08-18 16:00:42 -04:00
Eric Freese
9e110406fa Add test for special characters with match_prev_cmd strategy
Github #247 and #258
2017-08-18 11:18:07 -06:00
Alexander Neumann
1915e28882 Add 'emacs-forward-word'
This commit adds the 'emacs-forward-word' widget to the list of partial
accept widgets.
2017-08-18 11:14:21 -06:00
Eric Freese
d6d9a46981 Merge pull request #261 from alonhar/patch-1
Update README.md
2017-07-30 09:30:48 +02:00
Alon Harel
706499838c Update README.md 2017-07-24 21:19:07 +03:00
Eric Freese
e304365745 Merge pull request #256 from sumnerevans/patch-1
Added installation instructions for AUR, Homebrew
2017-07-08 09:58:35 +02:00
Sumner Evans
4e72f7a91e Added installation instructions for AUR, Homebrew 2017-07-07 09:17:46 -06:00
Eric Freese
2cb6eb6e29 Merge pull request #218 from zsh-users/develop
v0.4.0
2017-05-10 15:18:07 -06:00
Eric Freese
14179d869d Bump version 2017-05-10 15:05:43 -06:00
Eric Freese
281ed9bbf7 v0.4.0 changelog updates 2017-05-10 15:05:43 -06:00
Eric Freese
83129dd796 Make asynchronous suggestions disabled by default
While they are still experimental
2017-04-14 08:48:54 -06:00
Eric Freese
40b96f6cfd Merge pull request #223 from zsh-users/fixes/bpm_async_fix
Fixes/bpm async fix
2017-03-05 12:59:19 -05:00
Eric Freese
a2f0ffb122 Enabling suggestions should not fetch a suggestion if buffer is empty 2017-03-05 12:53:13 -05:00
Eric Freese
7d4a1d9a4a Add enable/disable/toggle widgets to disable suggestion functionality
[GitHub #219]

Intended to be helpful for folks using bracketed-paste-magic and other
widgets that use `zle -U`.
2017-03-03 18:43:17 -05:00
Eric Freese
e1959d0f61 Put in a general fix for #219 - Handling input from zle -U
Depends on patch to ZSH from workers/40702:

  http://www.zsh.org/mla/workers/2017/msg00414.html
2017-03-03 18:43:17 -05:00
Eric Freese
c52c428793 Fix issues with widgets wrapped by other plugins
Puts in a better fix for #126 and related issues.
2017-03-03 18:43:10 -05:00
Eric Freese
ea505b01e5 Add a spec for unlisted widgets fetching a new suggestion 2017-03-03 18:43:10 -05:00
Eric Freese
502fb4a174 Make tmux_socket_name public so you can access easily from binding.pry
Can attach while tests are stopped with `tmux -L <socket_name> attach`
2017-03-03 18:43:10 -05:00
Eric Freese
ce362248fa Use pry-byebug instead of pry for more functionality 2017-03-03 18:43:10 -05:00
Eric Freese
cb93366d0e Merge pull request #221 from zsh-users/circle_ci_setup
Set up Circle CI
2017-02-26 14:36:15 -07:00
Eric Freese
39762ecd97 Set up circle ci 2017-02-26 14:26:41 -07:00
Eric Freese
468b7403e9 Test should be passing block to RSpec wait_for
Fixes flaky test
2017-02-26 14:18:22 -07:00
Eric Freese
c9a51e0c4c Handle dashes at the beginning of commands 2017-02-18 16:51:53 -07:00
Eric Freese
48a21bf79e [cleanup] Remove an extra newline 2017-02-18 11:27:55 -07:00
Eric Freese
4afbbbadda We only need to run the feature detection if starting async 2017-02-18 11:25:27 -07:00
Eric Freese
e3fa4e4904 Don't do anything but re-bind widgets on each precmd
There's no need to re-run feature detection or async_start on every
precmd. Just do those once.
2017-02-18 11:15:53 -07:00
Eric Freese
2cd99e64b7 Add a test for modifying widget list vars after sourcing plugin 2017-02-18 11:15:53 -07:00
Eric Freese
c70d685d15 Clean up widget list spec 2017-02-18 11:12:10 -07:00
Eric Freese
255359dbb8 Use += to be a bit more true to the spec language 2017-02-18 10:35:30 -07:00
Eric Freese
4321fc097c We need to bind on every precmd to ensure we wrap other wrappers
Specifically, highlighting breaks if our widgets are wrapped by z-syn-h
widgets.
2017-02-17 23:20:04 -07:00
Eric Freese
75e850577d Gracefully handle being sourced multiple times
Should fix #126
2017-02-17 23:19:55 -07:00
Eric Freese
a0fcd81ce1 Destroy zpty on load if it already exists 2017-02-17 22:47:28 -07:00
Eric Freese
39ca3dac45 Use a different name for feature detection zpty
So that it doesn't conflict when the file is sourced again
2017-02-17 22:07:48 -07:00
Eric Freese
dcce973287 Remove support for long-deprecated options
These options have been deprecated for over a year.
2017-02-17 18:45:46 -07:00
Christian Höltje
0c940e70f2 Don't bind any zle-* methods
It seems like all the zle-* methods are special and shouldn't be
monkeyed with.

Specifically `zle-isearch-update` and friends. Binding that widget
caused `history-incremental-pattern-search` to stop working.

Fixes zsh-users/zsh-syntax-highlighting#387
2017-02-17 18:32:52 -07:00
Eric Freese
a109f52fe4 Merge pull request #180 from zsh-users/features/async
Asynchronous suggestions
2017-02-17 18:28:54 -07:00
Eric Freese
23ef16c297 Do not show suggestions if the buffer is empty 2017-02-17 18:26:34 -07:00
Eric Freese
938144530c Fix tests 2017-02-17 16:01:07 -07:00
Eric Freese
c4bfd8e2c6 Need to prevent zpty feature detection from HUPing existing zptys 2017-02-17 15:51:50 -07:00
Eric Freese
c959408305 Only wait a max of 2 seconds for content to match after clearing screen 2017-02-17 15:33:09 -07:00
Eric Freese
06fca77ffb Readme updates for v0.4.0 2017-02-16 20:12:04 -07:00
Eric Freese
9feac573c9 Do not show any error output from async zpty server process 2017-02-16 19:27:32 -07:00
Eric Freese
ed8056c5e8 Lots of async changes 2017-02-16 19:19:30 -07:00
Eric Freese
38eb7cdafd Update license date 2017-02-16 19:07:41 -07:00
Eric Freese
64e7ec5bf8 Rename internal term session method 2017-01-29 10:43:20 -07:00
Eric Freese
98f926d53d Clean up TerminalSession constructor a bit 2017-01-29 10:43:00 -07:00
Eric Freese
51e8755634 TerminalSession methods return self to support chaining 2017-01-29 10:42:28 -07:00
Eric Freese
5151adfe40 Make TerminalSession#clear block until the screen is cleared 2017-01-29 10:40:05 -07:00
Eric Freese
2c465a932a Rename async pty name config var 2017-01-29 10:39:07 -07:00
Eric Freese
e3eb286ea2 Lots of little async cleanups 2017-01-27 15:18:26 -07:00
Eric Freese
c3425870f1 Wait for the terminal.clear to go through before continuing
Prevents some flakiness in tests
2017-01-27 14:07:06 -07:00
Eric Freese
89dd69d517 Add pry gem for debugging support 2017-01-27 14:06:37 -07:00
Eric Freese
40bb2e7804 little cleanup 2017-01-26 17:00:56 -07:00
Eric Freese
16666da488 Handle versions of zsh where zpty does not set REPLY to fd of opened pty
Based on e702ec4697/async.zsh (L400-L406)
2017-01-26 16:50:19 -07:00
Eric Freese
f33b605a63 Move async initialization into start function to keep in one place 2017-01-26 16:40:34 -07:00
Eric Freese
78ba07179a Add feature detection
Checks whether `zpty` gives a file descriptor, which was not the case in
older versions of zsh.

Based on a4b2f81c96/async.zsh (L395-L401)
2017-01-26 16:40:34 -07:00
Eric Freese
3f57198d07 Only bind widgets once, on initial sourcing 2017-01-26 16:23:27 -07:00
Eric Freese
2dbd261989 Allow configuring of zsh binary to run integration tests against 2017-01-26 16:04:46 -07:00
Eric Freese
6c5cd42331 Go back to tracking last pid because kill %1 didn't seem to be working 2017-01-25 00:00:53 -07:00
Eric Freese
54e1eee924 Optimize case where manually typing in a suggestion 2017-01-25 00:00:13 -07:00
Eric Freese
21d9eda5dd Wrap suggestion fetch command in parens to actually run in background 2017-01-24 23:59:38 -07:00
Eric Freese
50e6832b8c Escape the prefix passed into the match_prev_cmd strategy 2017-01-24 23:06:41 -07:00
Eric Freese
0305908adf Revert fc usage in calculating suggestion
As far as I know, `fc` makes it impossible to tell whether history items
used an actual newline character or the string "\n". Pulling from the
`$history` array gives a more accurate representation of the actual
command that was run.
2017-01-24 23:04:07 -07:00
Eric Freese
8e06a54b1c Add test for string with "\n" in it 2017-01-24 22:49:21 -07:00
Eric Freese
b3208b08af Pass the chosen strategy into the suggestion server pty 2017-01-24 22:48:30 -07:00
Eric Freese
ab2742537f Quote the suggestion to support sh_split_word option 2017-01-24 22:27:47 -07:00
Eric Freese
e5a5b0c1e0 Output only newlines in the pty 2017-01-24 22:27:09 -07:00
Eric Freese
0337005eb0 Disable word splitting while reading to preserve whitespace 2017-01-24 21:59:22 -07:00
Eric Freese
b530b0c996 Use zpty -r with pattern matching to fetch suggestion 2017-01-24 20:01:30 -07:00
Eric Freese
5c891afd48 Reset zsh options inside pty (from zsh-async) 2017-01-24 20:01:27 -07:00
Eric Freese
e33eb570c4 Send only the prefix to the suggestion server 2017-01-24 20:01:11 -07:00
Eric Freese
fba20b042e Use %1 instead of tracking pid 2017-01-24 20:00:50 -07:00
Eric Freese
0308ed797e Rename worker to server 2017-01-24 20:00:34 -07:00
Eric Freese
e72c2d87e5 add a bunch of comments 2017-01-24 19:53:59 -07:00
Eric Freese
ab8f295225 First pass at async functionality 2017-01-24 19:45:11 -07:00
Eric Freese
debbffc79a Add rspec test around accepting suggestions 2017-01-19 22:38:19 -07:00
Eric Freese
4850119887 Add separate test task for RSpec 2017-01-19 22:38:19 -07:00
Eric Freese
c22ab0e399 Implement suggestion integration tests in RSpec + tmux 2017-01-19 22:38:19 -07:00
Eric Freese
07a6768fcb Add TerminalSession helper for managing a tmux session 2017-01-19 22:38:19 -07:00
Eric Freese
e6591d5de0 Add RSpec for high-level integration testing 2017-01-19 22:33:17 -07:00
Eric Freese
af671fb406 Add ruby settings to editor config 2017-01-19 01:03:24 -07:00
Eric Freese
fedc22e9bb Merge pull request #169 from zsh-users/develop
v0.3.3
2016-10-17 07:45:49 -06:00
Eric Freese
9cfaf5d342 v0.3.3 2016-10-17 07:45:09 -06:00
Eric Freese
9333f0653f Update changelog for v0.3.3 2016-10-17 07:43:56 -06:00
Eric Freese
b377c39d0e Only fetch a new suggestion if buffer has changed 2016-07-31 20:10:22 -06:00
Eric Freese
a44aa59321 Remove unnecessary reset of POSTDISPLAy 2016-07-31 20:09:26 -06:00
Eric Freese
25f4afb058 Add ZSH_AUTOSUGGEST_IGNORE_WIDGETS array 2016-07-31 19:35:30 -06:00
Eric Freese
472394681e Merge pull request #178 from lbolla/issue141-develop
Disable autosuggest if buffer is too large
2016-07-18 10:28:45 -06:00
Lorenzo Bolla
a9c8efa048 Update README 2016-07-18 16:06:50 +01:00
Lorenzo Bolla
cdf56a3305 Include result of make 2016-07-18 10:56:21 +01:00
Lorenzo Bolla
2450c95d8a Rename and document new config var 2016-07-18 10:55:19 +01:00
Lorenzo Bolla
7b81eb79b8 Disable autosuggest if buffer is too large
Make buffer max size configurable, defaulted to infinity
2016-07-18 08:56:00 +01:00
Eric Freese
63816c5da8 Fix #164: Use fc builtin instead of $history array for lookup
According to a few tests, the `fc` builtin appears to be quite a bit
faster than searching through the `$history` associative array when
dealing with large history files (500K+).
2016-06-10 13:52:24 -06:00
Eric Freese
b4b3a82ee3 Fix #168 and #130: Escape tildes when fetching suggestions 2016-06-10 13:51:20 -06:00
Eric Freese
85ea943789 Merge pull request #163 from tsdh/develop
Document caveats of match_prev_cmd strategy
2016-05-28 13:34:00 -06:00
Tassilo Horn
ca70612d3c Document caveats of match_prev_cmd strategy
This strategy relies on the history being exactly in the order in which
commands have been entered.  Therefore, options like suppressing
duplicates or expiring duplicates first will lead to unexpected
suggestions.
2016-05-28 21:23:35 +02:00
Eric Freese
62cdba4e0f Merge pull request #142 from zsh-users/v0.3.x
v0.3.2
2016-05-28 08:28:18 -06:00
Eric Freese
cce68de46d v0.3.2 2016-05-28 08:27:08 -06:00
Eric Freese
4a2d9f9049 Fix Makefile to not create symbolic link after PR #156 was merged 2016-05-28 08:26:24 -06:00
Eric Freese
7c688ec20c Add note to readme about PRs going to develop branch 2016-05-28 08:23:53 -06:00
Eric Freese
96eb0fae77 Changelog updates for v0.3.2 2016-05-28 08:18:52 -06:00
Eric Freese
5e5bfdb659 Merge pull request #156 from adamkruszewski/v0.3.x
Adjust plugin.zsh file to run on zsh 5.1 in mSYS2.
2016-05-12 08:53:20 -06:00
adamkruszewski
0a6c34947c Adjust plugin.zsh file to run on zsh 5.1 in mSYS2. 2016-05-11 17:02:41 +02:00
Eric Freese
e87bc74654 Fix 118: Clear suggestion before original widget to fix completions
See PR #149
2016-04-25 14:42:09 -06:00
Eric Freese
964773aa75 Use array indices for forward compatibility
See issue #152
2016-04-25 14:26:37 -06:00
Eric Freese
945c660856 Fix #152 by escaping widget names inside evals
Solves problems when dealing with widget names with irregular
characters such as those that come from `opp.zsh`.
2016-04-25 14:26:35 -06:00
Eric Freese
011d8bdfd1 Refactor to remove prev cmd function and simplify escaping 2016-04-25 14:19:26 -06:00
Eric Freese
c5f57da2b8 Pull duplicated test logic from strategies into single test file 2016-04-22 14:14:29 -06:00
Eric Freese
c477db2696 Remove unused test variables from Makefile 2016-04-15 13:41:41 -06:00
Eric Freese
d7001f2c34 Fix readme test script reference. 2016-04-15 13:40:18 -06:00
Eric Freese
6d6e7820f3 Fix #143: Add vi-add-eol to list of accept widgets. 2016-04-15 13:37:50 -06:00
Eric Freese
9bef50fac1 Merge pull request #140 from zsh-users/fixes/bound_widget_return_code
Keep track of return value from original widget (#135)
2016-04-14 11:18:01 -06:00
Eric Freese
1d4f7e157e Keep track of return value from original widget (#135) 2016-04-06 17:13:04 -06:00
Eric Freese
2acf25e065 Formatting 2016-03-15 09:24:13 -06:00
Eric Freese
ba7109169d Clean up tests with setUp and tearDown functions 2016-03-15 09:05:55 -06:00
Eric Freese
a28e72e84a Test Runner now supports running specific tests and choosing zsh bin 2016-03-15 09:04:17 -06:00
Eric Freese
87facd9b85 bump version v0.3.1 2016-03-14 22:33:26 -06:00
Eric Freese
dc822c54f8 Fix #133 2016-03-14 21:50:04 -06:00
Eric Freese
15c5db898f Fix #137 2016-03-14 21:41:14 -06:00
Eric Freese
46d5fe174d Remove extra newline 2016-03-14 18:02:16 -06:00
Eric Freese
6c31a02892 Remove old test script 2016-03-14 17:44:24 -06:00
Eric Freese
9ec62a1a23 Split out a separate test file for each widget 2016-03-14 17:38:37 -06:00
Eric Freese
1ed9155f89 Add Suggestion Strategy section to Configuration section of Readme. 2016-03-14 17:25:09 -06:00
Eric Freese
97b51a2c57 bump version v0.3.0 2016-03-14 17:18:40 -06:00
Eric Freese
b54c8a15c6 Add changelog 2016-03-14 17:07:04 -06:00
Eric Freese
2a6d401106 Add quotes 2016-03-14 16:51:27 -06:00
Eric Freese
a314a01a6a Fix various bugs found while testing 2016-03-14 16:51:27 -06:00
Eric Freese
e5cdbb6c33 Lots of test cleanup. 2016-03-14 16:51:27 -06:00
Eric Freese
dffd9beae1 Add stub.sh submodule 2016-03-14 16:51:20 -06:00
Eric Freese
d202b32ae9 Add shunit2 submodule 2016-03-14 16:51:20 -06:00
Eric Freese
ab0f4c0bd0 Grammar and formatting 2016-03-14 16:51:20 -06:00
Eric Freese
ee6dde9ee8 Rename escape command function 2016-03-14 16:51:20 -06:00
Geza Lore
73f774bd5d Add match_prev_cmd strategy.
A new suggestion strategy 'match_prev_cmd' is available. This is a bit
more context aware variaton on the default strategy.
The suggestion will be:
- The newest history entry that matches the current prefix, AND
- Whose preceding history entry also matches the previously executed
command.

See src/strategies/match_prev_cmd.zsh for an example.
2016-03-14 16:51:20 -06:00
Geza Lore
976acc708c Fix default suggestion strategy and add testing 2016-03-14 16:51:20 -06:00
Eric Freese
83f78d0760 Add suggestion "strategy" concept with default strategy 2016-03-14 16:51:20 -06:00
Eric Freese
9df362f783 Merge pull request #125 from zsh-users/features/execute_widget
Add a widget to accept and execute the current suggestion.
2016-03-04 18:57:43 -07:00
Eric Freese
125f48c7f2 Add test for execute widget 2016-03-01 13:18:46 -07:00
Eric Freese
8c3fdea75d Call original accept-line widget when executing suggestion 2016-03-01 13:18:46 -07:00
Kordan Ou
aa597eea6d Add an autosuggest widget: autosuggest-execute. 2016-03-01 13:18:46 -07:00
Eric Freese
f0a745576f bump version v0.2.17 2016-03-01 13:16:10 -07:00
Eric Freese
8935a39e9b Remove plugin compatibility section from readme 2016-03-01 13:14:20 -07:00
Eric Freese
c7c9929490 Add zsh-history-substring-search widgets to CLEAR array by default. 2016-03-01 13:13:01 -07:00
Eric Freese
985de56f6e Update asciinema to reflect new repo 2016-02-25 13:20:21 -07:00
Eric Freese
0a42f872b8 bump version v0.2.16 2016-02-25 13:05:03 -07:00
Eric Freese
dd54925b06 Update URL references after repo move to zsh-users 2016-02-25 13:04:32 -07:00
Eric Freese
c761dc8150 bump version v0.2.15 2016-02-24 18:40:24 -07:00
Eric Freese
cc921994e6 Fix #127 by adding quotes 2016-02-24 18:35:17 -07:00
Eric Freese
0242c7eff1 Fix highlighting when sh_word_split option is enabled 2016-02-24 13:59:49 -07:00
Eric Freese
9d100f4f32 bump version v0.2.14 2016-02-23 20:12:16 -07:00
Eric Freese
ddb7284852 Fix backslash escaping problems with echo -E. 2016-02-23 20:11:56 -07:00
Eric Freese
2a5791710a bump version v0.2.13 2016-02-23 18:14:12 -07:00
Eric Freese
03fac1f0d7 Revert "Use zle -w flag to set WIDGET appropriately when calling orig widget"
This reverts commit 70438d233d.
2016-02-23 18:13:03 -07:00
Eric Freese
aa859a282d bump version v0.2.12 2016-02-23 10:37:57 -07:00
Eric Freese
f08a5a1baa [Formatting] Remove extra space in test script. 2016-02-23 10:24:35 -07:00
Eric Freese
70438d233d Use zle -w flag to set WIDGET appropriately when calling orig widget 2016-02-23 10:21:35 -07:00
Eric Freese
ba029e83d0 bump version v0.2.11 2016-02-17 13:44:52 -07:00
Eric Freese
acc129de6c Fix error when using autosuggest widgets 2016-02-17 13:44:52 -07:00
Eric Freese
aa5ceee256 Make asciinema a bit smaller. 2016-02-16 21:55:56 -07:00
Eric Freese
113ca0ad10 Add asciinema recording to README 2016-02-16 21:35:44 -07:00
Eric Freese
2b449a62f8 bump version v0.2.10 2016-02-16 20:59:31 -07:00
Eric Freese
6d25df6864 Revert usage of fc for suggestions and fix for sh_word_split.
Force field splitting on \0 to support sh_word_split option.
2016-02-16 10:51:01 -07:00
Eric Freese
0faa2b6584 bump version v0.2.9 2016-02-16 09:34:35 -07:00
Eric Freese
a2d8d91196 Actually fix suggestions when sh_split_words option is enabled. 2016-02-16 09:33:26 -07:00
Eric Freese
dd9a8789a7 bump version v0.2.8 2016-02-16 07:59:36 -07:00
Eric Freese
1b98af5b33 Fix suggestions when sh_split_words option is enabled 2016-02-16 07:57:44 -07:00
Eric Freese
45ab49d1f2 bump version v0.2.7 2016-02-15 08:46:23 -07:00
Eric Freese
41f15d5c9f Forgot a pesky backslash 2016-02-15 08:45:52 -07:00
Eric Freese
3ce1adb55d bump version v0.2.6 2016-02-15 08:31:50 -07:00
Eric Freese
2461a98857 Fix segfaults once and for all? 2016-02-15 08:31:00 -07:00
Eric Freese
76f415bf43 bump version v0.2.5 2016-02-14 08:55:20 -07:00
Eric Freese
5e419da326 Remove list of modify widgets and make 'modify' the default behavior. 2016-02-14 08:54:34 -07:00
Eric Freese
cd71081303 bump version v0.2.4 2016-02-14 01:08:21 -07:00
Eric Freese
9788c2ee49 Fix deprecation warnings. 2016-02-14 01:07:05 -07:00
Eric Freese
ebcfc46b72 Comment formatting 2016-02-14 00:29:43 -07:00
Eric Freese
b49d002888 [README] Add example of minimal .zshrc. 2016-02-13 23:53:32 -07:00
Eric Freese
266437c98a bump version v0.2.3 2016-02-13 23:47:24 -07:00
Eric Freese
51b39e210e Bound widgets now handle arguments correctly 2016-02-13 23:46:34 -07:00
Eric Freese
011f5420fc Version bump v0.2.2 2016-02-13 21:15:33 -07:00
Eric Freese
1a38fbf6a5 [README] Add note about workaround for bpm bug. 2016-02-13 21:14:59 -07:00
Eric Freese
31452887d2 [Test] Add tests widgets 2016-02-13 14:13:21 -07:00
Eric Freese
cf146b6696 [Test] Clean up highlight tests 2016-02-13 14:13:21 -07:00
Eric Freese
74197498fc [Test] Add stub.sh from ericfreese/stub.sh for stubbing/mocking. 2016-02-13 14:13:21 -07:00
Eric Freese
abe577d519 Fix build 2016-02-13 14:13:21 -07:00
Eric Freese
0ae5907294 [README] Add note about Oh My Zsh paste bug. 2016-02-13 09:59:16 -07:00
Eric Freese
03bd381112 Add .plugin file and installation instructions for Oh My Zsh (#104). 2016-02-07 15:35:54 -07:00
Eric Freese
00bd0e9125 Use add-zsh-hook to remove need to call autosuggest_start. 2016-02-07 15:35:43 -07:00
Eric Freese
48d2dc1091 Remove absolute link in readme. 2016-02-07 14:50:00 -07:00
Eric Freese
f154d25fb3 Fix typo when setting up autosuggest-clear widget. 2016-02-07 08:58:09 -07:00
Eric Freese
e91db46ce0 Add Development section to README (#106) 2016-02-07 08:52:52 -07:00
Eric Freese
28836f15c5 Test script should be a .zsh file instead of .sh 2016-02-07 08:52:34 -07:00
Eric Freese
0dd1b7febb Add Troubleshooting section to README 2016-02-07 08:52:07 -07:00
103 changed files with 3240 additions and 8402 deletions

View File

@ -8,3 +8,11 @@ indent_size = 4
[*.md]
indent_style = space
[*.rb]
indent_style = space
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2

36
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
### Describe the bug
<!-- A clear and concise description of what the bug is. -->
### To Reproduce
Steps to reproduce the behavior:
<!-- If you are not able to reproduce it by running `zsh -df` and sourcing the plugin manually, it means there that the issue is caused by something in your local config file(s). Temporarily comment out or remove sections of your config and restart `zsh` until you narrow down exactly what is causing the issue. -->
```sh
% zsh -df
% source path/to/zsh-autosuggestions.zsh
% ... # what do you do to reproduce?
```
### Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
### Desktop
- OS + distribution: <!-- e.g. Arch Linux 2019.07.01 -->
- Zsh version: <!-- `echo $ZSH_VERSION` -->
- Plugin version: <!-- or git commit hash if installed via git -->
### Additional context
<!-- Add any other context about the problem here. -->

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
### Is your feature request related to a problem? Please describe.
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
### Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
### Additional context
<!-- Add any other context or screenshots about the feature request here. -->

51
.github/workflows/integration.yml vendored Normal file
View File

@ -0,0 +1,51 @@
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
IMAGE_CACHE_PATH: /tmp/.image-cache
IMAGE_CACHE_NAME: zsh-autosuggestions-test
jobs:
determine-versions:
runs-on: ubuntu-22.04
outputs:
versions: ${{ steps.set-versions.outputs.versions }}
steps:
- uses: actions/checkout@v3
- id: set-versions
run: |
echo "versions=$(
grep "^[^#]" ZSH_VERSIONS \
| sed -E 's/(^|$)/"/g' \
| paste -sd ',' - \
| sed -e 's/^/[/' -e 's/$/]/'
)" >> $GITHUB_OUTPUT
test:
needs: determine-versions
runs-on: ubuntu-22.04
strategy:
matrix:
version: ${{ fromJson(needs.determine-versions.outputs.versions) }}
steps:
- uses: actions/checkout@v3
- name: Docker image cache
id: image-cache
uses: actions/cache@v3
with:
path: ${{ env.IMAGE_CACHE_PATH }}
key: image-cache-${{ matrix.version }}-${{ hashFiles('Dockerfile', 'install_test_zsh.sh', 'Gemfile.lock') }}
- name: Load cached docker image if available
if: ${{ steps.image-cache.outputs.cache-hit }}
run: gunzip < $IMAGE_CACHE_PATH/$IMAGE_CACHE_NAME.tar.gz | docker load
- name: Build the docker image if necessary
if: ${{ !steps.image-cache.outputs.cache-hit }}
run: |
docker build --build-arg TEST_ZSH_VERSION=${{ matrix.version }} -t $IMAGE_CACHE_NAME .
mkdir -p $IMAGE_CACHE_PATH
docker save $IMAGE_CACHE_NAME | gzip > $IMAGE_CACHE_PATH/$IMAGE_CACHE_NAME.tar.gz
- name: Run the tests
run: |
docker run --rm \
-v $PWD:/zsh-autosuggestions \
$IMAGE_CACHE_NAME \
make test

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# zsh word code files
*.zwc

3
.rspec Normal file
View File

@ -0,0 +1,3 @@
--color
--require spec_helper
--format documentation

30
.rubocop.yml Normal file
View File

@ -0,0 +1,30 @@
# Rails:
# Enabled: true
AllCops:
TargetRubyVersion: 2.3
Include:
- '**/Rakefile'
- '**/config.ru'
- '**/Gemfile'
Metrics/LineLength:
Max: 120
Style/Documentation:
Enabled: false
Style/DotPosition:
EnforcedStyle: trailing
Style/FrozenStringLiteralComment:
Enabled: false
Style/Lambda:
Enabled: false
Style/MultilineMethodCallIndentation:
EnforcedStyle: indented
Style/TrailingUnderscoreVariable:
Enabled: false

1
.ruby-version Normal file
View File

@ -0,0 +1 @@
2.5.3

124
CHANGELOG.md Normal file
View File

@ -0,0 +1,124 @@
# Changelog
## v0.7.1
- Clear POSTDISPLAY instead of unsetting (#634)
- Always reset async file descriptor after consuming it (#630)
- Always use builtin `exec` (#628)
- Add `history-beginning-search-*-end` widgets to clear widget list (#619)
- Switch CI from Circle CI to GitHub Actions
## v0.7.0
- Enable asynchronous mode by default (#498)
- No longer wrap user widgets starting with `autosuggest-` prefix (#496)
- Fix a bug wrapping widgets that modify the buffer (#541)
## v0.6.4
- Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488)
- New configuration option to skip completion suggestions when buffer matches a pattern (#487)
- New configuration option to ignore history entries matching a pattern (#456)
## v0.6.3
- Fixed bug moving cursor to end of buffer after accepting suggestion (#453)
## v0.6.2
- Fixed bug deleting the last character in the buffer in vi mode (#450)
- Degrade gracefully when user doesn't have `zsh/system` module installed (#447)
## v0.6.1
- Fixed bug occurring when `_complete` had been aliased (#443)
## v0.6.0
- Added `completion` suggestion strategy powered by completion system (#111)
- Allow setting `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an empty string (#422)
- Don't fetch suggestions after copy-earlier-word (#439)
- Allow users to unignore zle-\* widgets (e.g. zle-line-init) (#432)
## v0.5.2
- Allow disabling automatic widget re-binding for better performance (#418)
- Fix async suggestions when `SH_WORD_SPLIT` is set
- Refactor async mode to use process substitution instead of zpty (#417)
## v0.5.1
- Speed up widget rebinding (#413)
- Clean up global variable creations (#403)
- Respect user's set options when running original widget (#402)
## v0.5.0
- Don't overwrite config with default values (#335)
- Support fallback strategies by supplying array to suggestion config var
- Rename "default" suggestion strategy to "history" to name it based on what it actually does
- Reset opts in some functions affected by `GLOB_SUBST` (#334)
- Support widgets starting with dashes (ex: `-a-widget`) (#337)
- Skip async tests in zsh versions less than 5.0.8 because of reliability issues
- Fix handling of newline + carriage return in async pty (#333)
## v0.4.3
- Avoid bell when accepting suggestions with `autosuggest-accept` (#228)
- Don't fetch suggestions after [up,down]-line-or-beginning-search (#227, #241)
- We are now running CI against new 5.5.1 version
- Fix partial-accept in vi mode (#188)
- Fix suggestion disappearing on fast movement after switching to `vicmd` mode (#290)
- Fix issue rotating through kill ring with `yank-pop` (#301)
- Fix issue creating new pty for async mode when previous pty is not properly cleaned up (#249)
## v0.4.2
- Fix bug in zsh versions older than 5.0.8 (#296)
- Officially support back to zsh v4.3.11
## v0.4.1
- Switch to [[ and (( conditionals instead of [ (#257)
- Avoid warnnestedvar warnings with `typeset -g` (#275)
- Replace tabs with spaces in yaml (#268)
- Clean up and fix escaping of special characters (#267)
- Add `emacs-forward-word` to default list of partial accept widgets (#246)
## v0.4.0
- High-level integration tests using RSpec and tmux
- Add continuous integration with Circle CI
- Experimental support for asynchronous suggestions (#170)
- Fix problems with multi-line suggestions (#225)
- Optimize case where manually typing in suggestion
- Avoid wrapping any zle-\* widgets (#206)
- Remove support for deprecated options from v0.0.x
- Handle history entries that begin with dashes
- Gracefully handle being sourced multiple times (#126)
- Add enable/disable/toggle widgets to disable/enable suggestions (#219)
## v0.3.3
- Switch from $history array to fc builtin for better performance with large HISTFILEs (#164)
- Fix tilde handling when extended_glob is set (#168)
- Add config option for maximum buffer length to fetch suggestions for (#178)
- Add config option for list of widgets to ignore (#184)
- Don't fetch a new suggestion unless a modification widget actually modifies the buffer (#183)
## v0.3.2
- Test runner now supports running specific tests and choosing zsh binary
- Return code from original widget is now correctly passed through (#135)
- Add `vi-add-eol` to list of accept widgets (#143)
- Escapes widget names within evals to fix problems with irregular widget names (#152)
- Plugin now clears suggestion while within a completion menu (#149)
- .plugin file no longer relies on symbolic link support, fixing issues on Windows (#156)
## v0.3.1
- Fixes issue with `vi-next-char` not accepting suggestion (#137).
- Fixes global variable warning when WARN_CREATE_GLOBAL option enabled (#133).
- Split out a separate test file for each widget.
## v0.3.0
- Adds `autosuggest-execute` widget (PR #124).
- Adds concept of suggestion "strategies" for different ways of fetching suggestions.
- Adds "match_prev_cmd" strategy (PR #131).
- Uses git submodules for testing dependencies.
- Lots of test cleanup.
- Various bug fixes for zsh 5.0.x and `sh_word_split` option.
## v0.2.17
Start of changelog.

1
DESCRIPTION Normal file
View File

@ -0,0 +1 @@
Fish-like fast/unobtrusive autosuggestions for zsh.

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM ruby:2.5.3-alpine
ARG TEST_ZSH_VERSION
RUN : "${TEST_ZSH_VERSION:?}"
RUN apk add --no-cache autoconf
RUN apk add --no-cache libtool
RUN apk add --no-cache libcap-dev
RUN apk add --no-cache pcre-dev
RUN apk add --no-cache curl
RUN apk add --no-cache build-base
RUN apk add --no-cache ncurses-dev
RUN apk add --no-cache tmux
WORKDIR /zsh-autosuggestions
ADD install_test_zsh.sh ./
RUN ./install_test_zsh.sh
ADD Gemfile Gemfile.lock ./
RUN bundle install

5
Gemfile Normal file
View File

@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'rspec'
gem 'rspec-wait'
gem 'pry-byebug'

41
Gemfile.lock Normal file
View File

@ -0,0 +1,41 @@
GEM
remote: https://rubygems.org/
specs:
byebug (9.0.5)
coderay (1.1.1)
diff-lcs (1.3)
method_source (0.8.2)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-byebug (3.4.0)
byebug (~> 9.0)
pry (~> 0.10)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
slop (3.6.0)
PLATFORMS
ruby
DEPENDENCIES
pry-byebug
rspec
rspec-wait
BUNDLED WITH
1.13.6

3
INFO
View File

@ -1,3 +0,0 @@
Fish-like fast/unobtrusive autosuggestions for zsh.
https://github.com/tarruda/zsh-autosuggestions
v0.1.0

81
INSTALL.md Normal file
View File

@ -0,0 +1,81 @@
# Installation
* [Packages](#packages)
* [Antigen](#antigen)
* [Oh My Zsh](#oh-my-zsh)
* [HomeBrew](#homebrew)
* [Manual](#manual-git-clone)
## Packages
| System | Package |
| ------------- | ------------- |
| Alpine Linux | [zsh-autosuggestions](https://pkgs.alpinelinux.org/packages?name=zsh-autosuggestions) |
| Debian / Ubuntu | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Fedora / CentOS / RHEL / Scientific Linux | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| OpenSUSE / SLE | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Arch Linux / Manjaro / Antergos / Hyperbola | [zsh-autosuggestions](https://www.archlinux.org/packages/zsh-autosuggestions), [zsh-autosuggestions-git](https://aur.archlinux.org/packages/zsh-autosuggestions-git) |
| NixOS | [zsh-autosuggestions](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/zs/zsh-autosuggestions/package.nix) |
| Void Linux | [zsh-autosuggestions](https://github.com/void-linux/void-packages/blob/master/srcpkgs/zsh-autosuggestions/template) |
| Mac OS | [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/z/zsh-autosuggestions.rb) |
| NetBSD | [pkgsrc](http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/shells/zsh-autosuggestions/README.html) |
## Antigen
1. Add the following to your `.zshrc`:
```sh
antigen bundle zsh-users/zsh-autosuggestions
```
2. Start a new terminal session.
## Oh My Zsh
1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
```
2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`):
```sh
plugins=(
# other plugins...
zsh-autosuggestions
)
```
3. Start a new terminal session.
## Homebrew
1. Install command:
```sh
brew install zsh-autosuggestions
```
2. To activate the autosuggestions, add the following at the end of your .zshrc:
```sh
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
## Manual (Git Clone)
1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.

View File

@ -1,5 +1,5 @@
Copyright (c) 2013 Thiago de Arruda
Copyright (c) 2016 Eric Freese
Copyright (c) 2016-2021 Eric Freese
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

View File

@ -1,27 +1,35 @@
DIST_DIR := ./dist
SRC_DIR := ./src
SCRIPT_DIR := ./script
SRC_DIR := ./src
SRC_TARGETS := \
SRC_FILES := \
$(SRC_DIR)/config.zsh \
$(SRC_DIR)/deprecated.zsh \
$(SRC_DIR)/util.zsh \
$(SRC_DIR)/bind.zsh \
$(SRC_DIR)/highlight.zsh \
$(SRC_DIR)/widgets.zsh \
$(SRC_DIR)/suggestion.zsh \
$(SRC_DIR)/strategies/*.zsh \
$(SRC_DIR)/fetch.zsh \
$(SRC_DIR)/async.zsh \
$(SRC_DIR)/start.zsh
$(DIST_DIR)/autosuggestions.zsh: $(SRC_TARGETS) LICENSE
mkdir -p $(DIST_DIR)
cat INFO | sed -e 's/^/# /g' > $@
echo "#" >> $@
cat LICENSE | sed -e 's/^/# /g' >> $@
cat >> $@ $(SRC_TARGETS)
HEADER_FILES := \
DESCRIPTION \
URL \
VERSION \
LICENSE
PLUGIN_TARGET := zsh-autosuggestions.zsh
all: $(PLUGIN_TARGET)
$(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES)
cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@
cat $(SRC_FILES) >> $@
.PHONY: clean
clean:
rm -rf $(DIST_DIR)
rm $(PLUGIN_TARGET)
.PHONY: test
test: $(DIST_DIR)/autosuggestions.zsh $(SCRIPT_DIR)/test.sh
$(SCRIPT_DIR)/test.sh
test: all
@test -n "$$TEST_ZSH_BIN" && echo "Testing zsh binary: $(TEST_ZSH_BIN)" || true
bundle exec rspec $(TESTS)

181
README.md
View File

@ -2,25 +2,18 @@
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
It suggests commands as you type, based on command history.
It suggests commands as you type based on history and completions.
Requirements: Zsh v4.3.11 or later
[![Chat on Gitter](https://img.shields.io/gitter/room/zsh-users/zsh-autosuggestions.svg)](https://gitter.im/zsh-users/zsh-autosuggestions)
<a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a>
## Installation
1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
```sh
git clone git://github.com/tarruda/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source ~/.zsh/zsh-autosuggestions/dist/autosuggestions.zsh
autosuggest_start
```
**Note:** If you're using other zle plugins like `zsh-syntax-highlighting` or `zsh-history-substring-search`, check out the [section on compatibility](#compatibility-with-other-zle-plugins) below.
See [INSTALL.md](INSTALL.md).
## Usage
@ -34,12 +27,35 @@ If you invoke the `forward-word` widget, it will partially accept the suggestion
## Configuration
You may want to override the default global config variables after sourcing the plugin. Default values of these variables can be found [here](https://github.com/tarruda/zsh-autosuggestions/blob/master/src/config.zsh).
You may want to override the default global config variables. Default values of these variables can be found [here](src/config.zsh).
**Note:** If you are using Oh My Zsh, you can put this configuration in a file in the `$ZSH_CUSTOM` directory. See their comments on [overriding internals](https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals).
### Suggestion Highlight Style
Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion is shown with. The default is `fg=8`.
Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion is shown with. The default is `fg=8`, which will set the foreground color to color 8 from the [256-color palette](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). If your terminal only supports 8 colors, you will need to use a number between 0 and 7.
Background color can also be set, and the suggestion can be styled bold, underlined, or standout. For example, this would show suggestions with bold, underlined, pink text on a cyan background:
```sh
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#ff00ff,bg=cyan,bold,underline"
```
For more info, read the Character Highlighting section of the zsh manual: `man zshzle` or [online](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting).
**Note:** Some iTerm2 users have reported [not being able to see the suggestions](https://github.com/zsh-users/zsh-autosuggestions/issues/416#issuecomment-486516333). If this affects you, the problem is likely caused by incorrect color settings. In order to correct this, go into iTerm2's setting, navigate to profile > colors and make sure that the colors for Basic Colors > Background and ANSI Colors > Bright Black are **different**.
### Suggestion Strategy
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies to choose from:
- `history`: Chooses the most recent match from history.
- `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module, which is included with zsh since 4.0.1)
- `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.
### Widget Mapping
@ -47,21 +63,55 @@ Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion
This plugin works by triggering custom behavior when certain [zle widgets](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets) are invoked. You can add and remove widgets from these arrays to change the behavior of this plugin:
- `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: Widgets in this array will clear the suggestion when invoked.
- `ZSH_AUTOSUGGEST_MODIFY_WIDGETS`: Widgets in this array will modify the buffer and fetch a new suggestion when invoked.
- `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: Widgets in this array will accept the suggestion when invoked.
- `ZSH_AUTOSUGGEST_EXECUTE_WIDGETS`: Widgets in this array will execute the suggestion when invoked.
- `ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS`: Widgets in this array will partially accept the suggestion when invoked.
- `ZSH_AUTOSUGGEST_IGNORE_WIDGETS`: Widgets in this array will not trigger any custom behavior.
**Note:** These arrays must be set before calling `autosuggest_start`.
Widgets that modify the buffer and are not found in any of these arrays will fetch a new suggestion after they are invoked.
**Note:** A widget shouldn't belong to more than one of the above arrays.
### Disabling suggestion for large buffers
Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long.
### Asynchronous Mode
Suggestions are fetched asynchronously by default in zsh versions 5.0.8 and greater. To disable asynchronous suggestions and fetch them synchronously instead, `unset ZSH_AUTOSUGGEST_USE_ASYNC` after sourcing the plugin.
Alternatively, if you are using a version of zsh older than 5.0.8 and want to enable asynchronous mode, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable after sourcing the plugin (it can be set to anything). Note that there is [a bug](https://github.com/zsh-users/zsh-autosuggestions/issues/364#issuecomment-481423232) in versions of zsh older than 5.0.8 where <kbd>ctrl</kbd> + <kbd>c</kbd> will fail to reset the prompt immediately after fetching a suggestion asynchronously.
### Disabling automatic widget re-binding
Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable automatic widget re-binding on each precmd. This can be a big boost to performance, but you'll need to handle re-binding yourself if any of the widget lists change or if you or another plugin wrap any of the autosuggest widgets. To re-bind widgets, run `_zsh_autosuggest_bind_widgets`.
### Ignoring history suggestions that match a pattern
Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer.
**Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies.
### Skipping completion suggestions for certain cases
Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands.
**Note:** This only affects the `completion` suggestion strategy.
### Key Bindings
This plugin provides two widgets that you can use with `bindkey`:
This plugin provides a few widgets that you can use with `bindkey`:
1. `autosuggest-accept`: Accepts the current suggestion.
2. `autosuggest-clear`: Clears the current suggestion.
2. `autosuggest-execute`: Accepts and executes the current suggestion.
3. `autosuggest-clear`: Clears the current suggestion.
4. `autosuggest-fetch`: Fetches a suggestion (works even when suggestions are disabled).
5. `autosuggest-disable`: Disables suggestions.
6. `autosuggest-enable`: Re-enables suggestions.
7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions.
For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.
@ -70,56 +120,19 @@ bindkey '^ ' autosuggest-accept
```
## Compatibility With Other ZLE Plugins
## Troubleshooting
If you have a problem, please search through [the list of issues on GitHub](https://github.com/zsh-users/zsh-autosuggestions/issues?q=) to see if someone else has already reported it.
### [`zsh-syntax-highlighting`](https://github.com/zsh-users/zsh-syntax-highlighting)
### Reporting an Issue
Source `zsh-autosuggestions.zsh` *before* `zsh-syntax-highlighting`.
Before reporting an issue, please try temporarily disabling sections of your configuration and other plugins that may be conflicting with this plugin to isolate the problem.
Call `autosuggest_start` *after* sourcing `zsh-syntax-highlighting`.
When reporting an issue, please include:
For example:
```sh
source ~/.zsh/zsh-autosuggestions/dist/autosuggestions.zsh
source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
autosuggest_start
```
### [`zsh-history-substring-search`](https://github.com/zsh-users/zsh-history-substring-search)
When the buffer is empty and one of the `history-substring-search-up/down` widgets is invoked, it will call the `up/down-line-or-history` widget. If the `up/down-line-or-history` widgets are in `ZSH_AUTOSUGGEST_CLEAR_WIDGETS` (the list of widgets that clear the suggestion), this can create an infinite recursion, crashing the shell session.
For best results, you'll want to remove `up-line-or-history` and `down-line-or-history` from `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`:
```
# Remove *-line-or-history widgets from list of widgets that clear the autosuggestion to avoid conflict with history-substring-search-* widgets
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=("${(@)ZSH_AUTOSUGGEST_CLEAR_WIDGETS:#(up|down)-line-or-history}")
```
Additionally, the `history-substring-search-up` and `history-substring-search-down` widgets are not bound by default. You'll probably want to add them to `ZSH_AUTOSUGGEST_CLEAR_WIDGETS` so that the suggestion will be cleared when you start searching through history:
```sh
# Add history-substring-search-* widgets to list of widgets that clear the autosuggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(history-substring-search-up history-substring-search-down)
```
Make sure you add/remove these widgets *before* calling `autosuggest_start`.
For example:
```sh
source ~/.zsh/zsh-autosuggestions/dist/autosuggestions.zsh
source ~/Code/zsh-history-substring-search/zsh-history-substring-search.zsh
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=("${(@)ZSH_AUTOSUGGEST_CLEAR_WIDGETS:#(up|down)-line-or-history}")
ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(history-substring-search-up history-substring-search-down)
autosuggest_start
```
- The smallest, simplest `.zshrc` configuration that will reproduce the problem. See [this comment](https://github.com/zsh-users/zsh-autosuggestions/issues/102#issuecomment-180944764) for a good example of what this means.
- The version of zsh you're using (`zsh --version`)
- Which operating system you're running
## Uninstallation
@ -133,6 +146,42 @@ autosuggest_start
```
## Development
### Build Process
Edit the source files in `src/`. Run `make` to build `zsh-autosuggestions.zsh` from those source files.
### Pull Requests
Pull requests are welcome! If you send a pull request, please:
- Request to merge into the `develop` branch (*NOT* `master`)
- Match the existing coding conventions.
- Include helpful comments to keep the barrier-to-entry low for people new to the project.
- Write tests that cover your code as much as possible.
### Testing
Tests are written in ruby using the [`rspec`](http://rspec.info/) framework. They use [`tmux`](https://tmux.github.io/) to drive a pseudoterminal, sending simulated keystrokes and making assertions on the terminal content.
Test files live in `spec/`. To run the tests, run `make test`. To run a specific test, run `TESTS=spec/some_spec.rb make test`. You can also specify a `zsh` binary to use by setting the `TEST_ZSH_BIN` environment variable (ex: `TEST_ZSH_BIN=/bin/zsh make test`).
It's possible to run the tests for any supported version of zsh in a Docker image by building an image from the provided Dockerfile. To build the docker image for a specific version of zsh (where `<version>` below is substituted with the contents of a line from the [`ZSH_VERSIONS`](ZSH_VERSIONS) file), run:
```sh
docker build --build-arg TEST_ZSH_VERSION=<version> -t zsh-autosuggestions-test .
```
After building the image, run the tests via:
```sh
docker run -it -v $PWD:/zsh-autosuggestions zsh-autosuggestions-test make test
```
## License
This project is licensed under [MIT license](http://opensource.org/licenses/MIT).

1
URL Normal file
View File

@ -0,0 +1 @@
https://github.com/zsh-users/zsh-autosuggestions

1
VERSION Normal file
View File

@ -0,0 +1 @@
v0.7.1

14
ZSH_VERSIONS Normal file
View File

@ -0,0 +1,14 @@
# Zsh releases to run tests against
# See https://github.com/zsh-users/zsh/releases
4.3.11
5.0.2
5.0.8
5.1.1
5.2
5.3.1
5.4.2
5.5.1
5.6.2
5.7.1
5.8.1
5.9

View File

@ -1,345 +0,0 @@
# Fish-like fast/unobtrusive autosuggestions for zsh.
# https://github.com/tarruda/zsh-autosuggestions
# v0.1.0
#
# Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016 Eric Freese
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#--------------------------------#
# Global Configuration Variables #
#--------------------------------#
# Color to use when highlighting suggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
# Prefix to use when saving original versions of bound widgets
ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
# Widgets that clear the suggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
up-line-or-history
down-line-or-history
accept-line
)
# Widgets that modify the suggestion
ZSH_AUTOSUGGEST_MODIFY_WIDGETS=(
list-choices
complete-word
menu-complete
menu-expand-or-complete
reverse-menu-complete
expand-or-complete
expand-or-complete-prefix
self-insert
magic-space
bracketed-paste
expand-cmd-path
accept-and-menu-complete
backward-delete-char
vi-backward-delete-char
delete-char
vi-delete-char
delete-char-or-list
)
# Widgets that accept the entire suggestion
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
vi-end-of-line
)
# Widgets that accept the suggestion as far as the cursor moves
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
vi-forward-word
vi-forward-word-end
vi-forward-blank-word
vi-forward-blank-word-end
)
#-------------------------------------#
# Handle Deprecated Variables/Widgets #
#-------------------------------------#
unset _ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN
_zsh_autosuggest_check_deprecated_config() {
if [ -n "$AUTOSUGGESTION_HIGHLIGHT_COLOR" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_COLOR is deprecated. Use ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE instead."
[ -z "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" ] && ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=$AUTOSUGGESTION_HIGHLIGHT_STYLE
unset AUTOSUGGESTION_HIGHLIGHT_STYLE
fi
if [ -n "$AUTOSUGGESTION_HIGHLIGHT_CURSOR" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_CURSOR is deprecated."
unset AUTOSUGGESTION_HIGHLIGHT_CURSOR
fi
if [ -n "$AUTOSUGGESTION_ACCEPT_RIGHT_ARROW" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_ACCEPT_RIGHT_ARROW is deprecated. The right arrow now accepts the suggestion by default."
unset AUTOSUGGESTION_ACCEPT_RIGHT_ARROW
fi
}
_zsh_autosuggest_deprecated_warning() {
>&2 echo "zsh-autosuggestions: $@"
}
_zsh_autosuggest_deprecated_start_widget() {
if [ -z "$_ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN" ]; then
_zsh_autosuggest_deprecated_warning "The autosuggest-start widget is deprecated. Use the autosuggest_start function instead. For more info, see README at https://github.com/tarruda/zsh-autosuggestions."
_ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN=true
fi
autosuggest_start
}
zle -N autosuggest-start _zsh_autosuggest_deprecated_start_widget
#----------------#
# Widget Helpers #
#----------------#
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
_zsh_autosuggest_bind_widget() {
local widget=$1
local autosuggest_function=$2
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local action
case $widgets[$widget] in
# Already bound
user:_zsh_autosuggest_(bound|orig)_*);;
# User-defined widget
user:*)
zle -N $prefix$widget ${widgets[$widget]#*:}
;;
# Built-in widget
builtin)
eval "_zsh_autosuggest_orig_$widget() { zle .$widget }"
zle -N $prefix$widget _zsh_autosuggest_orig_$widget
;;
# Completion widget
completion:*)
eval "zle -C $prefix$widget ${${widgets[$widget]#*:}/:/ }"
;;
esac
# Set up widget to call $autosuggest_function if it exists
# Otherwise just call the original widget
if [ -n "$autosuggest_function" ]; then;
action=$autosuggest_function;
else;
action="zle $prefix$widget \$@"
fi
# Create new function for the widget that highlights and calls the action
eval "_zsh_autosuggest_bound_$widget() {
_zsh_autosuggest_highlight_reset
$action
_zsh_autosuggest_highlight_apply
}"
# Create the bound widget
zle -N $widget _zsh_autosuggest_bound_$widget
}
# Map all configured widgets to the right autosuggest widgets
_zsh_autosuggest_bind_widgets() {
local widget;
# Find every widget we might want to bind and bind it appropriately
for widget in ${${(f)"$(builtin zle -la)"}:#(.*|_*|orig-*|autosuggest-*|$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX*|run-help|which-command|beep|set-local-history|yank)}; do
if [ ${ZSH_AUTOSUGGEST_MODIFY_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_modify
elif [ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_clear
elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_accept
elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_partial_accept
else
_zsh_autosuggest_bind_widget $widget
fi
done
}
# Given the name of a widget, invoke the original we saved, if it exists
_zsh_autosuggest_invoke_original_widget() {
local original_widget_name="$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX$1"
if [ $widgets[$original_widget_name] ]; then
zle $original_widget_name
fi
}
#--------------#
# Highlighting #
#--------------#
# If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() {
if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
# If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() {
if [ $#POSTDISPLAY -gt 0 ]; then
_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=($_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT)
else
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
#------------------------------------#
# Autosuggest Widget Implementations #
#------------------------------------#
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $WIDGET
}
# Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() {
# Original widget modifies the buffer
_zsh_autosuggest_invoke_original_widget $WIDGET
# Get a new suggestion if the buffer is not empty after modification
local suggestion
if [ $#BUFFER -gt 0 ]; then
suggestion=$(_zsh_autosuggest_suggestion $BUFFER)
fi
# Add the suggestion to the POSTDISPLAY
if [ -n "$suggestion" ]; then
POSTDISPLAY=${suggestion#$BUFFER}
else
unset POSTDISPLAY
fi
}
# Accept the entire suggestion
_zsh_autosuggest_accept() {
# Only accept if the cursor is at the end of the buffer
if [ $CURSOR -eq $#BUFFER ]; then
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
unset POSTDISPLAY
# Move the cursor to the end of the buffer
CURSOR=${#BUFFER}
fi
_zsh_autosuggest_invoke_original_widget $WIDGET
}
# Partially accept the suggestion
_zsh_autosuggest_partial_accept() {
# Save the contents of the buffer so we can restore later if needed
local original_buffer=$BUFFER
# Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY"
# Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $WIDGET
# If we've moved past the end of the original buffer
if [ $CURSOR -gt $#original_buffer ]; then
# Set POSTDISPLAY to text right of the cursor
POSTDISPLAY=$RBUFFER
# Clip the buffer at the cursor
BUFFER=$LBUFFER
else
# Restore the original buffer
BUFFER=$original_buffer
fi
}
_zsh_autosuggest_widget_accept() {
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_accept
_zsh_autosuggest_highlight_apply
}
_zsh_autosuggest_widget_clear() {
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_clear
_zsh_autosuggest_highlight_apply
}
zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_clear
#------------#
# Suggestion #
#------------#
# Get a suggestion from history that matches a given prefix
_zsh_autosuggest_suggestion() {
setopt localoptions extendedglob
# Escape the prefix (requires EXTENDED_GLOB)
local prefix=${1//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
# Get all history items (reversed) that match pattern $prefix*
local history_matches
history_matches=(${history[(R)$prefix*]})
# Echo the first item that matches
echo ${history_matches[1]}
}
#-------#
# Start #
#-------#
# Start the autosuggestion widgets
autosuggest_start() {
_zsh_autosuggest_check_deprecated_config
_zsh_autosuggest_bind_widgets
}

23
install_test_zsh.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
set -ex
mkdir zsh-build
cd zsh-build
curl -L https://api.github.com/repos/zsh-users/zsh/tarball/zsh-$TEST_ZSH_VERSION | tar xz --strip=1
./Util/preconfig
./configure --enable-pcre \
--enable-cap \
--enable-multibyte \
--with-term-lib='ncursesw tinfo' \
--with-tcsetpgrp
make install.bin
make install.modules
make install.fns
cd ..
rm -rf zsh-build

View File

@ -1,77 +0,0 @@
#!/usr/bin/env zsh
SCRIPT_DIR=$(dirname "$0")
TEST_DIR=$SCRIPT_DIR/../test
DIST_DIR=$SCRIPT_DIR/../dist
source $DIST_DIR/autosuggestions.zsh
testDefaultHighlightStyle() {
assertEquals \
"fg=8" \
"$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
}
testHighlightApplyWithSuggestion() {
orig_style=ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=4"
BUFFER="ec"
POSTDISPLAY="ho hello"
region_highlight=("0 2 fg=1")
_zsh_autosuggest_highlight_apply
assertEquals \
"adds to region_highlight with correct style" \
"0 2 fg=1 2 10 $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" \
"$region_highlight"
assertEquals \
"saves the higlight to be removed later" \
"2 10 $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" \
"$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=orig_style
}
testHighlightApplyWithoutSuggestion() {
BUFFER="echo hello"
POSTDISPLAY=""
region_highlight=("0 4 fg=1")
_zsh_autosuggest_highlight_apply
assertEquals \
"leaves region_highlight alone" \
"0 4 fg=1" \
"$region_highlight"
assertNull \
"clears the last highlight" \
"$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
}
testHighlightReset() {
BUFFER="ec"
POSTDISPLAY="ho hello"
region_highlight=("0 1 fg=1" "2 10 fg=8" "1 2 fg=1")
_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="2 10 fg=8"
_zsh_autosuggest_highlight_reset
assertEquals \
"removes last highlight region" \
"0 1 fg=1 1 2 fg=1" \
"$region_highlight"
assertNull \
"clears the last highlight" \
"$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
}
# For zsh compatibility
setopt shwordsplit
SHUNIT_PARENT=$0
source $TEST_DIR/shunit2-2.1.6/src/shunit2

70
spec/async_spec.rb Normal file
View File

@ -0,0 +1,70 @@
context 'with asynchronous suggestions enabled' do
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
describe '`up-line-or-beginning-search`' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -U up-line-or-beginning-search').
run_command('zle -N up-line-or-beginning-search').
send_string('bindkey "').
send_keys('C-v').send_keys('up').
send_string('" up-line-or-beginning-search').
send_keys('enter')
end
end
it 'should show previous history entries' do
with_history(
'echo foo',
'echo bar',
'echo baz'
) do
session.clear_screen
3.times { session.send_keys('up') }
wait_for { session.content }.to eq("echo foo")
end
end
end
describe '`copy-earlier-word`' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -Uz copy-earlier-word').
run_command('zle -N copy-earlier-word').
run_command('bindkey "^N" copy-earlier-word')
end
end
it 'should cycle through previous words in the buffer' do
session.clear_screen
session.send_string('foo bar baz')
sleep 0.5
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazbaz')
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazbar')
session.send_keys('C-n')
wait_for { session.content }.to eq('foo bar bazfoo')
end
end
describe 'pressing ^C after fetching a suggestion' do
before do
skip 'Workaround does not work below v5.0.8' if session.zsh_version < Gem::Version.new('5.0.8')
end
it 'terminates the prompt and begins a new one' do
session.send_keys('e')
sleep 0.5
session.send_keys('C-c')
sleep 0.5
session.send_keys('echo')
wait_for { session.content }.to eq("e\necho")
end
end
end

View File

@ -0,0 +1,14 @@
describe 'with `AUTO_CD` option set' do
let(:after_sourcing) do
-> {
session.run_command('setopt AUTO_CD')
session.run_command('autoload compinit && compinit')
}
end
it 'directory names are still completed' do
session.send_string('sr')
session.send_keys('C-i')
wait_for { session.content }.to eq('src/')
end
end

View File

@ -0,0 +1,43 @@
describe 'pasting using bracketed-paste-magic' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -Uz bracketed-paste-magic').
run_command('zle -N bracketed-paste bracketed-paste-magic')
end
end
context 'with suggestions disabled while pasting' do
before do
session.
run_command('bpm_init() { zle autosuggest-disable }').
run_command('bpm_finish() { zle autosuggest-enable }').
run_command('zstyle :bracketed-paste-magic paste-init bpm_init').
run_command('zstyle :bracketed-paste-magic paste-finish bpm_finish')
end
it 'does not show an incorrect suggestion' do
with_history('echo hello') do
session.paste_string("echo #{'a' * 60}")
sleep 1
expect(session.content).to eq("echo #{'a' * 60}")
end
end
end
context 'with `bracketed-paste` added to the list of widgets that clear the suggestion' do
let(:options) { ['ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(bracketed-paste)'] }
it 'does not retain an old suggestion' do
with_history ('echo foo') do
session.send_string('echo ')
wait_for { session.content }.to eq('echo foo')
session.paste_string('bar')
wait_for { session.content }.to eq('echo bar')
session.send_keys('C-a') # Any cursor movement works
sleep 1
expect(session.content).to eq('echo bar')
end
end
end
end

View File

@ -0,0 +1,14 @@
describe 'a running zpty command' do
let(:before_sourcing) { -> { session.run_command('zmodload zsh/zpty && zpty -b kitty cat') } }
context 'when using `completion` strategy' do
let(:options) { ["ZSH_AUTOSUGGEST_STRATEGY=completion"] }
it 'is not affected' do
session.send_keys('a').send_keys('C-h')
session.run_command('zpty -t kitty; echo $?')
wait_for { session.content }.to end_with("\n0")
end
end
end

View File

@ -0,0 +1,12 @@
describe 'with `GLOB_SUBST` option set' do
let(:after_sourcing) do
-> {
session.run_command('setopt GLOB_SUBST')
}
end
it 'error messages are not printed' do
session.send_string('[[')
wait_for { session.content }.to eq('[[')
end
end

View File

@ -0,0 +1,13 @@
describe 'rebinding [' do
context 'initialized before sourcing the plugin' do
before do
session.run_command("function [ { $commands[\\[] \"$@\" }")
session.clear_screen
end
it 'executes the custom behavior and the built-in behavior' do
session.send_string('asdf')
wait_for { session.content }.to eq('asdf')
end
end
end

View File

@ -0,0 +1,80 @@
describe 'when using vi mode' do
let(:before_sourcing) do
-> do
session.run_command('bindkey -v')
end
end
describe 'moving the cursor after exiting insert mode' do
it 'should not clear the current suggestion' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('h')
wait_for { session.content }.to eq('foobar foo')
end
end
end
describe '`vi-forward-word-end`' do
it 'should accept through the end of the current word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('e'). # vi-forward-word-end
send_keys('a'). # vi-add-next
send_string('baz')
wait_for { session.content }.to eq('foobarbaz')
end
end
end
describe '`vi-forward-word`' do
it 'should accept through the first character of the next word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('w'). # vi-forward-word
send_keys('a'). # vi-add-next
send_string('az')
wait_for { session.content }.to eq('foobar faz')
end
end
end
describe '`vi-find-next-char`' do
it 'should accept through the next occurrence of the character' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('f'). # vi-find-next-char
send_keys('o').
send_keys('a'). # vi-add-next
send_string('b')
wait_for { session.content }.to eq('foobar fob')
end
end
end
describe '`vi-delete`' do
it 'should be able to remove the last character in the buffer' do
skip 'deleting last char did not work below zsh version 5.0.8' if session.zsh_version < Gem::Version.new('5.0.8')
session.
send_string('echo foo').
send_keys('escape').
send_keys('d').
send_keys('l')
wait_for { session.content }.to eq('echo fo')
end
end
end

View File

@ -0,0 +1,39 @@
describe 'a wrapped widget' do
let(:widget) { 'backward-delete-char' }
context 'initialized before sourcing the plugin' do
let(:before_sourcing) do
-> do
session.
run_command("_orig_#{widget}() { zle .#{widget} }").
run_command("zle -N orig-#{widget} _orig_#{widget}").
run_command("#{widget}-magic() { zle orig-#{widget}; BUFFER+=b }").
run_command("zle -N #{widget} #{widget}-magic")
end
end
it 'executes the custom behavior and the built-in behavior' do
with_history('foobar', 'foodar') do
session.send_string('food').send_keys('C-h')
wait_for { session.content }.to eq('foobar')
end
end
end
context 'initialized after sourcing the plugin' do
before do
session.
run_command("zle -N orig-#{widget} ${widgets[#{widget}]#*:}").
run_command("#{widget}-magic() { zle orig-#{widget}; BUFFER+=b }").
run_command("zle -N #{widget} #{widget}-magic").
clear_screen
end
it 'executes the custom behavior and the built-in behavior' do
with_history('foobar', 'foodar') do
session.send_string('food').send_keys('C-h')
wait_for { session.content }.to eq('foobar')
end
end
end
end

View File

@ -0,0 +1,24 @@
describe 'using `zle -U`' do
let(:before_sourcing) do
-> do
session.
run_command('_zsh_autosuggest_strategy_test() { sleep 1; _zsh_autosuggest_strategy_history "$1" }').
run_command('foo() { zle -U - "echo hello" }; zle -N foo; bindkey ^B foo')
end
end
let(:options) { ['unset ZSH_AUTOSUGGEST_USE_ASYNC', 'ZSH_AUTOSUGGEST_STRATEGY=test'] }
# TODO: This is only possible with the $KEYS_QUEUED_COUNT widget parameter, coming soon...
xit 'does not fetch a suggestion for every inserted character' do
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
it 'shows a suggestion when the widget completes' do
with_history('echo hello world') do
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to match(/\Aecho hello\e\[[0-9]+m world/)
end
end
end

23
spec/kill_ring_spec.rb Normal file
View File

@ -0,0 +1,23 @@
context 'with some items in the kill ring' do
before do
session.
send_string('echo foo').
send_keys('C-u').
send_string('echo bar').
send_keys('C-u')
end
describe '`yank-pop`' do
it 'should cycle through all items in the kill ring' do
session.send_keys('C-y')
wait_for { session.content }.to eq('echo bar')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo foo')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo bar')
end
end
end

17
spec/line_init_spec.rb Normal file
View File

@ -0,0 +1,17 @@
context 'with zle-line-init unignored' do
let(:after_sourcing) do
-> do
session.
run_command('setopt extendedglob').
run_command('ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(${(@)ZSH_AUTOSUGGEST_IGNORE_WIDGETS:#zle-\*} zle-\^line-init)').
run_command('zle-line-init() { BUFFER="echo" }')
end
end
it 'should fetch a suggestion on each line initialization' do
with_history('echo foo') do
session.run_command('zle -N zle-line-init')
wait_for { session.content }.to end_with('echo foo')
end
end
end

8
spec/multi_line_spec.rb Normal file
View File

@ -0,0 +1,8 @@
describe 'a multi-line suggestion' do
it 'should be displayed on multiple lines' do
with_history("echo \"\n\"") do
session.send_keys('e')
wait_for { session.content }.to eq("echo \"\n\"")
end
end
end

View File

@ -0,0 +1,30 @@
describe 'a suggestion' do
let(:term_opts) { { width: 200 } }
let(:long_command) { "echo #{'a' * 100}" }
around do |example|
with_history(long_command) { example.run }
end
it 'is provided for any buffer length' do
session.send_string(long_command[0...-1])
wait_for { session.content }.to eq(long_command)
end
context 'when ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE is specified' do
let(:buffer_max_size) { 10 }
let(:options) { ["ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=#{buffer_max_size}"] }
it 'is provided when the buffer is shorter than the specified length' do
session.send_string(long_command[0...(buffer_max_size - 1)])
wait_for { session.content }.to eq(long_command)
end
it 'is provided when the buffer is equal to the specified length' do
session.send_string(long_command[0...(buffer_max_size)])
wait_for { session.content }.to eq(long_command)
end
it 'is not provided when the buffer is longer than the specified length'
end
end

View File

@ -0,0 +1,7 @@
describe 'a displayed suggestion' do
it 'is shown in the default style'
describe 'when ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE is set to a zle_highlight string' do
it 'is shown in the specified style'
end
end

View File

@ -0,0 +1,7 @@
describe 'an original zle widget' do
context 'is accessible with the default prefix'
context 'when ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX is set' do
it 'is accessible with the specified prefix'
end
end

View File

@ -0,0 +1,55 @@
describe 'a suggestion for a given prefix' do
let(:history_strategy) { '_zsh_autosuggest_strategy_history() { suggestion="history" }' }
let(:foobar_strategy) { '_zsh_autosuggest_strategy_foobar() { [[ "foobar baz" = $1* ]] && suggestion="foobar baz" }' }
let(:foobaz_strategy) { '_zsh_autosuggest_strategy_foobaz() { [[ "foobaz bar" = $1* ]] && suggestion="foobaz bar" }' }
let(:after_sourcing) do
-> do
session.run_command(history_strategy)
end
end
it 'by default is determined by calling the `history` strategy function' do
session.send_string('h')
wait_for { session.content }.to eq('history')
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to an array' do
let(:after_sourcing) do
-> do
session.
run_command(foobar_strategy).
run_command(foobaz_strategy).
run_command('ZSH_AUTOSUGGEST_STRATEGY=(foobar foobaz)')
end
end
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to a string' do
let(:after_sourcing) do
-> do
session.
run_command(foobar_strategy).
run_command(foobaz_strategy).
run_command('ZSH_AUTOSUGGEST_STRATEGY="foobar foobaz"')
end
end
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
end

View File

@ -0,0 +1,121 @@
describe 'a zle widget' do
let(:widget) { 'my-widget' }
let(:before_sourcing) { -> { session.run_command("#{widget}() {}; zle -N #{widget}; bindkey ^B #{widget}") } }
context 'when added to ZSH_AUTOSUGGEST_ACCEPT_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_ACCEPT_WIDGETS+=(#{widget})"] }
it 'accepts the suggestion and moves the cursor to the end of the buffer when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
wait_for { session.cursor }.to eq([10, 0])
end
end
end
context 'when added to ZSH_AUTOSUGGEST_CLEAR_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(#{widget})"] }
it 'clears the suggestion when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('e')
end
end
end
context 'when added to ZSH_AUTOSUGGEST_EXECUTE_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_EXECUTE_WIDGETS+=(#{widget})"] }
it 'executes the suggestion when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to end_with("\nhello")
end
end
end
context 'when added to ZSH_AUTOSUGGEST_IGNORE_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(#{widget})"] }
it 'should not be wrapped with an autosuggest widget' do
session.run_command("echo $widgets[#{widget}]")
wait_for { session.content }.to end_with("\nuser:#{widget}")
end
end
context 'that moves the cursor forward' do
before { session.run_command("#{widget}() { zle forward-char }") }
context 'when added to ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS' do
let(:options) { ["ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(#{widget})"] }
it 'accepts the suggestion as far as the cursor is moved when invoked' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to start_with('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to match(/\Aec\e\[[0-9]+mho hello/)
end
end
end
end
context 'that modifies the buffer' do
before { session.run_command("#{widget}() { BUFFER=\"foo\" }") }
context 'when not added to any of the widget lists' do
it 'modifies the buffer and fetches a new suggestion' do
with_history('foobar') do
session.send_keys('C-b')
wait_for { session.content }.to eq('foobar')
end
end
end
end
end
describe 'a modification to the widget lists' do
let(:widget) { 'my-widget' }
let(:before_sourcing) { -> { session.run_command("#{widget}() {}; zle -N #{widget}; bindkey ^B #{widget}") } }
before { session.run_command("ZSH_AUTOSUGGEST_ACCEPT_WIDGETS+=(#{widget})") }
it 'takes effect on the next cmd line' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
end
end
context 'when manual rebind is enabled' do
let(:options) { ["ZSH_AUTOSUGGEST_MANUAL_REBIND=true"] }
it 'does not take effect until bind command is re-run' do
with_history('echo hello') do
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
sleep 1
expect(session.content(esc_seqs: true)).not_to eq('echo hello')
session.send_keys('C-c')
session.run_command('_zsh_autosuggest_bind_widgets').clear_screen
wait_for { session.content }.to eq('')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to eq('echo hello')
end
end
end
end

54
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,54 @@
require 'pry'
require 'rspec/wait'
require 'terminal_session'
require 'tempfile'
RSpec.shared_context 'terminal session' do
let(:term_opts) { {} }
let(:session) { TerminalSession.new(term_opts) }
let(:before_sourcing) { -> {} }
let(:after_sourcing) { -> {} }
let(:options) { [] }
around do |example|
before_sourcing.call
session.run_command(['source zsh-autosuggestions.zsh', *options].join('; '))
after_sourcing.call
session.clear_screen
example.run
session.destroy
end
def with_history(*commands, &block)
Tempfile.create do |f|
f.write(commands.map{|c| c.gsub("\n", "\\\n")}.join("\n"))
f.flush
session.run_command('fc -p')
session.run_command("fc -R #{f.path}")
session.clear_screen
yield block
session.send_keys('C-c')
session.run_command('fc -P')
end
end
end
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.wait_timeout = 2
config.include_context 'terminal session'
end

View File

@ -0,0 +1,72 @@
describe 'the `completion` suggestion strategy' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion'] }
let(:before_sourcing) do
-> do
session.
run_command('autoload compinit && compinit').
run_command('_foo() { compadd bar; compadd bat }').
run_command('_num() { compadd two; compadd three }').
run_command('compdef _foo baz').
run_command('compdef _num one')
end
end
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not add extra carriage returns when prefix has a line feed' do
skip '`stty` does not work inside zpty below zsh version 5.0.3' if session.zsh_version < Gem::Version.new('5.0.3')
session.send_string('baz \\').send_keys('C-v', 'C-j')
wait_for { session.content }.to eq("baz \\\nbar")
end
context 'when `_complete` is aliased' do
let(:before_sourcing) do
-> do
session.
run_command('autoload compinit && compinit').
run_command('_foo() { compadd bar; compadd bat }').
run_command('compdef _foo baz').
run_command('alias _complete=_complete')
end
end
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
end
context 'when ZSH_AUTOSUGGEST_COMPLETION_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion', 'ZSH_AUTOSUGGEST_COMPLETION_IGNORE="one *"'] }
it 'makes suggestions when the buffer does not match the pattern' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not make suggestions when the buffer matches the pattern' do
session.send_string('one t')
sleep 1
expect(session.content).to eq('one t')
end
end
context 'when async mode is enabled' do
let(:options) { ['ZSH_AUTOSUGGEST_USE_ASYNC=true', 'ZSH_AUTOSUGGEST_STRATEGY=completion'] }
it 'suggests the first completion result' do
session.send_string('baz ')
wait_for { session.content }.to eq('baz bar')
end
it 'does not add extra carriage returns when prefix has a line feed' do
skip '`stty` does not work inside zpty below zsh version 5.0.3' if session.zsh_version < Gem::Version.new('5.0.3')
session.send_string('baz \\').send_keys('C-v', 'C-j')
wait_for { session.content }.to eq("baz \\\nbar")
end
end
end

View File

@ -0,0 +1,23 @@
require 'strategies/special_characters_helper'
describe 'the `history` suggestion strategy' do
it 'suggests the last matching history entry' do
with_history('ls foo', 'ls bar', 'echo baz') do
session.send_string('ls')
wait_for { session.content }.to eq('ls bar')
end
end
context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] }
it 'does not make suggestions that match the pattern' do
with_history('ls foo', 'ls bar', 'echo baz') do
session.send_string('ls')
wait_for { session.content }.to eq('ls foo')
end
end
end
include_examples 'special characters'
end

View File

@ -0,0 +1,34 @@
require 'strategies/special_characters_helper'
describe 'the `match_prev_cmd` strategy' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd'] }
let(:history) { [
'echo what',
'ls foo',
'echo what',
'ls bar',
'ls baz',
'echo what'
] }
it 'suggests the last matching history entry after the previous command' do
with_history(*history) do
session.send_string('ls')
wait_for { session.content }.to eq('ls bar')
end
end
context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd', 'ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] }
it 'does not make suggestions that match the pattern' do
with_history(*history) do
session.send_string('ls')
wait_for { session.content }.to eq('ls foo')
end
end
end
include_examples 'special characters'
end

View File

@ -0,0 +1,75 @@
shared_examples 'special characters' do
describe 'a special character in the buffer should be treated like any other character' do
it 'asterisk' do
with_history('echo "hello*"', 'echo "hello."') do
session.send_string('echo "hello*')
wait_for { session.content }.to eq('echo "hello*"')
end
end
it 'question mark' do
with_history('echo "hello?"', 'echo "hello."') do
session.send_string('echo "hello?')
wait_for { session.content }.to eq('echo "hello?"')
end
end
it 'backslash' do
with_history('echo "hello\nworld"') do
session.send_string('echo "hello\\')
wait_for { session.content }.to eq('echo "hello\nworld"')
end
end
it 'double backslash' do
with_history('echo "\\\\"') do
session.send_string('echo "\\\\')
wait_for { session.content }.to eq('echo "\\\\"')
end
end
it 'tilde' do
with_history('echo ~/foo') do
session.send_string('echo ~')
wait_for { session.content }.to eq('echo ~/foo')
end
end
it 'parentheses' do
with_history('echo "$(ls foo)"') do
session.send_string('echo "$(')
wait_for { session.content }.to eq('echo "$(ls foo)"')
end
end
it 'square bracket' do
with_history('echo "$history[123]"') do
session.send_string('echo "$history[')
wait_for { session.content }.to eq('echo "$history[123]"')
session.send_string('123]')
wait_for { session.content }.to eq('echo "$history[123]"')
end
end
it 'octothorpe' do
with_history('echo "#yolo"') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#yolo"')
end
end
it 'caret' do
with_history('echo "^A"', 'echo "^B"') do
session.send_string('echo "^A')
wait_for { session.content }.to eq('echo "^A"')
end
end
it 'dash' do
with_history('-foo() {}') do
session.send_string('-')
wait_for { session.content }.to eq('-foo() {}')
end
end
end
end

99
spec/terminal_session.rb Normal file
View File

@ -0,0 +1,99 @@
require 'securerandom'
class TerminalSession
ZSH_BIN = ENV['TEST_ZSH_BIN'] || 'zsh'
def initialize(opts = {})
opts = {
width: 80,
height: 24,
prompt: '',
term: 'xterm-256color',
zsh_bin: ZSH_BIN
}.merge(opts)
@opts = opts
cmd="PS1=\"#{opts[:prompt]}\" TERM=#{opts[:term]} #{ZSH_BIN} -f"
tmux_command("new-session -d -x #{opts[:width]} -y #{opts[:height]} '#{cmd}'")
end
def zsh_version
@zsh_version ||= Gem::Version.new(`#{ZSH_BIN} -c 'echo -n $ZSH_VERSION'`)
end
def tmux_socket_name
@tmux_socket_name ||= SecureRandom.hex(6)
end
def run_command(command)
send_string(command)
send_keys('enter')
self
end
def send_string(str)
tmux_command("send-keys -t 0 -l -- '#{str.gsub("'", "\\'")}'")
self
end
def send_keys(*keys)
tmux_command("send-keys -t 0 #{keys.join(' ')}")
self
end
def paste_string(str)
tmux_command("set-buffer -- '#{str}'")
tmux_command("paste-buffer -dpr -t 0")
self
end
def content(esc_seqs: false)
cmd = 'capture-pane -p -t 0'
cmd += ' -e' if esc_seqs
tmux_command(cmd).strip
end
def clear_screen
send_keys('C-l')
i = 0
until content == opts[:prompt] || i > 20 do
sleep(0.1)
i = i + 1
end
self
end
def destroy
tmux_command('kill-session')
end
def cursor
tmux_command("display-message -t 0 -p '\#{cursor_x},\#{cursor_y}'").
strip.
split(',').
map(&:to_i)
end
def attach!
tmux_command('attach-session')
end
private
attr_reader :opts
def tmux_command(cmd)
out = `tmux -u -L #{tmux_socket_name} #{cmd}`
raise("tmux error running: '#{cmd}'") unless $?.success?
out
end
end

View File

@ -0,0 +1,19 @@
describe 'the `autosuggest-disable` widget' do
before do
session.run_command('bindkey ^B autosuggest-disable')
end
it 'disables suggestions and clears the suggestion' do
with_history('echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
end
end
end

View File

@ -0,0 +1,42 @@
describe 'the `autosuggest-enable` widget' do
before do
session.
run_command('typeset -g _ZSH_AUTOSUGGEST_DISABLED').
run_command('bindkey ^B autosuggest-enable')
end
it 'enables suggestions and fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
session.send_string('c')
wait_for { session.content }.to eq('echo hello')
end
end
context 'invoked on an empty buffer' do
it 'does not fetch a suggestion' do
with_history('echo hello') do
session.send_keys('C-b')
sleep 1
expect(session.content).to eq('')
end
end
end
context 'invoked on a non-empty buffer' do
it 'fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View File

@ -0,0 +1,24 @@
describe 'the `autosuggest-fetch` widget' do
context 'when suggestions are disabled' do
before do
session.
run_command('bindkey ^B autosuggest-disable').
run_command('bindkey ^F autosuggest-fetch').
send_keys('C-b')
end
it 'will fetch and display a suggestion' do
with_history('echo hello') do
session.send_string('echo h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-f')
wait_for { session.content }.to eq('echo hello')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View File

@ -0,0 +1,26 @@
describe 'the `autosuggest-toggle` widget' do
before do
session.run_command('bindkey ^B autosuggest-toggle')
end
it 'toggles suggestions' do
with_history('echo world', 'echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-h')
session.send_string('w')
wait_for { session.content }.to eq('echo world')
end
end
end

77
src/async.zsh Normal file
View File

@ -0,0 +1,77 @@
#--------------------------------------------------------------------#
# Async #
#--------------------------------------------------------------------#
_zsh_autosuggest_async_request() {
zmodload zsh/system 2>/dev/null # For `$sysparams`
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
# If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# We won't know the pid unless the user has zsh/system module installed
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
# Zsh will make a new process group for the child process only if job
# control is enabled (MONITOR option)
if [[ -o MONITOR ]]; then
# Send the signal to the process group to kill any processes that may
# have been forked by the suggestion strategy
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
else
# Kill just the child process since it wasn't placed in a new process
# group. If the suggestion strategy forked any child processes they may
# be orphaned and left behind.
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
fi
fi
fi
# Fork a process to fetch a suggestion and open a pipe to read from it
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid
echo $sysparams[pid]
# Fetch and print the suggestion
local suggestion
_zsh_autosuggest_fetch_suggestion "$1"
echo -nE "$suggestion"
)
# There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least
is-at-least 5.8 || command true
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
# When the fd is readable, call the response handler
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
}
# Called when new data is ready to be read from the pipe
# First arg will be fd ready for reading
# Second arg will be passed in case of error
_zsh_autosuggest_async_response() {
emulate -L zsh
local suggestion
if [[ -z "$2" || "$2" == "hup" ]]; then
# Read everything from the fd and give it as a suggestion
IFS='' read -rd '' -u $1 suggestion
zle autosuggest-suggest -- "$suggestion"
# Close the fd
builtin exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
_ZSH_AUTOSUGGEST_ASYNC_FD=
}

View File

@ -1,80 +1,106 @@
#----------------#
# Widget Helpers #
#----------------#
#--------------------------------------------------------------------#
# Widget Helpers #
#--------------------------------------------------------------------#
_zsh_autosuggest_incr_bind_count() {
typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
}
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
_zsh_autosuggest_bind_widget() {
local widget=$1
local autosuggest_function=$2
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local action
typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
local widget=$1
local autosuggest_action=$2
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local -i bind_count
# Save a reference to the original widget
case $widgets[$widget] in
# Already bound
user:_zsh_autosuggest_(bound|orig)_*);;
user:_zsh_autosuggest_(bound|orig)_*)
bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
;;
# User-defined widget
user:*)
zle -N $prefix$widget ${widgets[$widget]#*:}
_zsh_autosuggest_incr_bind_count $widget
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
;;
# Built-in widget
builtin)
eval "_zsh_autosuggest_orig_$widget() { zle .$widget }"
zle -N $prefix$widget _zsh_autosuggest_orig_$widget
_zsh_autosuggest_incr_bind_count $widget
eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
;;
# Completion widget
completion:*)
eval "zle -C $prefix$widget ${${widgets[$widget]#*:}/:/ }"
_zsh_autosuggest_incr_bind_count $widget
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;;
esac
# Set up widget to call $autosuggest_function if it exists
# Otherwise just call the original widget
if [ -n "$autosuggest_function" ]; then;
action=$autosuggest_function;
else;
action="zle $prefix$widget \$@"
fi
# Create new function for the widget that highlights and calls the action
eval "_zsh_autosuggest_bound_$widget() {
_zsh_autosuggest_highlight_reset
$action
_zsh_autosuggest_highlight_apply
# Pass the original widget's name explicitly into the autosuggest
# function. Use this passed in widget name to call the original
# widget instead of relying on the $WIDGET variable being set
# correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`).
eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
_zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
}"
# Create the bound widget
zle -N $widget _zsh_autosuggest_bound_$widget
zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
}
# Map all configured widgets to the right autosuggest widgets
_zsh_autosuggest_bind_widgets() {
local widget;
emulate -L zsh
local widget
local ignore_widgets
ignore_widgets=(
.\*
_\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
)
# Find every widget we might want to bind and bind it appropriately
for widget in ${${(f)"$(builtin zle -la)"}:#(.*|_*|orig-*|autosuggest-*|$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX*|run-help|which-command|beep|set-local-history|yank)}; do
if [ ${ZSH_AUTOSUGGEST_MODIFY_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_modify
elif [ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_clear
elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_accept
elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then
_zsh_autosuggest_bind_widget $widget _zsh_autosuggest_partial_accept
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget clear
elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget accept
elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget execute
elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_zsh_autosuggest_bind_widget $widget partial_accept
else
_zsh_autosuggest_bind_widget $widget
# Assume any unspecified widget might modify the buffer
_zsh_autosuggest_bind_widget $widget modify
fi
done
}
# Given the name of a widget, invoke the original we saved, if it exists
# Given the name of an original widget and args, invoke it, if it exists
_zsh_autosuggest_invoke_original_widget() {
local original_widget_name="$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX$1"
# Do nothing unless called with at least one arg
(( $# )) || return 0
if [ $widgets[$original_widget_name] ]; then
zle $original_widget_name
local original_widget_name="$1"
shift
if (( ${+widgets[$original_widget_name]} )); then
zle $original_widget_name -- $@
fi
}

View File

@ -1,61 +1,95 @@
#--------------------------------#
# Global Configuration Variables #
#--------------------------------#
#--------------------------------------------------------------------#
# Global Configuration Variables #
#--------------------------------------------------------------------#
# Color to use when highlighting suggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
# Prefix to use when saving original versions of bound widgets
ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
typeset -ga ZSH_AUTOSUGGEST_STRATEGY
ZSH_AUTOSUGGEST_STRATEGY=(history)
}
# Widgets that clear the suggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
up-line-or-history
down-line-or-history
accept-line
)
# Widgets that modify the suggestion
ZSH_AUTOSUGGEST_MODIFY_WIDGETS=(
list-choices
complete-word
menu-complete
menu-expand-or-complete
reverse-menu-complete
expand-or-complete
expand-or-complete-prefix
self-insert
magic-space
bracketed-paste
expand-cmd-path
accept-and-menu-complete
backward-delete-char
vi-backward-delete-char
delete-char
vi-delete-char
delete-char-or-list
)
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
history-beginning-search-forward-end
history-beginning-search-backward-end
history-substring-search-up
history-substring-search-down
up-line-or-beginning-search
down-line-or-beginning-search
up-line-or-history
down-line-or-history
accept-line
copy-earlier-word
)
}
# Widgets that accept the entire suggestion
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
vi-end-of-line
)
(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
vi-end-of-line
vi-add-eol
)
}
# Widgets that accept the entire suggestion and execute it
(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
)
}
# Widgets that accept the suggestion as far as the cursor moves
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
vi-forward-word
vi-forward-word-end
vi-forward-blank-word
vi-forward-blank-word-end
)
(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
emacs-forward-word
vi-forward-word
vi-forward-word-end
vi-forward-blank-word
vi-forward-blank-word-end
vi-find-next-char
vi-find-next-char-skip
)
}
# Widgets that should be ignored (globbing supported but must be escaped)
(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
orig-\*
beep
run-help
set-local-history
which-command
yank
yank-pop
zle-\*
)
}
# Pty name for capturing completions for completion suggestion strategy
(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty

View File

@ -1,39 +0,0 @@
#-------------------------------------#
# Handle Deprecated Variables/Widgets #
#-------------------------------------#
unset _ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN
_zsh_autosuggest_check_deprecated_config() {
if [ -n "$AUTOSUGGESTION_HIGHLIGHT_COLOR" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_COLOR is deprecated. Use ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE instead."
[ -z "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" ] && ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=$AUTOSUGGESTION_HIGHLIGHT_STYLE
unset AUTOSUGGESTION_HIGHLIGHT_STYLE
fi
if [ -n "$AUTOSUGGESTION_HIGHLIGHT_CURSOR" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_CURSOR is deprecated."
unset AUTOSUGGESTION_HIGHLIGHT_CURSOR
fi
if [ -n "$AUTOSUGGESTION_ACCEPT_RIGHT_ARROW" ]; then
_zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_ACCEPT_RIGHT_ARROW is deprecated. The right arrow now accepts the suggestion by default."
unset AUTOSUGGESTION_ACCEPT_RIGHT_ARROW
fi
}
_zsh_autosuggest_deprecated_warning() {
>&2 echo "zsh-autosuggestions: $@"
}
_zsh_autosuggest_deprecated_start_widget() {
if [ -z "$_ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN" ]; then
_zsh_autosuggest_deprecated_warning "The autosuggest-start widget is deprecated. Use the autosuggest_start function instead. For more info, see README at https://github.com/tarruda/zsh-autosuggestions."
_ZSH_AUTOSUGGEST_DEPRECATED_START_WIDGET_WARNING_SHOWN=true
fi
autosuggest_start
}
zle -N autosuggest-start _zsh_autosuggest_deprecated_start_widget

27
src/fetch.zsh Normal file
View File

@ -0,0 +1,27 @@
#--------------------------------------------------------------------#
# Fetch Suggestion #
#--------------------------------------------------------------------#
# Loops through all specified strategies and returns a suggestion
# from the first strategy to provide one.
#
_zsh_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
local strategy
# Ensure we are working with an array
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
for strategy in $strategies; do
# Try to get a suggestion from this strategy
_zsh_autosuggest_strategy_$strategy "$1"
# Ensure the suggestion matches the prefix
[[ "$suggestion" != "$1"* ]] && unset suggestion
# Break once we've found a valid suggestion
[[ -n "$suggestion" ]] && break
done
}

View File

@ -1,11 +1,13 @@
#--------------#
# Highlighting #
#--------------#
#--------------------------------------------------------------------#
# Highlighting #
#--------------------------------------------------------------------#
# If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() {
if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi
@ -13,9 +15,11 @@ _zsh_autosuggest_highlight_reset() {
# If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() {
if [ $#POSTDISPLAY -gt 0 ]; then
_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=($_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT)
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if (( $#POSTDISPLAY )); then
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
else
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
fi

View File

@ -1,10 +1,33 @@
#-------#
# Start #
#-------#
#--------------------------------------------------------------------#
# Start #
#--------------------------------------------------------------------#
# Start the autosuggestion widgets
autosuggest_start() {
_zsh_autosuggest_check_deprecated_config
_zsh_autosuggest_start() {
# By default we re-bind widgets on every precmd to ensure we wrap other
# wrappers. Specifically, highlighting breaks if our widgets are wrapped by
# zsh-syntax-highlighting widgets. This also allows modifications to the
# widget list variables to take effect on the next precmd. However this has
# a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
# to disable the automatic re-binding.
if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
add-zsh-hook -d precmd _zsh_autosuggest_start
fi
_zsh_autosuggest_bind_widgets
}
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd
add-zsh-hook precmd _zsh_autosuggest_start

View File

@ -0,0 +1,137 @@
#--------------------------------------------------------------------#
# Completion Suggestion Strategy #
#--------------------------------------------------------------------#
# Fetches a suggestion from the completion engine
#
_zsh_autosuggest_capture_postcompletion() {
# Always insert the first completion into the buffer
compstate[insert]=1
# Don't list completions
unset 'compstate[list]'
}
_zsh_autosuggest_capture_completion_widget() {
# Add a post-completion hook to be called after all completions have been
# gathered. The hook can modify compstate to affect what is done with the
# gathered completions.
local -a +h comppostfuncs
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
# Only capture completions at the end of the buffer
CURSOR=$#BUFFER
# Run the original widget wrapping `.complete-word` so we don't
# recursively try to fetch suggestions, since our pty is forked
# after autosuggestions is initialized.
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
if is-at-least 5.0.3; then
# Don't do any cr/lf transformations. We need to do this immediately before
# output because if we do it in setup, onlcr will be re-enabled when we enter
# vared in the async code path. There is a bug in zpty module in older versions
# where the tty is not properly attached to the pty slave, resulting in stty
# getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
# commit f75904a38
stty -onlcr -ocrnl -F /dev/tty
fi
# The completion has been added, print the buffer as the suggestion
echo -nE - $'\0'$BUFFER$'\0'
}
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() {
# There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
# process immediately, before it has a chance to kill any other
# zpty processes.
if ! is-at-least 5.4; then
zshexit() {
# The zsh builtin `kill` fails sometimes in older versions
# https://unix.stackexchange.com/a/477647/156673
kill -KILL $$ 2>&- || command kill -KILL $$
# Block for long enough for the signal to come through
sleep 1
}
fi
# Try to avoid any suggestions that wouldn't match the prefix
zstyle ':completion:*' matcher-list ''
zstyle ':completion:*' path-completion false
zstyle ':completion:*' max-errors 0 not-numeric
bindkey '^I' autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_sync() {
_zsh_autosuggest_capture_setup
zle autosuggest-capture-completion
}
_zsh_autosuggest_capture_completion_async() {
_zsh_autosuggest_capture_setup
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
# Make vared completion work as if for a normal command line
# https://stackoverflow.com/a/7057118/154703
autoload +X _complete
functions[_original_complete]=$functions[_complete]
function _complete() {
unset 'compstate[vared]'
_original_complete "$@"
}
# Open zle with buffer set so we can capture completions for it
vared 1
}
_zsh_autosuggest_strategy_completion() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable extended glob for completion ignore pattern
setopt EXTENDED_GLOB
typeset -g suggestion
local line REPLY
# Exit if we don't have completions
whence compdef >/dev/null || return
# Exit if we don't have zpty
zmodload zsh/zpty 2>/dev/null || return
# Exit if our search string matches the ignore pattern
[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
# Zle will be inactive if we are in async mode
if zle; then
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
else
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
fi
{
# The completion result is surrounded by null bytes, so read the
# content between the first two null bytes.
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
# Extract the suggestion from between the null bytes. On older
# versions of zsh (older than 5.3), we sometimes get extra bytes after
# the second null byte, so trim those off the end.
# See http://www.zsh.org/mla/workers/2015/msg03290.html
suggestion="${${(@0)line}[2]}"
} always {
# Destroy the pty
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
}
}

View File

@ -0,0 +1,32 @@
#--------------------------------------------------------------------#
# History Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix.
#
_zsh_autosuggest_strategy_history() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Give the first history item matching the pattern as the suggestion
# - (r) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)$pattern]}"
}

View File

@ -0,0 +1,66 @@
#--------------------------------------------------------------------#
# Match Previous Command Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix and whose preceding history item also matches the most
# recently executed command.
#
# For example, suppose your history has the following entries:
# - pwd
# - ls foo
# - ls bar
# - pwd
#
# Given the history list above, when you type 'ls', the suggestion
# will be 'ls foo' rather than 'ls bar' because your most recently
# executed command (pwd) was previously followed by 'ls foo'.
#
# Note that this strategy won't work as expected with ZSH options that don't
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
# `HIST_EXPIRE_DUPS_FIRST`.
_zsh_autosuggest_strategy_match_prev_cmd() {
# Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
setopt EXTENDED_GLOB
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match the prefix, excluding those that match
# the ignore pattern
local pattern="$prefix*"
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
fi
# Get all history event numbers that correspond to history
# entries that match the pattern
local history_match_keys
history_match_keys=(${(k)history[(R)$~pattern]})
# By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}"
# Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do
# Stop if we ran out of history
[[ $key -gt 1 ]] || break
# See if the history entry preceding the suggestion matches the
# previous command, and use it if it does
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
histkey="$key"
break
fi
done
# Give back the matched history entry
typeset -g suggestion="$history[$histkey]"
}

View File

@ -1,19 +0,0 @@
#------------#
# Suggestion #
#------------#
# Get a suggestion from history that matches a given prefix
_zsh_autosuggest_suggestion() {
setopt localoptions extendedglob
# Escape the prefix (requires EXTENDED_GLOB)
local prefix=${1//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
# Get all history items (reversed) that match pattern $prefix*
local history_matches
history_matches=(${history[(R)$prefix*]})
# Echo the first item that matches
echo ${history_matches[1]}
}

11
src/util.zsh Normal file
View File

@ -0,0 +1,11 @@
#--------------------------------------------------------------------#
# Utility Functions #
#--------------------------------------------------------------------#
_zsh_autosuggest_escape_command() {
setopt localoptions EXTENDED_GLOB
# Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
}

View File

@ -1,87 +1,231 @@
#------------------------------------#
# Autosuggest Widget Implementations #
#------------------------------------#
#--------------------------------------------------------------------#
# Autosuggest Widget Implementations #
#--------------------------------------------------------------------#
# Disable suggestions
_zsh_autosuggest_disable() {
typeset -g _ZSH_AUTOSUGGEST_DISABLED
_zsh_autosuggest_clear
}
# Enable suggestions
_zsh_autosuggest_enable() {
unset _ZSH_AUTOSUGGEST_DISABLED
if (( $#BUFFER )); then
_zsh_autosuggest_fetch
fi
}
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
fi
}
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
unset POSTDISPLAY
POSTDISPLAY=
_zsh_autosuggest_invoke_original_widget $WIDGET
_zsh_autosuggest_invoke_original_widget $@
}
# Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() {
# Original widget modifies the buffer
_zsh_autosuggest_invoke_original_widget $WIDGET
local -i retval
# Get a new suggestion if the buffer is not empty after modification
local suggestion
if [ $#BUFFER -gt 0 ]; then
suggestion=$(_zsh_autosuggest_suggestion $BUFFER)
# Only available in zsh >= 5.4
local -i KEYS_QUEUED_COUNT
# Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one
POSTDISPLAY=
# Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@
retval=$?
emulate -L zsh
# Don't fetch a new suggestion if there's more input to be read immediately
if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
POSTDISPLAY="$orig_postdisplay"
return $retval
fi
# Add the suggestion to the POSTDISPLAY
if [ -n "$suggestion" ]; then
POSTDISPLAY=${suggestion#$BUFFER}
# Optimize if manually typing in the suggestion or if buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
return $retval
fi
# Bail out if suggestions are disabled
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
return $?
fi
# Get a new suggestion if the buffer is not empty after modification
if (( $#BUFFER > 0 )); then
if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
_zsh_autosuggest_fetch
fi
fi
return $retval
}
# Fetch a new suggestion based on what's currently in the buffer
_zsh_autosuggest_fetch() {
if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
_zsh_autosuggest_async_request "$BUFFER"
else
unset POSTDISPLAY
local suggestion
_zsh_autosuggest_fetch_suggestion "$BUFFER"
_zsh_autosuggest_suggest "$suggestion"
fi
}
# Offer a suggestion
_zsh_autosuggest_suggest() {
emulate -L zsh
local suggestion="$1"
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}"
else
POSTDISPLAY=
fi
}
# Accept the entire suggestion
_zsh_autosuggest_accept() {
# Only accept if the cursor is at the end of the buffer
if [ $CURSOR -eq $#BUFFER ]; then
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
local -i retval max_cursor_pos=$#BUFFER
# Remove the suggestion
unset POSTDISPLAY
# Move the cursor to the end of the buffer
CURSOR=${#BUFFER}
# When vicmd keymap is active, the cursor can't move all the way
# to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
max_cursor_pos=$((max_cursor_pos - 1))
fi
_zsh_autosuggest_invoke_original_widget $WIDGET
# If we're not in a valid state to accept a suggestion, just run the
# original widget and bail out
if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
_zsh_autosuggest_invoke_original_widget $@
return
fi
# Only accept if the cursor is at the end of the buffer
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
# Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Move the cursor to the end of the buffer
if [[ "$KEYMAP" = "vicmd" ]]; then
CURSOR=$(($#BUFFER - 1))
else
CURSOR=$#BUFFER
fi
return $retval
}
# Accept the entire suggestion and execute it
_zsh_autosuggest_execute() {
# Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
# Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior
_zsh_autosuggest_invoke_original_widget "accept-line"
}
# Partially accept the suggestion
_zsh_autosuggest_partial_accept() {
local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed
local original_buffer=$BUFFER
local original_buffer="$BUFFER"
# Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY"
# Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $WIDGET
_zsh_autosuggest_invoke_original_widget $@
retval=$?
# Normalize cursor location across vi/emacs modes
cursor_loc=$CURSOR
if [[ "$KEYMAP" = "vicmd" ]]; then
cursor_loc=$((cursor_loc + 1))
fi
# If we've moved past the end of the original buffer
if [ $CURSOR -gt $#original_buffer ]; then
if (( $cursor_loc > $#original_buffer )); then
# Set POSTDISPLAY to text right of the cursor
POSTDISPLAY=$RBUFFER
POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
# Clip the buffer at the cursor
BUFFER=$LBUFFER
BUFFER="${BUFFER[1,$cursor_loc]}"
else
# Restore the original buffer
BUFFER=$original_buffer
BUFFER="$original_buffer"
fi
return $retval
}
_zsh_autosuggest_widget_accept() {
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_accept
_zsh_autosuggest_highlight_apply
}
() {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_zsh_autosuggest_widget_clear() {
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_clear
_zsh_autosuggest_highlight_apply
}
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_clear
local action
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
eval "_zsh_autosuggest_widget_$action() {
local -i retval
_zsh_autosuggest_highlight_reset
_zsh_autosuggest_$action \$@
retval=\$?
_zsh_autosuggest_highlight_apply
zle -R
return \$retval
}"
done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
done
}

View File

@ -1,62 +0,0 @@
#! /bin/sh
# $Id: gen_test_results.sh 54 2008-10-21 23:29:23Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# This script runs the provided unit tests and sends the output to the
# appropriate file.
#
# treat unset variables as an error
set -u
die()
{
[ $# -gt 0 ] && echo "error: $@" >&2
exit 1
}
BASE_DIR="`dirname $0`/.."
LIB_DIR="${BASE_DIR}/lib"
# load libraries
. ${LIB_DIR}/shflags || die 'unable to load shflags library'
. ${LIB_DIR}/shlib || die 'unable to load shlib library'
. ${LIB_DIR}/versions || die 'unable to load versions library'
BASE_DIR=`shlib_relToAbsPath "${BASE_DIR}"`
SRC_DIR="${BASE_DIR}/src"
os_name=`versions_osName |sed 's/ /_/g'`
os_version=`versions_osVersion`
DEFINE_boolean force false 'force overwrite' f
DEFINE_string output_dir "`pwd`" 'output dir' d
DEFINE_string output_file "${os_name}-${os_version}.txt" 'output file' o
DEFINE_string suite 'shunit2_test.sh' 'unit test suite' s
FLAGS "${@:-}" || exit $?; shift ${FLAGS_ARGC}
# determine output filename
output="${FLAGS_output_dir:+${FLAGS_output_dir}/}${FLAGS_output_file}"
output=`shlib_relToAbsPath "${output}"`
# checks
if [ -f "${output}" ]; then
if [ ${FLAGS_force} -eq ${FLAGS_TRUE} ]; then
rm -f "${output}"
else
echo "not overwriting '${output}'" >&2
exit ${FLAGS_ERROR}
fi
fi
touch "${output}" 2>/dev/null || die "unable to write to '${output}'"
# run tests
( cd "${SRC_DIR}"; ./${FLAGS_suite} |tee "${output}" )
echo >&2
echo "output written to '${output}'" >&2

View File

@ -1,36 +0,0 @@
#! /bin/sh
# $Id: which 12 2007-02-18 03:31:14Z sfsetse $
#
# This is a simple implementation of the 'which' command for those OSes that
# don't have one.
#
true; TRUE=$?
false; FALSE=$?
showAll=${FALSE}
# process command line flags
while getopts 'a' opt; do
case ${opt} in
a) showAll=${TRUE}
esac
done
shift `expr ${OPTIND} - 1`
# exit if no arguments were given
[ $# -eq 0 ] && exit 1
command=$1
# search for command
out=`echo "${PATH}" |sed "s/:/\n/g" |\
while read path; do
fullPath="${path}/${command}"
if [ -x "${fullPath}" ]; then
echo "${fullPath}"
[ ${showAll} -eq ${FALSE} ] && break
fi
done`
[ -z "${out}" ] && exit 1
echo "${out}"

View File

@ -1,214 +0,0 @@
Changes in shUnit2 2.1.X
========================
Changes with 2.1.6
------------------
Removed all references to the DocBook documentation.
Simplified the 'src' structure.
Fixed error message in fail() that stated wrong number of required arguments.
Updated lib/versions.
Fixed bug in _shunit_mktempDir() where a failure occurred when the 'od' command was not present in /usr/bin.
Renamed shunit_tmpDir variable to SHUNIT_TMPDIR to closer match the standard
TMPDIR variable.
Added support for calling shunit2 as an executable, in addition to the existing
method of sourcing it in as a library. This allows users to keep tests working
despite the location of the shunit2 executable being different for each OS
distribution.
Issue #14: Improved handling of some strange chars (e.g. single and double
quotes) in messages.
Issue# 27: Fixed error message for assertSame().
Issue# 25: Added check and error message to user when phantom functions are
written to a partition mounted with noexec.
Issue# 11: Added support for defining functions like 'function someFunction()'.
Changes with 2.1.5
------------------
Issue# 1: Fixed bug pointed out by R Bernstein in the trap code where certain
types of exit conditions did not generate the ending report.
Issue# 2: Added assertNotEquals() assert.
Issue# 3: Moved check for unset variables out of shUnit2 into the unit tests.
Testing poorly written software blows up if this check is in, but it is only
interesting for shUnit2 itself. Added shunit_test_output.sh unit test for this.
Some shells still do not catch such errors properly (e.g. Bourne shell and BASH
2.x).
Added new custom assert in test_helpers to check for output to STDOUT, and none
to STDERR.
Replaced fatal message in the temp directory creation with a _shunit_fatal()
function call.
Fixed test_output unit test so it works now that the 'set -u' stuff was removed
for Issue# 3.
Flushed out the coding standards in the README.txt a bit more, and brought the
shunit2 code up to par with the documented standards.
Issue# 4: Completely changed the reporting output to be a closer match for
JUnit and PyUnit. As a result, tests are counted separately from assertions.
Provide public shunit_tmpDir variable that can be used by unit test scripts that
need automated and guaranteed cleanup.
Issue# 7: Fixed duplicated printing of messages passed to asserts.
Per code review, fixed wording of failSame() and failNotSame() messages.
Replaced version_info.sh with versions library and made appropriate changes in
other scripts to use it.
Added gen_test_results.sh to make releases easier.
Fixed bugs in shlib_relToAbsPath() in shlib.
Converted DocBook documentation to reStructuredText for easier maintenance. The
DocBook documentation is now considered obsolete, and will be removed in a
future release.
Issue# 5: Fixed the documentation around the usage of failures.
Issue# 9: Added unit tests and updated documentation to demonstrate the
requirement of quoting values twice when macros are used. This is due to how
shell parses arguments.
When an invalid number of arguments is passed to a function, the invalid number
is returned to the user so they are more aware of what the cause might be.
Changes with 2.1.4
------------------
Removed the _shunit_functionExists() function as it was dead code.
Fixed zsh version number check in version_info.
Fixed bug in last resort temporary directory creation.
Fixed off-by-one in exit value for scripts caught by the trap handler.
Added argument count error checking to all functions.
Added mkdir_test.sh example.
Moved src/test into src/shell to better match structure used with shFlags.
Fixed problem where null values were not handled properly under ksh.
Added support for outputting line numbers as part of assert messages.
Started documenting the coding standards, and changed some variable names as a
result.
Improved zsh version and option checks.
Renamed the __SHUNIT_VERSION variable to SHUNIT_VERSION.
Changes with 2.1.3
------------------
Added some explicit variable defaults, even though the variables are set, as
they sometimes behave strange when the script is canceled.
Additional workarounds for zsh compatibility.
shUnit2 now exits with a non-zero exit code if any of the tests failed. This was
done for automated testing frameworks. Tests that were skipped are not
considered failures, and do not affect the exit code.
Changed detection of STDERR output in unit tests.
Changes with 2.1.2
------------------
Unset additional variables that were missed.
Added checks and workarounds to improve zsh compatibility.
Added some argument count checks ``assertEquals()``, ``assertNull()``, and
``assertSame()``
Changes with 2.1.1
------------------
Fixed bug where ``fail()`` was not honoring skipping.
Fixed problem with ``docs-docbook-prep`` target that prevented it from working.
(Thanks to Bryan Larsen for pointing this out.)
Changed the test in ``assertFalse()`` so that any non-zero value registers as
false. (Credits to Bryan Larsen)
Major fiddling to bring more in line with `JUnit <http://junit.org/>`. Asserts
give better output when no message is given, and failures now just fail.
It was pointed out that the simple 'failed' message for a failed assert was not
only insufficient, it was nonstandard (when compared to JUnit) and didn't
provide the user with an expected vs actual result. The code was revised
somewhat to bring closer into alignment with JUnit (v4.3.1 specifically) so
that it feels more "normal". (Credits to Richard Jensen)
As part of the JUnit realignment, it was noticed that fail*() functions in
JUnit don't actually do any comparisons themselves. They only generate a
failure message. Updated the code to match.
Added self-testing unit tests. Kinda horkey, but they did find bugs during the
JUnit realignment.
Fixed the code for returning from asserts as the return was being called before
the unsetting of variables occurred. (Credits to Mathias Goldau)
The assert(True|False)() functions now accept an integer value for a
conditional test. A value of '0' is considered 'true', while any non-zero value
is considered 'false'.
All public functions now fill use default values to work properly with the '-x'
shell debugging flag.
Fixed the method of percent calculation for the report to get achieve better
accuracy.
Changes with 2.1.0 (since 2.0.1)
--------------------------------
This release is a branch of the 2.0.1 release.
Moving to `reStructured Text <http://docutils.sourceforge.net/rst.html>`_ for
the documentation.
Fixed problem with ``fail()``. The failure message was not properly printed.
Fixed the ``Makefile`` so that the DocBook XML and XSLT files would be
downloaded before parsing can continue.
Renamed the internal ``__SHUNIT_TRUE`` and ``__SHUNIT_FALSE`` variables to
``SHUNIT_TRUE`` and ``SHUNIT_FALSE`` so that unit tests can "use" them.
Added support for test "skipping". If skipping is turned on with the
``startSkip()`` function, ``assert`` and ``fail`` functions will return
immediately, and the skip will be recorded.
The report output format was changed to include the percentage for each test
result, rather than just those successful.
.. $Revision: 326 $
.. vim:fileencoding=latin1:ft=text:spell:tw=80

View File

@ -1,504 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -1,540 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>shUnit2 2.1.x README</title>
<style type="text/css">
/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date: 2007-04-11 11:48:16 +0100 (Wed, 11 Apr 2007) $
:Revision: $Revision: 2791 $
:Copyright: This stylesheet has been placed in the public domain.
:Modified by: Kate Ward <kate.ward@forestent.com>
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left {
clear: left }
img.align-right {
clear: right }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
/*
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
*/
table.footnote {
border-left: solid 1px black;
margin-left: 1px ;
font-size: 80% }
}
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
/*
tt.docutils {
background-color: #eeeeee }
*/
ul.auto-toc {
list-style-type: none }
/* customizations by kward */
h1 { font-size: 133%; border-top:1px solid #CCCCFF; }
h1.title { font-size: 150%; border-top:0px; padding-top: 1em; }
/* div.document { font-size: 90% } */
</style>
</head>
<body>
<div class="document" id="shunit2-2-1-x-readme">
<h1 class="title">shUnit2 2.1.x README</h1>
<div class="section" id="code-google-com">
<h1>code.google.com</h1>
<p>This project is stored on code.google.com as <a class="reference external" href="http://code.google.com/p/shunit2/">http://code.google.com/p/shunit2/</a>.
All releases as of 2.1.4 and full source are available there. Documentation is
included as part of the source and each release. Source code is stored in
Subversion and can be accessed using the following information.</p>
<p>Browse the code in a web browser:</p>
<ul class="simple">
<li><a class="reference external" href="http://code.google.com/p/shunit2/source/browse">http://code.google.com/p/shunit2/source/browse</a></li>
<li>svn &gt; trunk &gt; source &gt; 2.1</li>
</ul>
<p>Check out the code locally</p>
<pre class="literal-block">
$ svn checkout http://shunit2.googlecode.com/svn/trunk/ shflags-read-only
</pre>
</div>
<div class="section" id="sourceforge">
<h1>SourceForge</h1>
<p>DEPRECATED</p>
<p>This project is stored on SourceForge as <a class="reference external" href="http://sf.net/projects/shunit2">http://sf.net/projects/shunit2</a>. The
source code is stored in Subversion and can be accessed using the following
information.</p>
<p>Check out the code locally</p>
<pre class="literal-block">
$ svn co https://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1 shunit2
</pre>
<p>Browse the code in a web browser:</p>
<ul class="simple">
<li><a class="reference external" href="http://shunit2.svn.sourceforge.net/viewvc/shunit2/trunk/source/2.1/">http://shunit2.svn.sourceforge.net/viewvc/shunit2/trunk/source/2.1/</a></li>
<li><a class="reference external" href="http://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1/">http://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1/</a></li>
</ul>
</div>
<div class="section" id="making-a-release">
<h1>Making a release</h1>
<p>For these steps, it is assumed we are working with release 2.0.0.</p>
<p>Steps:</p>
<ul class="simple">
<li>write release notes</li>
<li>update version</li>
<li>finish changelog</li>
<li>check all the code in</li>
<li>tag the release</li>
<li>export the release</li>
<li>create tarball</li>
<li>md5sum the tarball and sign with gpg</li>
<li>update website</li>
<li>post to SourceForge and Freshmeat</li>
</ul>
<div class="section" id="write-release-notes">
<h2>Write Release Notes</h2>
<p>This should be pretty self explanatory. Use one of the release notes from a
previous release as an example.</p>
<p>The versions of the various platforms and shells are included when the
master unit test script is run, or when <tt class="docutils literal">bin/gen_test_results.sh</tt> is
used. To determine the versions of the installed shells by hand, use the
<tt class="docutils literal">lib/versions</tt> script.</p>
<p>Alternatively, do the following:</p>
<table border="1" class="docutils">
<colgroup>
<col width="9%" />
<col width="12%" />
<col width="79%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Shell</th>
<th class="head">OS</th>
<th class="head">Notes</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>bash</td>
<td>&nbsp;</td>
<td><tt class="docutils literal">$ bash <span class="pre">--version</span></tt></td>
</tr>
<tr><td>dash</td>
<td>Linux</td>
<td><tt class="docutils literal">$ dpkg <span class="pre">-l</span> |grep dash</tt></td>
</tr>
<tr><td rowspan="3">ksh</td>
<td>&nbsp;</td>
<td><tt class="docutils literal">$ ksh <span class="pre">--version</span></tt>
-or-
<tt class="docutils literal">$ echo 'echo $KSH_VERSION' |ksh</tt></td>
</tr>
<tr><td>Cygwin</td>
<td>see pdksh</td>
</tr>
<tr><td>Solaris</td>
<td><tt class="docutils literal">$ strings /usr/bin/ksh |grep 'Version'</tt></td>
</tr>
<tr><td rowspan="2">pdksh</td>
<td>&nbsp;</td>
<td><tt class="docutils literal">$ strings /bin/pdksh |grep 'PD KSH'</tt></td>
</tr>
<tr><td>Cygwin</td>
<td>look in the downloaded Cygwin directory</td>
</tr>
<tr><td>sh</td>
<td>Solaris</td>
<td>not possible</td>
</tr>
<tr><td>zsh</td>
<td>&nbsp;</td>
<td><tt class="docutils literal">$ zsh <span class="pre">--version</span></tt></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="update-version">
<h2>Update Version</h2>
<p>Edit <tt class="docutils literal">src/shell/shunit2</tt> and change the version number in the comment, as well
as in the <tt class="docutils literal">SHUNIT_VERSION</tt> variable.</p>
</div>
<div class="section" id="finish-documentation">
<h2>Finish Documentation</h2>
<p>Make sure that any remaining changes get put into the <tt class="docutils literal"><span class="pre">CHANGES-X.X.txt</span></tt> file.</p>
<p>Finish writing the <tt class="docutils literal"><span class="pre">RELEASE_NOTES-X.X.X.txt</span></tt>. If necessary, run it
through the <strong>fmt</strong> command to make it pretty (hopefully it is already).</p>
<pre class="literal-block">
$ fmt -w 80 RELEASE_NOTES-2.0.0.txt &gt;RELEASE_NOTES-2.0.0.txt.new
$ mv RELEASE_NOTES-2.0.0.txt.new RELEASE_NOTES-2.0.0.txt
</pre>
<p>We want to have an up-to-date version of the documentation in the release, so
we'd better build it.</p>
<pre class="literal-block">
$ pwd
.../shunit2/source/2.1
$ cd doc
$ RST2HTML_OPTS='--stylesheet-path=rst2html.css'
$ rst2html ${RST2HTML_OPTS} shunit2.txt &gt;shunit2.html
$ rst2html ${RST2HTML_OPTS} README.txt &gt;README.html
</pre>
</div>
<div class="section" id="check-in-all-the-code">
<h2>Check In All the Code</h2>
<p>This step is pretty self-explanatory</p>
<pre class="literal-block">
$ pwd
.../shunit2/source/2.0
$ svn ci -m &quot;finalizing release&quot;
</pre>
</div>
<div class="section" id="tag-the-release">
<h2>Tag the Release</h2>
<pre class="literal-block">
$ pwd
.../shunit2/source
$ ls
2.0 2.1
$ svn cp -m &quot;Release 2.0.0&quot; 2.0 https://shunit2.googlecode.com/svn/tags/source/2.0.0
</pre>
</div>
<div class="section" id="export-the-release">
<h2>Export the Release</h2>
<pre class="literal-block">
$ pwd
.../shunit2/builds
$ svn export https://shunit2.googlecode.com/svn/tags/source/2.0.0 shunit2-2.0.0
</pre>
</div>
<div class="section" id="create-tarball">
<h2>Create Tarball</h2>
<pre class="literal-block">
$ tar cfz ../releases/shunit2-2.0.0.tgz shunit2-2.0.0
</pre>
</div>
<div class="section" id="sign-the-tarball-with-gpg">
<h2>Sign the Tarball with gpg</h2>
<pre class="literal-block">
$ cd ../releases
$ gpg --default-key kate.ward&#64;forestent.com --detach-sign shunit2-2.0.0.tgz
</pre>
</div>
<div class="section" id="update-website">
<h2>Update Website</h2>
<p>Again, pretty self-explanatory. Make sure to copy the GPG signature file. Once
that is done, make sure to tag the website so we can go back in time if needed.</p>
<pre class="literal-block">
$ pwd
.../shunit2
$ ls
source website
$ svn cp -m &quot;Release 2.0.0&quot; \
website https://shunit2.googlecode.com/svn/tags/website/20060916
</pre>
<p>Now, update the website. It too is held in Subversion, so <strong>ssh</strong> into the web
server and use <tt class="docutils literal">svn up</tt> to grab the latest version.</p>
</div>
<div class="section" id="post-to-code-google-com-and-freshmeat">
<h2>Post to code.google.com and Freshmeat</h2>
<ul class="simple">
<li><a class="reference external" href="http://code.google.com/p/shunit2/">http://code.google.com/p/shunit2/</a></li>
<li><a class="reference external" href="http://freshmeat.net/">http://freshmeat.net/</a></li>
</ul>
</div>
</div>
<div class="section" id="related-documentation">
<h1>Related Documentation</h1>
<dl class="docutils">
<dt>Docbook:</dt>
<dd><a class="reference external" href="http://www.docbook.org/">http://www.docbook.org/</a></dd>
<dt>Docbook XML</dt>
<dd><dl class="first last docutils">
<dt>docbook-xml-4.4.zip:</dt>
<dd><a class="reference external" href="http://www.docbook.org/xml/4.4/docbook-xml-4.4.zip">http://www.docbook.org/xml/4.4/docbook-xml-4.4.zip</a>
<a class="reference external" href="http://www.oasis-open.org/docbook/xml/4.4/docbook-xml-4.4.zip">http://www.oasis-open.org/docbook/xml/4.4/docbook-xml-4.4.zip</a></dd>
<dt>docbook-xml-4.5.zip:</dt>
<dd><a class="reference external" href="http://www.docbook.org/xml/4.5/docbook-xml-4.5.zip">http://www.docbook.org/xml/4.5/docbook-xml-4.5.zip</a></dd>
</dl>
</dd>
<dt>Docbook XSL</dt>
<dd><dl class="first last docutils">
<dt>docbook-xsl-1.71.0.tar.bz2:</dt>
<dd><a class="reference external" href="http://prdownloads.sourceforge.net/docbook/docbook-xsl-1.71.0.tar.bz2?download">http://prdownloads.sourceforge.net/docbook/docbook-xsl-1.71.0.tar.bz2?download</a></dd>
<dt>docbook-xsl-1.71.1.tar.bz2:</dt>
<dd><a class="reference external" href="http://downloads.sourceforge.net/docbook/docbook-xsl-1.71.1.tar.bz2?use_mirror=puzzle">http://downloads.sourceforge.net/docbook/docbook-xsl-1.71.1.tar.bz2?use_mirror=puzzle</a></dd>
</dl>
</dd>
<dt>JUnit:</dt>
<dd><a class="reference external" href="http://www.junit.org/">http://www.junit.org/</a></dd>
<dt>reStructuredText:</dt>
<dd><a class="reference external" href="http://docutils.sourceforge.net/docs/user/rst/quickstart.html">http://docutils.sourceforge.net/docs/user/rst/quickstart.html</a></dd>
</dl>
<!-- generate HTML using rst2html from Docutils of -->
<!-- http://docutils.sourceforge.net/ -->
<!-- -->
<!-- vim:fileencoding=latin1:ft=rst:spell:tw=80 -->
<!-- $Revision: 286 $ -->
</div>
</div>
</body>
</html>

View File

@ -1,214 +0,0 @@
====================
shUnit2 2.1.x README
====================
code.google.com
===============
This project is stored on code.google.com as http://code.google.com/p/shunit2/.
All releases as of 2.1.4 and full source are available there. Documentation is
included as part of the source and each release. Source code is stored in
Subversion and can be accessed using the following information.
Browse the code in a web browser:
- http://code.google.com/p/shunit2/source/browse
- svn > trunk > source > 2.1
Check out the code locally ::
$ svn checkout http://shunit2.googlecode.com/svn/trunk/ shflags-read-only
SourceForge
===========
DEPRECATED
This project is stored on SourceForge as http://sf.net/projects/shunit2. The
source code is stored in Subversion and can be accessed using the following
information.
Check out the code locally ::
$ svn co https://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1 shunit2
Browse the code in a web browser:
- http://shunit2.svn.sourceforge.net/viewvc/shunit2/trunk/source/2.1/
- http://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source/2.1/
Making a release
================
For these steps, it is assumed we are working with release 2.0.0.
Steps:
- write release notes
- update version
- finish changelog
- check all the code in
- tag the release
- export the release
- create tarball
- md5sum the tarball and sign with gpg
- update website
- post to SourceForge and Freshmeat
Write Release Notes
-------------------
This should be pretty self explanatory. Use one of the release notes from a
previous release as an example.
The versions of the various platforms and shells are included when the
master unit test script is run, or when ``bin/gen_test_results.sh`` is
used. To determine the versions of the installed shells by hand, use the
``lib/versions`` script.
Alternatively, do the following:
+-------+---------+-----------------------------------------------------------+
| Shell | OS | Notes |
+=======+=========+===========================================================+
| bash | | ``$ bash --version`` |
+-------+---------+-----------------------------------------------------------+
| dash | Linux | ``$ dpkg -l |grep dash`` |
+-------+---------+-----------------------------------------------------------+
| ksh | | ``$ ksh --version`` |
| | | -or- |
| | | ``$ echo 'echo $KSH_VERSION' |ksh`` |
| +---------+-----------------------------------------------------------+
| | Cygwin | see pdksh |
| +---------+-----------------------------------------------------------+
| | Solaris | ``$ strings /usr/bin/ksh |grep 'Version'`` |
+-------+---------+-----------------------------------------------------------+
| pdksh | | ``$ strings /bin/pdksh |grep 'PD KSH'`` |
| +---------+-----------------------------------------------------------+
| | Cygwin | look in the downloaded Cygwin directory |
+-------+---------+-----------------------------------------------------------+
| sh | Solaris | not possible |
+-------+---------+-----------------------------------------------------------+
| zsh | | ``$ zsh --version`` |
+-------+---------+-----------------------------------------------------------+
Update Version
--------------
Edit ``src/shell/shunit2`` and change the version number in the comment, as well
as in the ``SHUNIT_VERSION`` variable.
Finish Documentation
--------------------
Make sure that any remaining changes get put into the ``CHANGES-X.X.txt`` file.
Finish writing the ``RELEASE_NOTES-X.X.X.txt``. If necessary, run it
through the **fmt** command to make it pretty (hopefully it is already). ::
$ fmt -w 80 RELEASE_NOTES-2.0.0.txt >RELEASE_NOTES-2.0.0.txt.new
$ mv RELEASE_NOTES-2.0.0.txt.new RELEASE_NOTES-2.0.0.txt
We want to have an up-to-date version of the documentation in the release, so
we'd better build it. ::
$ pwd
.../shunit2/source/2.1
$ cd doc
$ RST2HTML_OPTS='--stylesheet-path=rst2html.css'
$ rst2html ${RST2HTML_OPTS} shunit2.txt >shunit2.html
$ rst2html ${RST2HTML_OPTS} README.txt >README.html
Check In All the Code
---------------------
This step is pretty self-explanatory ::
$ pwd
.../shunit2/source/2.0
$ svn ci -m "finalizing release"
Tag the Release
---------------
::
$ pwd
.../shunit2/source
$ ls
2.0 2.1
$ svn cp -m "Release 2.0.0" 2.0 https://shunit2.googlecode.com/svn/tags/source/2.0.0
Export the Release
------------------
::
$ pwd
.../shunit2/builds
$ svn export https://shunit2.googlecode.com/svn/tags/source/2.0.0 shunit2-2.0.0
Create Tarball
--------------
::
$ tar cfz ../releases/shunit2-2.0.0.tgz shunit2-2.0.0
Sign the Tarball with gpg
-------------------------
::
$ cd ../releases
$ gpg --default-key kate.ward@forestent.com --detach-sign shunit2-2.0.0.tgz
Update Website
--------------
Again, pretty self-explanatory. Make sure to copy the GPG signature file. Once
that is done, make sure to tag the website so we can go back in time if needed.
::
$ pwd
.../shunit2
$ ls
source website
$ svn cp -m "Release 2.0.0" \
website https://shunit2.googlecode.com/svn/tags/website/20060916
Now, update the website. It too is held in Subversion, so **ssh** into the web
server and use ``svn up`` to grab the latest version.
Post to code.google.com and Freshmeat
-------------------------------------
- http://code.google.com/p/shunit2/
- http://freshmeat.net/
Related Documentation
=====================
Docbook:
http://www.docbook.org/
Docbook XML
docbook-xml-4.4.zip:
http://www.docbook.org/xml/4.4/docbook-xml-4.4.zip
http://www.oasis-open.org/docbook/xml/4.4/docbook-xml-4.4.zip
docbook-xml-4.5.zip:
http://www.docbook.org/xml/4.5/docbook-xml-4.5.zip
Docbook XSL
docbook-xsl-1.71.0.tar.bz2:
http://prdownloads.sourceforge.net/docbook/docbook-xsl-1.71.0.tar.bz2?download
docbook-xsl-1.71.1.tar.bz2:
http://downloads.sourceforge.net/docbook/docbook-xsl-1.71.1.tar.bz2?use_mirror=puzzle
JUnit:
http://www.junit.org/
reStructuredText:
http://docutils.sourceforge.net/docs/user/rst/quickstart.html
.. generate HTML using rst2html from Docutils of
.. http://docutils.sourceforge.net/
..
.. vim:fileencoding=latin1:ft=rst:spell:tw=80
.. $Revision: 310 $

View File

@ -1,104 +0,0 @@
Release Notes for shUnit2 2.1.0
===============================
This release was branched from shUnit2 2.0.1. It mostly adds new functionality,
but there are couple of bugs fixed from the previous release.
See the ``CHANGES-2.1.rst`` file for a full list of changes.
Tested Platforms
----------------
This list of platforms comes from the latest version of log4sh as shUnit2 is
used in the testing of log4sh on each of these platforms.
Cygwin
- bash 3.2.9(10)
- pdksh 5.2.14
Linux
- bash 3.1.17(1), 3.2.10(1)
- dash 0.5.3
- ksh 1993-12-28
- pdksh 5.2.14
- zsh 4.3.2 (does not work)
Mac OS X 10.4.8 (Darwin 8.8)
- bash 2.05b.0(1)
- ksh 1993-12-28
Solaris 8 U3 (x86)
- /bin/sh
- bash 2.03.0(1)
- ksh M-11/16/88i
Solaris 10 U2 (sparc)
- /bin/sh
- bash 3.00.16(1)
- ksh M-11/16/88i
Solaris 10 U2 (x86)
- /bin/sh
- bash 3.00.16(1)
- ksh M-11/16/88i
New Features
------------
Test skipping
Support added for test "skipping". A skip mode can be enabled so that
subsequent ``assert`` and ``fail`` functions that are called will be recorded
as "skipped" rather than as "passed" or "failed". This functionality can be
used such that when a set of tests makes sense on one platform but not on
another, they can be effectively disabled without altering the total number
of tests.
One example might be when something is supported under ``bash``, but not
under a standard Bourne shell.
New functions: ``startSkipping()``, ``endSkipping``, ``isSkipping``
Changes and Enhancements
------------------------
Moving to the use of `reStructured Text
<http://docutils.sourceforge.net/rst.html>`_ for documentation. It is easy to
read and edit in textual form, but converts nicely to HTML.
The report format has changed. Rather than including a simple "success"
percentage at the end, a percentage is given for each type of test.
Bug Fixes
---------
The ``fail()`` function did not output the optional failure message.
Fixed the ``Makefile`` so that the DocBook XML and XSLT files would be
downloaded before documentation parsing will continue.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
None.
.. $Revision: 273 $
.. vim:fileencoding=latin1:spell:syntax=rst:textwidth=80

View File

@ -1,88 +0,0 @@
Release Notes for shUnit2 2.1.1
===============================
This is mainly a bug fix release, but it also incorporates a realignment with
the JUnit 4 code. Asserts now provide better failure messages, and the failure
functions no longer perform tests.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
Tested Platforms
----------------
This list of platforms comes from the latest version of log4sh as shUnit2 is
used in the testing of log4sh on each of these platforms.
Cygwin
- bash 3.2.15(13)
- pdksh 5.2.14
Linux
- bash 3.1.17(1), 3.2.10(1)
- dash 0.5.3
- ksh 1993-12-28
- pdksh 5.2.14
- zsh 4.3.2 (does not work)
Mac OS X 10.4.9 (Darwin 8.9.1)
- bash 2.05b.0(1)
- ksh 1993-12-28
Solaris 8 U3 (x86)
- /bin/sh
- bash 2.03.0(1)
- ksh M-11/16/88i
Solaris 10 U2 (sparc, x86)
- /bin/sh
- bash 3.00.16(1)
- ksh M-11/16/88i
New Features
------------
None.
Changes and Enhancements
------------------------
The internal test in ``assertFalse()`` now accepts any non-zero value as false.
The ``assertTrue()`` and ``assertFalse()`` functions now accept an integer value
for a conditional test. A value of '0' is considered 'true', while any non-zero
value is considered 'false'.
Self-testing unit tests were added.
Bug Fixes
---------
The ``fail()`` assert now honors skipping.
The ``docs-docbook-prep`` target now works properly.
All asserts now properly unset their variables.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
Functions do not properly test for an invalid number of arguments.
.. vim:fileencoding=latin1:ft=rst:spell:textwidth=80

View File

@ -1,83 +0,0 @@
Release Notes for shUnit2 2.1.2
===============================
This release adds initial support for the zsh shell. Due to some differences
with this shell as compared with others, some special checks have been added,
and there are some extra requirements necessary when this shell is to be used.
To use zsh with shUnit2, the following two requirements must be met:
* The ``shwordsplit`` option must be set.
* The ``function_argzero`` option must be unset.
Please read the Shell Errata section of the documentation for guidance on how
to meet these requirements.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
Tested Platforms
----------------
This list of platforms comes from the latest version of log4sh as shUnit2 is
used in the testing of log4sh on each of these platforms.
Linux
- bash 3.1.17(1), 3.2.25(1)
- dash 0.5.4
- ksh 1993-12-28
- pdksh 5.2.14
- zsh 4.2.5, 4.3.4
Mac OS X 10.4.11 (Darwin 8.11.1)
- bash 2.05b.0(1)
- ksh 1993-12-28
- zsh 4.2.3
Solaris 10 U3 (x86)
- /bin/sh
- bash 3.00.16(1)
- ksh M-11/16/88i
- zsh 4.2.1
New Features
------------
Support for the zsh shell.
Changes and Enhancements
------------------------
Added some argument count checks.
Bug Fixes
---------
None.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
Functions do not properly test for an invalid number of arguments.
ksh and pdksh do not pass null arguments (i.e. empty strings as '') properly,
and as such checks do not work properly.
zsh requires the ``shwordsplit`` option to be set, and the ``function_argzero``
option to be unset for proper operation.
.. vim:fileencoding=latin1:ft=rst:spell:textwidth=80

View File

@ -1,84 +0,0 @@
Release Notes for shUnit2 2.1.3
===============================
This release is minor feature release. It improves support for zsh (although it
still isn't what it could be) and adds automated testing framework support by
returning a non-zero exit when tests fail.
To use zsh with shUnit2, the following two requirements must be met:
* The ``shwordsplit`` option must be set.
* The ``function_argzero`` option must be unset.
Please read the Shell Errata section of the documentation for guidance on how
to meet these requirements.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
Tested Platforms
----------------
Cygwin
- bash 3.2.33(18)
- pdksh 5.2.14
Linux
- bash 3.2.33(1)
- dash 0.5.4
- ksh 1993-12-28
- pdksh 5.2.14
- zsh 4.3.4
Mac OS X 10.5.2 (Darwin 9.2.2)
- bash 3.2.17(1)
- ksh 1993-12-28
- zsh 4.3.4
Solaris 11 x86 (Nevada 77)
- /bin/sh
- bash 3.2.25(1)
- ksh M-11/16/88i
- zsh 4.3.4
New Features
------------
None.
Changes and Enhancements
------------------------
Support for automated testing frameworks.
Bug Fixes
---------
Fixed some issues with zsh support.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
Functions do not properly test for an invalid number of arguments.
ksh and pdksh do not pass null arguments (i.e. empty strings as '') properly,
and as such checks do not work properly.
zsh requires the ``shwordsplit`` option to be set, and the ``function_argzero``
option to be unset for proper operation.
.. vim:fileencoding=latin1:ft=rst:spell:textwidth=80

View File

@ -1,100 +0,0 @@
Release Notes for shUnit2 2.1.4
===============================
This release contains lots of bug fixes and changes. Mostly, it fixes zsh
support in zsh 3.0, and the handling of null values in ksh.
To use zsh with shUnit2, the following requirement must be met:
- The ``shwordsplit`` option must be set.
Please read the Shell Errata section of the documentation for guidance on how
to meet these requirements.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
Tested Platforms
----------------
Cygwin
- bash 3.2.39(19)
- pdksh 5.2.14
- zsh 4.3.4
Linux (Ubuntu Dapper 6.06)
- bash 3.1.17(1)
- pdksh 5.2.14
- zsh 4.2.5
Linux (Ubuntu Hardy 8.04)
- bash 3.2.39(1)
- dash 0.5.4
- ksh 1993-12-28
- pdksh 5.2.14
- zsh 4.3.4
Mac OS X 10.5.4 (Darwin 9.4.0)
- bash 3.2.17(1)
- ksh 1993-12-28
- zsh 4.3.4
Solaris 9 U6 x86
- /bin/sh
- bash 2.05.0(1)
- ksh M-11/16/88i
- zsh 3.0.8
Solaris 11 x86 (Nevada 77)
- /bin/sh
- bash 3.2.25(1)
- ksh M-11/16/88i
- zsh 4.3.4
New Features
------------
Support added to output assert source line number as part of assert messages.
Changes and Enhancements
------------------------
Support for automated testing frameworks.
Added argument count error checking to all functions.
Bug Fixes
---------
Fixed some issues with ksh and zsh support.
Fixed off-by-one of exit value in trap handler.
Fixed handling of null values under ksh.
Fixed bug in last resort temporary directory creation.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
zsh requires the ``shwordsplit`` option to be set.
Line numbers in assert messages do not work properly with Bash 2.x.
.. vim:fileencoding=latin1:ft=rst:spell:tw=80

View File

@ -1,128 +0,0 @@
Release Notes for shUnit2 2.1.5
===============================
This release contains several bug fixes and changes. Additionally, it includes
a rewrite of the test output to better match JUnit and PyUnit.
This version also includes a slightly expanded set of coding standards by which
shUnit2 is coded. It should help anyone reading the code to better understand
it.
Please read the Shell Errata section of the documentation for guidance on how
to meet these requirements.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
Tested Platforms
----------------
Cygwin
- bash 3.2.39(20)
- ksh (sym-link to pdksh)
- pdksh 5.2.14
- zsh 4.3.4
Linux (Ubuntu Dapper 6.06)
- bash 3.1.17(1)
- ksh M-1993-12-28
- pdksh 5.2.14-99/07/13.2
- zsh 4.2.5
Linux (Ubuntu Hardy 8.04)
- bash 3.2.39(1)
- dash 0.5.4
- ksh M-1993-12-28
- pdksh 5.2.14-99/07/13.2
- zsh 4.3.4
Mac OS X 10.5.4 (Darwin 9.4.0)
- bash 3.2.17(1)
- ksh M-1993-12-28
- zsh 4.3.4
Solaris 9 U6 x86
- /bin/sh
- bash 2.05.0(1)
- ksh M-11/16/88i
- zsh 3.0.8
Solaris 11 x86 (Nevada 77)
- /bin/sh
- bash 3.2.25(1)
- ksh M-11/16/88i
- zsh 4.3.4
New Features
------------
Support added for output assert source line number as part of assert messages.
Issue #2: Added assertNotEquals() assert.
Provided a public ``shunit_tmpDir`` variable that can be used by unit test
scripts that need automated and guaranteed cleanup.
Changes and Enhancements
------------------------
Issue #3: Removed the check for unset variables as shUnit2 should not expect
scripts being tested to be clean.
Issue #4: Rewrote the test summary. It is now greatly simplified and much more
script friendly.
Issue #5: Fixed the documentation around the usage of failures.
Issue #9: Added unit tests and improved documentation around the use of macros.
Code updated to meet documented coding standards.
Improved code reuse of ``_shunit_exit()`` and ``_shunit_fatal()`` functions.
All output except shUnit2 error messages now goes to STDOUT.
Converted DocBook documentation to reStructuredText for easier maintenance.
Bug Fixes
---------
Issue #1: Fixed bug in rap code where certain types of exit conditions did not
generate the ending report.
Issue #7: Fixed duplicated printing of messages passed to asserts.
Fixed bugs in ``shlib_relToAbsPath()`` in ``shlib``.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
Zsh requires the ``shwordsplit`` option to be set. See the documentation for
examples of how to do this.
Line numbers in assert messages do not work properly with BASH 2.x.
The Bourne shell of Solaris, BASH 2.x, and Zsh 3.0.x do not properly catch the
SIGTERM signal. As such, shell interpreter failures due to such things as
unbound variables cannot be caught. (See ``shunit_test_misc.sh``)
.. vim:fileencoding=latin1:ft=rst:spell:tw=80

View File

@ -1,112 +0,0 @@
Release Notes for shUnit2 2.1.6
===============================
This release contains bug fixes and changes. It is also the first release to
support running shunit2 as a standalone program.
Please read the Shell Errata section of the documentation for guidance on how
to meet these requirements.
See the ``CHANGES-2.1.txt`` file for a full list of changes.
New Features
------------
Support for running shUnit2 as a standalone program. This makes it possible for
users to execute their unit tests in a manner that is not dependent on the
location an OS distribution maintainer chose to place shUnit2 in the file
system.
Added support for functions defined like 'function someFunction()'.
Changes and Enhancements
------------------------
Renamed the public ``shunit_tmpDir`` variable to ``SHUNIT_TMPDIR`` to be more
consistent with the ``TMPDIR`` variable.
Bug Fixes
---------
Fixed issue where shunit2 would fail on some distributions when creating a
temporary directory because the **od** command was not present.
Deprecated Features
-------------------
None.
Known Bugs and Issues
---------------------
Zsh requires the ``shwordsplit`` option to be set. See the documentation for
examples of how to do this.
Line numbers in assert messages do not work properly with BASH 2.x.
The Bourne shell of Solaris, BASH 2.x, and Zsh 3.0.x do not properly catch the
SIGTERM signal. As such, shell interpreter failures due to such things as
unbound variables cannot be caught. (See ``shunit_test_misc.sh``)
Tested Platforms
----------------
Cygwin 1.7.9 (Windows XP SP2)
- bash 4.1.10(4)
- dash 0.5.6.1
- ksh (sym-link to pdksh)
- pdksh 5.2.14
- zsh 4.3.11
Linux (Ubuntu Dapper 6.06.2 LTS)
- bash 3.1.17(1)
- dash 0.5.3
- ksh (sym-link to pdksh)
- pdksh 5.2.14-99/07/13.2
- zsh 4.2.5
Linux (Ubuntu Hardy 8.04.4 LTS)
- bash 3.2.39(1)
- dash 0.5.4
- ksh M-1993-12-28
- pdksh 5.2.14-99/07/13.2
- zsh 4.3.4
Linux (Ubuntu Lucid 10.04.2 LTS)
- bash 4.1.5(1)
- dash 0.5.5.1
- ksh JM-93t+-2009-05-01
- pdksh 5.2.14-99/07/13.2
- zsh 4.3.10
Mac OS X 10.6.7
- bash 3.2.48(1)
- ksh M-1993-12-28
- zsh 4.3.9
Solaris 8 U7 x86
- /bin/sh
- bash 2.03.0(1)
- ksh M-11/16/88i
- zsh 3.0.6
Solaris 9 U6 x86
- /bin/sh
- bash 2.05.0(1)
- ksh M-11/16/88i
- zsh 3.0.8
OpenSolaris 2009.06(snv_111b) x86
- /bin/sh
- bash 3.2.25(1)
- ksh 2008-11-04
.. vim:fileencoding=latin1:ft=rst:spell:tw=80

View File

@ -1,13 +0,0 @@
Make it possible to execute a single test by passing the name of the test on
the command line
Add support for '--randomize-order' so that the test order is randomized to
check for dependencies (which shouldn't be there) between tests.
--debug option to display point in source code (line number and such) where the
problem showed up.
assertTrue() just gives 'ASSERT:', nothing else :-(. others too?
upd: assertNull() will give message passed, but nothing else useful :-(
$Revision: 228 $

View File

@ -1,74 +0,0 @@
Coding Standards
================
Variable and Function Names
---------------------------
All shUnit2 specific constants, variables, and functions will be prefixed
appropriately with 'shunit'. This is to distinguish usage in the shUnit2 code
from users own scripts so that the shell name space remains predictable to
users. The exceptions here are the standard ``assertEquals``, etc. functions.
All non-builtin constants and variables will be surrouned with squiggle
brackets, e.g. '${shunit_someVariable}' to improve code readability.
Due to some shells not supporting local variables in functions, care in the
naming and use of variables, both public and private, is very important.
Accidental overriding of the variables can occur easily if care is not taken as
all variables are technically global variables in some shells.
+----------------------------------+---------------------------+
| *type* | *sample* |
+==================================+===========================+
| global public constant | ``SHUNIT_TRUE`` |
+----------------------------------+---------------------------+
| global private constant | ``__SHUNIT_SHELL_FLAGS`` |
+----------------------------------+---------------------------+
| global public variable | not used |
+----------------------------------+---------------------------+
| global private variable | ``__shunit_someVariable`` |
+----------------------------------+---------------------------+
| global macro | ``_SHUNIT_SOME_MACRO_`` |
+----------------------------------+---------------------------+
| public function | ``assertEquals`` |
+----------------------------------+---------------------------+
| public function, local variable | ``shunit_someVariable_`` |
+----------------------------------+---------------------------+
| private function | ``_shunit_someFunction`` |
+----------------------------------+---------------------------+
| private function, local variable | ``_shunit_someVariable_`` |
+----------------------------------+---------------------------+
Where it makes sense, variables can have the first letter of the second and
later words capitalized. For example, the local variable name for the total
number of test cases seen might be ``shunit_totalTestsSeen_``.
Local Variable Cleanup
----------------------
As many shells do not support local variables, no support for cleanup of
variables is present either. As such, all variables local to a function must be
cleared up with the ``unset`` command at the end of each function.
Indentation
-----------
Code block indentation is two (2) spaces, and tabs may not be used. ::
if [ -z 'some string' ]; then
someFunction
fi
Lines of code should be no longer than 80 characters unless absolutely
necessary. When lines are wrapped using the backslash character '\', subsequent
lines should be indented with four (4) spaces so as to differentiate from the
standard spacing of two characters. Tabs may *not* be used. ::
for x in some set of very long set of arguments that make for a very long \
that extends much too long for one line
do
echo ${x}
done
.. vim:fileencoding=latin1:ft=rst:spell:tw=80
.. $Revision: 301 $

View File

@ -1,14 +0,0 @@
The original author of shunit2 is Kate Ward. The following people have
contributed in some way or another to shunit2.
Bryan Larsen
Kevin Van Horn
Maciej Bliziński
Mario Sparada
Mathias Goldau
Richard Jensen
Rob Holland
Rocky Bernstein
wood4321 (of code.google.com)
$Revision: 313 $

View File

@ -1,34 +0,0 @@
Design Doc for shUnit
shUnit is based upon JUnit. The initial ideas for the script came from the book
"Pragmatic Unit Testing - In Java with JUnit" by Andrew Hunt and David Thomas.
The script was written to perform unit testing for log4sh. log4sh had grown
enough that it was becoming difficult to easily test and and verify that the
tests passed for the many different operating systems on which it was being
used.
The functions in shUnit are meant to match those in JUnit as much as possible
where shell allows. In the initial version, there will be no concept of
exceptions (as normal POSIX shell has no concept of them) but attempts to trap
problems will be done.
Programatic Standards:
* SHUNIT_TRUE - public global constant
* __SHUNIT_SHELL_FLAGS - private global constant
* __shunit_oldShellFlags - private global variable
* assertEquals - public unit test function
* shunit_publicFunc - public shUnit function; can be called from parent unit
test script
* _shunit_privateFunc - private shUnit function; should not be called from
parent script. meant for internal use by shUnit
* _su_myVar - variable inside a public function. prefixing with '_su_' to
reduce the chances that a variable outside of shUnit will be overridden.
* _su__myVar - variable inside a private function. prefixing with '_su__' to
reduce the chances that a variable in a shUnit public function, or a variable
outside of shUnit will be overridden.
$Revision: 4 $

View File

@ -1,292 +0,0 @@
/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date: 2007-04-11 11:48:16 +0100 (Wed, 11 Apr 2007) $
:Revision: $Revision: 2791 $
:Copyright: This stylesheet has been placed in the public domain.
:Modified by: Kate Ward <kate.ward@forestent.com>
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left {
clear: left }
img.align-right {
clear: right }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
/*
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
*/
table.footnote {
border-left: solid 1px black;
margin-left: 1px ;
font-size: 80% }
}
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
/*
tt.docutils {
background-color: #eeeeee }
*/
ul.auto-toc {
list-style-type: none }
/* customizations by kward */
h1 { font-size: 133%; border-top:1px solid #CCCCFF; }
h1.title { font-size: 150%; border-top:0px; padding-top: 1em; }
/* div.document { font-size: 90% } */

View File

@ -1,880 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>shUnit2 2.1.x Documentation</title>
<style type="text/css">
/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date: 2007-04-11 11:48:16 +0100 (Wed, 11 Apr 2007) $
:Revision: $Revision: 2791 $
:Copyright: This stylesheet has been placed in the public domain.
:Modified by: Kate Ward <kate.ward@forestent.com>
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left {
clear: left }
img.align-right {
clear: right }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
/*
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
*/
table.footnote {
border-left: solid 1px black;
margin-left: 1px ;
font-size: 80% }
}
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
/*
tt.docutils {
background-color: #eeeeee }
*/
ul.auto-toc {
list-style-type: none }
/* customizations by kward */
h1 { font-size: 133%; border-top:1px solid #CCCCFF; }
h1.title { font-size: 150%; border-top:0px; padding-top: 1em; }
/* div.document { font-size: 90% } */
</style>
</head>
<body>
<div class="document" id="shunit2-2-1-x-documentation">
<h1 class="title">shUnit2 2.1.x Documentation</h1>
<div class="section" id="abstract">
<h1><a class="toc-backref" href="#id1">Abstract</a></h1>
<p><a class="reference external" href="http://shunit2.googlecode.com/">shUnit2</a> is a <a class="reference external" href="http://en.wikipedia.org/wiki/XUnit">xUnit</a> unit test framework for Bourne based shell scripts, and it
is designed to work in a similar manner to <a class="reference external" href="http://www.junit.org/">JUnit</a>, <a class="reference external" href="http://pyunit.sourceforge.net/">PyUnit</a>, etc.. If you have
ever had the desire to write a unit test for a shell script, shUnit2 can do the
job.</p>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#abstract" id="id1">Abstract</a></li>
<li><a class="reference internal" href="#introduction" id="id2">Introduction</a><ul>
<li><a class="reference internal" href="#credits-contributors" id="id3">Credits / Contributors</a></li>
<li><a class="reference internal" href="#feedback" id="id4">Feedback</a></li>
</ul>
</li>
<li><a class="reference internal" href="#quickstart" id="id5">Quickstart</a></li>
<li><a class="reference internal" href="#function-reference" id="id6">Function Reference</a><ul>
<li><a class="reference internal" href="#general-info" id="id7">General Info</a></li>
<li><a class="reference internal" href="#asserts" id="id8">Asserts</a></li>
<li><a class="reference internal" href="#failures" id="id9">Failures</a></li>
<li><a class="reference internal" href="#setup-teardown" id="id10">Setup/Teardown</a></li>
<li><a class="reference internal" href="#skipping" id="id11">Skipping</a></li>
<li><a class="reference internal" href="#suites" id="id12">Suites</a></li>
</ul>
</li>
<li><a class="reference internal" href="#advanced-usage" id="id13">Advanced Usage</a><ul>
<li><a class="reference internal" href="#some-constants-you-can-use" id="id14">Some constants you can use</a></li>
<li><a class="reference internal" href="#error-handling" id="id15">Error handling</a></li>
<li><a class="reference internal" href="#including-line-numbers-in-asserts-macros" id="id16">Including Line Numbers in Asserts (Macros)</a></li>
<li><a class="reference internal" href="#test-skipping" id="id17">Test Skipping</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix" id="id18">Appendix</a><ul>
<li><a class="reference internal" href="#getting-help" id="id19">Getting help</a></li>
<li><a class="reference internal" href="#zsh" id="id20">Zsh</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id2">Introduction</a></h1>
<p>shUnit2 was originally developed to provide a consistent testing solution for
<a class="reference external" href="http://log4sh.sourceforge.net/">log4sh</a>, a shell based logging framework similar to <a class="reference external" href="http://logging.apache.org/">log4j</a>. During the
development of that product, a repeated problem of having things work just fine
under one shell (<tt class="docutils literal">/bin/bash</tt> on Linux to be specific), and then not working
under another shell (<tt class="docutils literal">/bin/sh</tt> on Solaris) kept coming up. Although several
simple tests were run, they were not adequate and did not catch some corner
cases. The decision was finally made to write a proper unit test framework after
multiple brown-bag releases were made. <em>Research was done to look for an
existing product that met the testing requirements, but no adequate product was
found.</em></p>
<p>Tested Operating Systems (varies over time)</p>
<ul class="simple">
<li>Cygwin</li>
<li>FreeBSD (user supported)</li>
<li>Linux (Gentoo, Ubuntu)</li>
<li>Mac OS X</li>
<li>Solaris 8, 9, 10 (inc. OpenSolaris)</li>
</ul>
<p>Tested Shells</p>
<ul class="simple">
<li>Bourne Shell (<strong>sh</strong>)</li>
<li>BASH - GNU Bourne Again SHell (<strong>bash</strong>)</li>
<li>DASH (<strong>dash</strong>)</li>
<li>Korn Shell (<strong>ksh</strong>)</li>
<li>pdksh - Public Domain Korn Shell (<strong>pdksh</strong>)</li>
<li>zsh - Zsh (<strong>zsh</strong>) (since 2.1.2) <em>please see the Zsh shell errata for more
information</em></li>
</ul>
<p>See the appropriate Release Notes for this release
(<tt class="docutils literal"><span class="pre">doc/RELEASE_NOTES-X.X.X.txt</span></tt>) for the list of actual versions tested.</p>
<div class="section" id="credits-contributors">
<h2><a class="toc-backref" href="#id3">Credits / Contributors</a></h2>
<p>A list of contributors to shUnit2 can be found in the source archive in
<tt class="docutils literal">doc/contributors.txt</tt>. Many thanks go out to all those who have contributed
to make this a better tool.</p>
<p>shUnit2 is the original product of many hours of work by Kate Ward, the primary
author of the code. For other products by her, look up <a class="reference external" href="http://log4sh.sourceforge.net/">log4sh</a> or <a class="reference external" href="http://shflags.googlecode.com/">shFlags</a>, or
visit her website at <a class="reference external" href="http://forestent.com/">http://forestent.com/</a>.</p>
</div>
<div class="section" id="feedback">
<h2><a class="toc-backref" href="#id4">Feedback</a></h2>
<p>Feedback is most certainly welcome for this document. Send your additions,
comments and criticisms to the <a class="reference external" href="mailto:shunit2-users&#64;google.com">shunit2-users&#64;google.com</a> mailing list.</p>
</div>
</div>
<div class="section" id="quickstart">
<h1><a class="toc-backref" href="#id5">Quickstart</a></h1>
<p>This section will give a very quick start to running unit tests with shUnit2.
More information is located in later sections.</p>
<p>Here is a quick sample script to show how easy it is to write a unit test in
shell. <em>Note: the script as it stands expects that you are running it from the
``examples`` directory.</em></p>
<pre class="literal-block">
#! /bin/sh
# file: examples/equality_test.sh
testEquality()
{
assertEquals 1 1
}
# load shunit2
. ../src/shell/shunit2
</pre>
<p>Running the unit test should give results similar to the following.</p>
<pre class="literal-block">
testEquality
Ran 1 test.
OK
</pre>
<p>W00t! You've just run your first successful unit test. So, what just happened?
Quite a bit really, and it all happened simply by sourcing the <tt class="docutils literal">shunit2</tt>
library. The basic functionality for the script above goes like this:</p>
<ul class="simple">
<li>When shUnit2 is sourced, it will walk through any functions defined whose
namestart with the string <tt class="docutils literal">test</tt> and add those to an internal list of tests
to execute. Once a list of test functions to be run has been determined,
shunit2 will go to work.</li>
<li>Before any tests are executed, shUnit2 again looks for a function, this time
one named <tt class="docutils literal">oneTimeSetUp()</tt>. If it exists, it will be run. This function is
normally used to setup the environment for all tests to be run. Things like
creating directories for output or setting environment variables are good to
place here. Just so you know, you can also declare a corresponding function
named <tt class="docutils literal">oneTimeTearDown()</tt> function that does the same thing, but once all
the tests have been completed. It is good for removing temporary directories,
etc.</li>
<li>shUnit2 is now ready to run tests. Before doing so though, it again looks for
another function that might be declared, one named <tt class="docutils literal">setUp()</tt>. If the
function exists, it will be run before each test. It is good for resetting the
environment so that each test starts with a clean slate. At this stage, the
first test is finally run. The success of the test is recorded for a report
that will be generated later. After the test is run, shUnit2 looks for a final
function that might be declared, one named <tt class="docutils literal">tearDown()</tt>. If it exists, it
will be run after each test. It is a good place for cleaning up after each
test, maybe doing things like removing files that were created, or removing
directories. This set of steps, <tt class="docutils literal">setUp()</tt> &gt; <tt class="docutils literal">test()</tt> &gt; <tt class="docutils literal">tearDown()</tt>, is
repeated for all of the available tests.</li>
<li>Once all the work is done, shUnit2 will generate the nice report you saw
above. A summary of all the successes and failures will be given so that you
know how well your code is doing.</li>
</ul>
<p>We should now try adding a test that fails. Change your unit test to look like
this.</p>
<pre class="literal-block">
#! /bin/sh
# file: examples/party_test.sh
testEquality()
{
assertEquals 1 1
}
testPartyLikeItIs1999()
{
year=`date '+%Y'`
assertEquals &quot;It's not 1999 :-(&quot; \
'1999' &quot;${year}&quot;
}
# load shunit2
. ../src/shell/shunit2
</pre>
<p>So, what did you get? I guess it told you that this isn't 1999. Bummer, eh?
Hopefully, you noticed a couple of things that were different about the second
test. First, we added an optional message that the user will see if the assert
fails. Second, we did comparisons of strings instead of integers as in the first
test. It doesn't matter whether you are testing for equality of strings or
integers. Both work equally well with shUnit2.</p>
<p>Hopefully, this is enough to get you started with unit testing. If you want a
ton more examples, take a look at the tests provided with <a class="reference external" href="http://log4sh.sourceforge.net/">log4sh</a> or <a class="reference external" href="http://shflags.googlecode.com/">shFlags</a>.
Both provide excellent examples of more advanced usage. shUnit2 was after all
written to help with the unit testing problems that <a class="reference external" href="http://log4sh.sourceforge.net/">log4sh</a> had.</p>
</div>
<div class="section" id="function-reference">
<h1><a class="toc-backref" href="#id6">Function Reference</a></h1>
<div class="section" id="general-info">
<h2><a class="toc-backref" href="#id7">General Info</a></h2>
<p>Any string values passed should be properly quoted -- they should must be
surrounded by single-quote (') or double-quote (&quot;) characters -- so that the
shell will properly parse them.</p>
</div>
<div class="section" id="asserts">
<h2><a class="toc-backref" href="#id8">Asserts</a></h2>
<dl class="docutils">
<dt><tt class="docutils literal">assertEquals [message] expected actual</tt></dt>
<dd>Asserts that <em>expected</em> and <em>actual</em> are equal to one another. The <em>expected</em>
and <em>actual</em> values can be either strings or integer values as both will be
treated as strings. The <em>message</em> is optional, and must be quoted.</dd>
<dt><tt class="docutils literal">assertNotEquals [message] expected actual</tt></dt>
<dd>Asserts that <em>unexpected</em> and <em>actual</em> are not equal to one another. The
<em>unexpected</em> and <em>actual</em> values can be either strings or integer values as
both will be treaded as strings. The <em>message</em> is optional, and must be
quoted.</dd>
<dt><tt class="docutils literal">assertSame [message] expected actual</tt></dt>
<dd>This function is functionally equivalent to <tt class="docutils literal">assertEquals</tt>.</dd>
<dt><tt class="docutils literal">assertNotSame [message] unexpected actual</tt></dt>
<dd>This function is functionally equivalent to <tt class="docutils literal">assertNotEquals</tt>.</dd>
<dt><tt class="docutils literal">assertNull [message] value</tt></dt>
<dd>Asserts that <em>value</em> is <em>null</em>, or in shell terms, a zero-length string. The
<em>value</em> must be a string as an integer value does not translate into a
zero-length string. The <em>message</em> is optional, and must be quoted.</dd>
<dt><tt class="docutils literal">assertNotNull [message] value</tt></dt>
<dd>Asserts that <em>value</em> is <em>not null</em>, or in shell terms, a non-empty string. The
<em>value</em> may be a string or an integer as the later will be parsed as a
non-empty string value. The <em>message</em> is optional, and must be quoted.</dd>
<dt><tt class="docutils literal">assertTrue [message] condition</tt></dt>
<dd><p class="first">Asserts that a given shell test <em>condition</em> is <em>true</em>. The condition can be as
simple as a shell <em>true</em> value (the value <tt class="docutils literal">0</tt> -- equivalent to
<tt class="docutils literal">${SHUNIT_TRUE}</tt>), or a more sophisticated shell conditional expression. The
<em>message</em> is optional, and must be quoted.</p>
<p>A sophisticated shell conditional expression is equivalent to what the <strong>if</strong>
or <strong>while</strong> shell built-ins would use (more specifically, what the <strong>test</strong>
command would use). Testing for example whether some value is greater than
another value can be done this way.</p>
<pre class="literal-block">
assertTrue &quot;[ 34 -gt 23 ]&quot;
</pre>
<p>Testing for the ability to read a file can also be done. This particular test
will fail.</p>
<pre class="literal-block">
assertTrue 'test failed' &quot;[ -r /some/non-existant/file' ]&quot;
</pre>
<p>As the expressions are standard shell <strong>test</strong> expressions, it is possible to
string multiple expressions together with <tt class="docutils literal"><span class="pre">-a</span></tt> and <tt class="docutils literal"><span class="pre">-o</span></tt> in the standard
fashion. This test will succeed as the entire expression evaluates to <em>true</em>.</p>
<pre class="literal-block">
assertTrue 'test failed' '[ 1 -eq 1 -a 2 -eq 2 ]'
</pre>
<p class="last"><em>One word of warning: be very careful with your quoting as shell is not the
most forgiving of bad quoting, and things will fail in strange ways.</em></p>
</dd>
<dt><tt class="docutils literal">assertFalse [message] condition</tt></dt>
<dd><p class="first">Asserts that a given shell test <em>condition</em> is <em>false</em>. The condition can be
as simple as a shell <em>false</em> value (the value <tt class="docutils literal">1</tt> -- equivalent to
<tt class="docutils literal">${SHUNIT_FALSE}</tt>), or a more sophisticated shell conditional expression.
The <em>message</em> is optional, and must be quoted.</p>
<p class="last"><em>For examples of more sophisticated expressions, see ``assertTrue``.</em></p>
</dd>
</dl>
</div>
<div class="section" id="failures">
<h2><a class="toc-backref" href="#id9">Failures</a></h2>
<p>Just to clarify, failures <strong>do not</strong> test the various arguments against one
another. Failures simply fail, optionally with a message, and that is all they
do. If you need to test arguments against one another, use asserts.</p>
<p>If all failures do is fail, why might one use them? There are times when you may
have some very complicated logic that you need to test, and the simple asserts
provided are simply not adequate. You can do your own validation of the code,
use an <tt class="docutils literal">assertTrue ${SHUNIT_TRUE}</tt> if your own tests succeeded, and use a
failure to record a failure.</p>
<dl class="docutils">
<dt><tt class="docutils literal">fail [message]</tt></dt>
<dd>Fails the test immediately. The <em>message</em> is optional, and must be quoted.</dd>
<dt><tt class="docutils literal">failNotEquals [message] unexpected actual</tt></dt>
<dd><p class="first">Fails the test immediately, reporting that the <em>unexpected</em> and <em>actual</em>
values are not equal to one another. The <em>message</em> is optional, and must be
quoted.</p>
<p class="last"><em>Note: no actual comparison of unexpected and actual is done.</em></p>
</dd>
<dt><tt class="docutils literal">failSame [message] expected actual</tt></dt>
<dd><p class="first">Fails the test immediately, reporting that the <em>expected</em> and <em>actual</em> values
are the same. The <em>message</em> is optional, and must be quoted.</p>
<p class="last"><em>Note: no actual comparison of expected and actual is done.</em></p>
</dd>
<dt><tt class="docutils literal">failNotSame [message] expected actual</tt></dt>
<dd><p class="first">Fails the test immediately, reporting that the <em>expected</em> and <em>actual</em> values
are not the same. The <em>message</em> is optional, and must be quoted.</p>
<p class="last"><em>Note: no actual comparison of expected and actual is done.</em></p>
</dd>
</dl>
</div>
<div class="section" id="setup-teardown">
<h2><a class="toc-backref" href="#id10">Setup/Teardown</a></h2>
<dl class="docutils">
<dt><tt class="docutils literal">oneTimeSetUp</tt></dt>
<dd><p class="first">This function can be be optionally overridden by the user in their test suite.</p>
<p class="last">If this function exists, it will be called once before any tests are run. It
is useful to prepare a common environment for all tests.</p>
</dd>
<dt><tt class="docutils literal">oneTimeTearDown</tt></dt>
<dd><p class="first">This function can be be optionally overridden by the user in their test suite.</p>
<p class="last">If this function exists, it will be called once after all tests are completed.
It is useful to clean up the environment after all tests.</p>
</dd>
<dt><tt class="docutils literal">setUp</tt></dt>
<dd><p class="first">This function can be be optionally overridden by the user in their test suite.</p>
<p class="last">If this function exists, it will be called before each test is run. It is
useful to reset the environment before each test.</p>
</dd>
<dt><tt class="docutils literal">tearDown</tt></dt>
<dd><p class="first">This function can be be optionally overridden by the user in their test suite.</p>
<p class="last">If this function exists, it will be called after each test completes. It is
useful to clean up the environment after each test.</p>
</dd>
</dl>
</div>
<div class="section" id="skipping">
<h2><a class="toc-backref" href="#id11">Skipping</a></h2>
<dl class="docutils">
<dt><tt class="docutils literal">startSkipping</tt></dt>
<dd>This function forces the remaining <em>assert</em> and <em>fail</em> functions to be
&quot;skipped&quot;, i.e. they will have no effect. Each function skipped will be
recorded so that the total of asserts and fails will not be altered.</dd>
<dt><tt class="docutils literal">endSkipping</tt></dt>
<dd>This function returns calls to the <em>assert</em> and <em>fail</em> functions to their
default behavior, i.e. they will be called.</dd>
<dt><tt class="docutils literal">isSkipping</tt></dt>
<dd>This function returns the current state of skipping. It can be compared
against <tt class="docutils literal">${SHUNIT_TRUE}</tt> or <tt class="docutils literal">${SHUNIT_FALSE}</tt> if desired.</dd>
</dl>
</div>
<div class="section" id="suites">
<h2><a class="toc-backref" href="#id12">Suites</a></h2>
<p>The default behavior of shUnit2 is that all tests will be found dynamically. If
you have a specific set of tests you want to run, or you don't want to use the
standard naming scheme of prefixing your tests with <tt class="docutils literal">test</tt>, these functions
are for you. Most users will never use them though.</p>
<dl class="docutils">
<dt><tt class="docutils literal">suite</tt></dt>
<dd><p class="first">This function can be optionally overridden by the user in their test suite.</p>
<p class="last">If this function exists, it will be called when <tt class="docutils literal">shunit2</tt> is sourced. If it
does not exist, shUnit2 will search the parent script for all functions
beginning with the word <tt class="docutils literal">test</tt>, and they will be added dynamically to the
test suite.</p>
</dd>
<dt><tt class="docutils literal">suite_addTest name</tt></dt>
<dd>This function adds a function named <em>name</em> to the list of tests scheduled for
execution as part of this test suite. This function should only be called from
within the <tt class="docutils literal">suite()</tt> function.</dd>
</dl>
</div>
</div>
<div class="section" id="advanced-usage">
<h1><a class="toc-backref" href="#id13">Advanced Usage</a></h1>
<p>This section covers several advanced usage topics.</p>
<div class="section" id="some-constants-you-can-use">
<h2><a class="toc-backref" href="#id14">Some constants you can use</a></h2>
<p>There are several constants provided by shUnit2 as variables that might be of
use to you.</p>
<p>Predefined</p>
<table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">SHUNIT_VERSION</tt></td>
<td>The version of shUnit2 you are running.</td>
</tr>
<tr><td><tt class="docutils literal">SHUNIT_TRUE</tt></td>
<td>Standard shell <em>true</em> value (the integer value 0).</td>
</tr>
<tr><td><tt class="docutils literal">SHUNIT_FALSE</tt></td>
<td>Standard shell <em>false</em> value (the integer value 1).</td>
</tr>
<tr><td><tt class="docutils literal">SHUNIT_ERROR</tt></td>
<td>The integer value 2.</td>
</tr>
<tr><td><tt class="docutils literal">SHUNIT_TMPDIR</tt></td>
<td>Path to temporary directory that will be automatically
cleaned up upon exit of shUnit2.</td>
</tr>
</tbody>
</table>
<p>User defined</p>
<table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">SHUNIT_PARENT</tt></td>
<td>The filename of the shell script containing the tests. This
is needed specifically for Zsh support.</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="error-handling">
<h2><a class="toc-backref" href="#id15">Error handling</a></h2>
<p>The constants values <tt class="docutils literal">SHUNIT_TRUE</tt>, <tt class="docutils literal">SHUNIT_FALSE</tt>, and <tt class="docutils literal">SHUNIT_ERROR</tt> are
returned from nearly every function to indicate the success or failure of the
function. Additionally the variable <tt class="docutils literal">flags_error</tt> is filled with a detailed
error message if any function returns with a <tt class="docutils literal">SHUNIT_ERROR</tt> value.</p>
</div>
<div class="section" id="including-line-numbers-in-asserts-macros">
<h2><a class="toc-backref" href="#id16">Including Line Numbers in Asserts (Macros)</a></h2>
<p>If you include lots of assert statements in an individual test function, it can
become difficult to determine exactly which assert was thrown unless your
messages are unique. To help somewhat, line numbers can be included in the
assert messages. To enable this, a special shell &quot;macro&quot; must be used rather
than the standard assert calls. <em>Shell doesn't actually have macros; the name is
used here as the operation is similar to a standard macro.</em></p>
<p>For example, to include line numbers for a <tt class="docutils literal">assertEquals()</tt> function call,
replace the <tt class="docutils literal">assertEquals()</tt> with <tt class="docutils literal">${_ASSERT_EQUALS_}</tt>.</p>
<p>Example&nbsp;--&nbsp;Asserts with and without line numbers</p>
<pre class="literal-block">
#! /bin/sh
# file: examples/lineno_test.sh
testLineNo()
{
# this assert will have line numbers included (e.g. &quot;ASSERT:[123] ...&quot;)
echo &quot;ae: ${_ASSERT_EQUALS_}&quot;
${_ASSERT_EQUALS_} 'not equal' 1 2
# this assert will not have line numbers included (e.g. &quot;ASSERT: ...&quot;)
assertEquals 'not equal' 1 2
}
# load shunit2
. ../src/shell/shunit2
</pre>
<p>Notes:</p>
<ol class="arabic">
<li><p class="first">Due to how shell parses command-line arguments, all strings used with macros
should be quoted twice. Namely, single-quotes must be converted to
single-double-quotes, and vice-versa. If the string being passed is
absolutely for sure not empty, the extra quoting is not necessary.</p>
<p>Normal <tt class="docutils literal">assertEquals</tt> call.</p>
<pre class="literal-block">
assertEquals 'some message' 'x' ''
</pre>
<p>Macro <tt class="docutils literal">_ASSERT_EQUALS_</tt> call. Note the extra quoting around the <em>message</em>
and the <em>null</em> value.</p>
<pre class="literal-block">
_ASSERT_EQUALS_ '&quot;some message&quot;' 'x' '&quot;&quot;'
</pre>
</li>
<li><p class="first">Line numbers are not supported in all shells. If a shell does not support
them, no errors will be thrown. Supported shells include: <strong>bash</strong> (&gt;=3.0),
<strong>ksh</strong>, <strong>pdksh</strong>, and <strong>zsh</strong>.</p>
</li>
</ol>
</div>
<div class="section" id="test-skipping">
<h2><a class="toc-backref" href="#id17">Test Skipping</a></h2>
<p>There are times where the test code you have written is just not applicable to
the system you are running on. This section describes how to skip these tests
but maintain the total test count.</p>
<p>Probably the easiest example would be shell code that is meant to run under the
<strong>bash</strong> shell, but the unit test is running under the Bourne shell. There are
things that just won't work. The following test code demonstrates two sample
functions, one that will be run under any shell, and the another that will run
only under the <strong>bash</strong> shell.</p>
<p>Example&nbsp;-- math include</p>
<pre class="literal-block">
# available as examples/math.inc
add_generic()
{
num_a=$1
num_b=$2
expr $1 + $2
}
add_bash()
{
num_a=$1
num_b=$2
echo $(($1 + $2))
}
</pre>
<p>And here is a corresponding unit test that correctly skips the <tt class="docutils literal">add_bash()</tt>
function when the unit test is not running under the <strong>bash</strong> shell.</p>
<p>Example&nbsp;-- math unit test</p>
<pre class="literal-block">
#! /bin/sh
# available as examples/math_test.sh
testAdding()
{
result=`add_generic 1 2`
assertEquals \
&quot;the result of '${result}' was wrong&quot; \
3 &quot;${result}&quot;
# disable non-generic tests
[ -z &quot;${BASH_VERSION:-}&quot; ] &amp;&amp; startSkipping
result=`add_bash 1 2`
assertEquals \
&quot;the result of '${result}' was wrong&quot; \
3 &quot;${result}&quot;
}
oneTimeSetUp()
{
# load include to test
. ./math.inc
}
# load and run shUnit2
. ../src/shell/shunit2
</pre>
<p>Running the above test under the <strong>bash</strong> shell will result in the following
output.</p>
<pre class="literal-block">
$ /bin/bash math_test.sh
testAdding
Ran 1 test.
OK
</pre>
<p>But, running the test under any other Unix shell will result in the following
output.</p>
<pre class="literal-block">
$ /bin/ksh math_test.sh
testAdding
Ran 1 test.
OK (skipped=1)
</pre>
<p>As you can see, the total number of tests has not changed, but the report
indicates that some tests were skipped.</p>
<p>Skipping can be controlled with the following functions: <tt class="docutils literal">startSkipping()</tt>,
<tt class="docutils literal">stopSkipping()</tt>, and <tt class="docutils literal">isSkipping()</tt>. Once skipping is enabled, it will
remain enabled until the end of the current test function call, after which
skipping is disabled.</p>
</div>
</div>
<div class="section" id="appendix">
<h1><a class="toc-backref" href="#id18">Appendix</a></h1>
<div class="section" id="getting-help">
<h2><a class="toc-backref" href="#id19">Getting help</a></h2>
<p>For help, please send requests to either the <a class="reference external" href="mailto:shunit2-users&#64;googlegroups.com">shunit2-users&#64;googlegroups.com</a>
mailing list (archives available on the web at
<a class="reference external" href="http://groups.google.com/group/shunit2-users">http://groups.google.com/group/shunit2-users</a>) or directly to
Kate Ward &lt;kate dot ward at forestent dot com&gt;.</p>
</div>
<div class="section" id="zsh">
<h2><a class="toc-backref" href="#id20">Zsh</a></h2>
<p>For compatibility with Zsh, there is one requirement that must be met -- the
<tt class="docutils literal">shwordsplit</tt> option must be set. There are three ways to accomplish this.</p>
<ol class="arabic">
<li><p class="first">In the unit-test script, add the following shell code snippet before sourcing
the <tt class="docutils literal">shunit2</tt> library.</p>
<pre class="literal-block">
setopt shwordsplit
</pre>
</li>
<li><p class="first">When invoking <strong>zsh</strong> from either the command-line or as a script with
<tt class="docutils literal">#!</tt>, add the <tt class="docutils literal"><span class="pre">-y</span></tt> parameter.</p>
<pre class="literal-block">
#! /bin/zsh -y
</pre>
</li>
<li><p class="first">When invoking <strong>zsh</strong> from the command-line, add <tt class="docutils literal"><span class="pre">-o</span> shwordsplit <span class="pre">--</span></tt> as
parameters before the script name.</p>
<pre class="literal-block">
$ zsh -o shwordsplit -- some_script
</pre>
</li>
</ol>
<!-- generate HTML using rst2html from Docutils of -->
<!-- http://docutils.sourceforge.net/ -->
<!-- -->
<!-- vim:fileencoding=latin1:ft=rst:spell:sts=2:sw=2:tw=80 -->
<!-- $Revision: 233 $ -->
</div>
</div>
</div>
</body>
</html>

View File

@ -1,562 +0,0 @@
===========================
shUnit2 2.1.x Documentation
===========================
Abstract
========
shUnit2_ is a xUnit_ unit test framework for Bourne based shell scripts, and it
is designed to work in a similar manner to JUnit_, PyUnit_, etc.. If you have
ever had the desire to write a unit test for a shell script, shUnit2 can do the
job.
.. contents:: Table of Contents
:depth: 2
Introduction
============
shUnit2 was originally developed to provide a consistent testing solution for
log4sh_, a shell based logging framework similar to log4j_. During the
development of that product, a repeated problem of having things work just fine
under one shell (``/bin/bash`` on Linux to be specific), and then not working
under another shell (``/bin/sh`` on Solaris) kept coming up. Although several
simple tests were run, they were not adequate and did not catch some corner
cases. The decision was finally made to write a proper unit test framework after
multiple brown-bag releases were made. *Research was done to look for an
existing product that met the testing requirements, but no adequate product was
found.*
Tested Operating Systems (varies over time)
- Cygwin
- FreeBSD (user supported)
- Linux (Gentoo, Ubuntu)
- Mac OS X
- Solaris 8, 9, 10 (inc. OpenSolaris)
Tested Shells
- Bourne Shell (**sh**)
- BASH - GNU Bourne Again SHell (**bash**)
- DASH (**dash**)
- Korn Shell (**ksh**)
- pdksh - Public Domain Korn Shell (**pdksh**)
- zsh - Zsh (**zsh**) (since 2.1.2) *please see the Zsh shell errata for more
information*
See the appropriate Release Notes for this release
(``doc/RELEASE_NOTES-X.X.X.txt``) for the list of actual versions tested.
Credits / Contributors
----------------------
A list of contributors to shUnit2 can be found in the source archive in
``doc/contributors.txt``. Many thanks go out to all those who have contributed
to make this a better tool.
shUnit2 is the original product of many hours of work by Kate Ward, the primary
author of the code. For other products by her, look up log4sh_ or shFlags_, or
visit her website at http://forestent.com/.
Feedback
--------
Feedback is most certainly welcome for this document. Send your additions,
comments and criticisms to the shunit2-users@google.com mailing list.
Quickstart
==========
This section will give a very quick start to running unit tests with shUnit2.
More information is located in later sections.
Here is a quick sample script to show how easy it is to write a unit test in
shell. *Note: the script as it stands expects that you are running it from the
``examples`` directory.* ::
#! /bin/sh
# file: examples/equality_test.sh
testEquality()
{
assertEquals 1 1
}
# load shunit2
. ../src/shell/shunit2
Running the unit test should give results similar to the following. ::
testEquality
Ran 1 test.
OK
W00t! You've just run your first successful unit test. So, what just happened?
Quite a bit really, and it all happened simply by sourcing the ``shunit2``
library. The basic functionality for the script above goes like this:
- When shUnit2 is sourced, it will walk through any functions defined whose
namestart with the string ``test`` and add those to an internal list of tests
to execute. Once a list of test functions to be run has been determined,
shunit2 will go to work.
- Before any tests are executed, shUnit2 again looks for a function, this time
one named ``oneTimeSetUp()``. If it exists, it will be run. This function is
normally used to setup the environment for all tests to be run. Things like
creating directories for output or setting environment variables are good to
place here. Just so you know, you can also declare a corresponding function
named ``oneTimeTearDown()`` function that does the same thing, but once all
the tests have been completed. It is good for removing temporary directories,
etc.
- shUnit2 is now ready to run tests. Before doing so though, it again looks for
another function that might be declared, one named ``setUp()``. If the
function exists, it will be run before each test. It is good for resetting the
environment so that each test starts with a clean slate. At this stage, the
first test is finally run. The success of the test is recorded for a report
that will be generated later. After the test is run, shUnit2 looks for a final
function that might be declared, one named ``tearDown()``. If it exists, it
will be run after each test. It is a good place for cleaning up after each
test, maybe doing things like removing files that were created, or removing
directories. This set of steps, ``setUp()`` > ``test()`` > ``tearDown()``, is
repeated for all of the available tests.
- Once all the work is done, shUnit2 will generate the nice report you saw
above. A summary of all the successes and failures will be given so that you
know how well your code is doing.
We should now try adding a test that fails. Change your unit test to look like
this. ::
#! /bin/sh
# file: examples/party_test.sh
testEquality()
{
assertEquals 1 1
}
testPartyLikeItIs1999()
{
year=`date '+%Y'`
assertEquals "It's not 1999 :-(" \
'1999' "${year}"
}
# load shunit2
. ../src/shell/shunit2
So, what did you get? I guess it told you that this isn't 1999. Bummer, eh?
Hopefully, you noticed a couple of things that were different about the second
test. First, we added an optional message that the user will see if the assert
fails. Second, we did comparisons of strings instead of integers as in the first
test. It doesn't matter whether you are testing for equality of strings or
integers. Both work equally well with shUnit2.
Hopefully, this is enough to get you started with unit testing. If you want a
ton more examples, take a look at the tests provided with log4sh_ or shFlags_.
Both provide excellent examples of more advanced usage. shUnit2 was after all
written to help with the unit testing problems that log4sh_ had.
Function Reference
==================
General Info
------------
Any string values passed should be properly quoted -- they should must be
surrounded by single-quote (') or double-quote (") characters -- so that the
shell will properly parse them.
Asserts
-------
``assertEquals [message] expected actual``
Asserts that *expected* and *actual* are equal to one another. The *expected*
and *actual* values can be either strings or integer values as both will be
treated as strings. The *message* is optional, and must be quoted.
``assertNotEquals [message] expected actual``
Asserts that *unexpected* and *actual* are not equal to one another. The
*unexpected* and *actual* values can be either strings or integer values as
both will be treaded as strings. The *message* is optional, and must be
quoted.
``assertSame [message] expected actual``
This function is functionally equivalent to ``assertEquals``.
``assertNotSame [message] unexpected actual``
This function is functionally equivalent to ``assertNotEquals``.
``assertNull [message] value``
Asserts that *value* is *null*, or in shell terms, a zero-length string. The
*value* must be a string as an integer value does not translate into a
zero-length string. The *message* is optional, and must be quoted.
``assertNotNull [message] value``
Asserts that *value* is *not null*, or in shell terms, a non-empty string. The
*value* may be a string or an integer as the later will be parsed as a
non-empty string value. The *message* is optional, and must be quoted.
``assertTrue [message] condition``
Asserts that a given shell test *condition* is *true*. The condition can be as
simple as a shell *true* value (the value ``0`` -- equivalent to
``${SHUNIT_TRUE}``), or a more sophisticated shell conditional expression. The
*message* is optional, and must be quoted.
A sophisticated shell conditional expression is equivalent to what the **if**
or **while** shell built-ins would use (more specifically, what the **test**
command would use). Testing for example whether some value is greater than
another value can be done this way. ::
assertTrue "[ 34 -gt 23 ]"
Testing for the ability to read a file can also be done. This particular test
will fail. ::
assertTrue 'test failed' "[ -r /some/non-existant/file' ]"
As the expressions are standard shell **test** expressions, it is possible to
string multiple expressions together with ``-a`` and ``-o`` in the standard
fashion. This test will succeed as the entire expression evaluates to *true*.
::
assertTrue 'test failed' '[ 1 -eq 1 -a 2 -eq 2 ]'
*One word of warning: be very careful with your quoting as shell is not the
most forgiving of bad quoting, and things will fail in strange ways.*
``assertFalse [message] condition``
Asserts that a given shell test *condition* is *false*. The condition can be
as simple as a shell *false* value (the value ``1`` -- equivalent to
``${SHUNIT_FALSE}``), or a more sophisticated shell conditional expression.
The *message* is optional, and must be quoted.
*For examples of more sophisticated expressions, see ``assertTrue``.*
Failures
--------
Just to clarify, failures **do not** test the various arguments against one
another. Failures simply fail, optionally with a message, and that is all they
do. If you need to test arguments against one another, use asserts.
If all failures do is fail, why might one use them? There are times when you may
have some very complicated logic that you need to test, and the simple asserts
provided are simply not adequate. You can do your own validation of the code,
use an ``assertTrue ${SHUNIT_TRUE}`` if your own tests succeeded, and use a
failure to record a failure.
``fail [message]``
Fails the test immediately. The *message* is optional, and must be quoted.
``failNotEquals [message] unexpected actual``
Fails the test immediately, reporting that the *unexpected* and *actual*
values are not equal to one another. The *message* is optional, and must be
quoted.
*Note: no actual comparison of unexpected and actual is done.*
``failSame [message] expected actual``
Fails the test immediately, reporting that the *expected* and *actual* values
are the same. The *message* is optional, and must be quoted.
*Note: no actual comparison of expected and actual is done.*
``failNotSame [message] expected actual``
Fails the test immediately, reporting that the *expected* and *actual* values
are not the same. The *message* is optional, and must be quoted.
*Note: no actual comparison of expected and actual is done.*
Setup/Teardown
--------------
``oneTimeSetUp``
This function can be be optionally overridden by the user in their test suite.
If this function exists, it will be called once before any tests are run. It
is useful to prepare a common environment for all tests.
``oneTimeTearDown``
This function can be be optionally overridden by the user in their test suite.
If this function exists, it will be called once after all tests are completed.
It is useful to clean up the environment after all tests.
``setUp``
This function can be be optionally overridden by the user in their test suite.
If this function exists, it will be called before each test is run. It is
useful to reset the environment before each test.
``tearDown``
This function can be be optionally overridden by the user in their test suite.
If this function exists, it will be called after each test completes. It is
useful to clean up the environment after each test.
Skipping
--------
``startSkipping``
This function forces the remaining *assert* and *fail* functions to be
"skipped", i.e. they will have no effect. Each function skipped will be
recorded so that the total of asserts and fails will not be altered.
``endSkipping``
This function returns calls to the *assert* and *fail* functions to their
default behavior, i.e. they will be called.
``isSkipping``
This function returns the current state of skipping. It can be compared
against ``${SHUNIT_TRUE}`` or ``${SHUNIT_FALSE}`` if desired.
Suites
------
The default behavior of shUnit2 is that all tests will be found dynamically. If
you have a specific set of tests you want to run, or you don't want to use the
standard naming scheme of prefixing your tests with ``test``, these functions
are for you. Most users will never use them though.
``suite``
This function can be optionally overridden by the user in their test suite.
If this function exists, it will be called when ``shunit2`` is sourced. If it
does not exist, shUnit2 will search the parent script for all functions
beginning with the word ``test``, and they will be added dynamically to the
test suite.
``suite_addTest name``
This function adds a function named *name* to the list of tests scheduled for
execution as part of this test suite. This function should only be called from
within the ``suite()`` function.
Advanced Usage
==============
This section covers several advanced usage topics.
Some constants you can use
--------------------------
There are several constants provided by shUnit2 as variables that might be of
use to you.
Predefined
================== ===========================================================
``SHUNIT_VERSION`` The version of shUnit2 you are running.
``SHUNIT_TRUE`` Standard shell *true* value (the integer value 0).
``SHUNIT_FALSE`` Standard shell *false* value (the integer value 1).
``SHUNIT_ERROR`` The integer value 2.
``SHUNIT_TMPDIR`` Path to temporary directory that will be automatically
cleaned up upon exit of shUnit2.
================== ===========================================================
User defined
================== ===========================================================
``SHUNIT_PARENT`` The filename of the shell script containing the tests. This
is needed specifically for Zsh support.
================== ===========================================================
Error handling
--------------
The constants values ``SHUNIT_TRUE``, ``SHUNIT_FALSE``, and ``SHUNIT_ERROR`` are
returned from nearly every function to indicate the success or failure of the
function. Additionally the variable ``flags_error`` is filled with a detailed
error message if any function returns with a ``SHUNIT_ERROR`` value.
Including Line Numbers in Asserts (Macros)
------------------------------------------
If you include lots of assert statements in an individual test function, it can
become difficult to determine exactly which assert was thrown unless your
messages are unique. To help somewhat, line numbers can be included in the
assert messages. To enable this, a special shell "macro" must be used rather
than the standard assert calls. *Shell doesn't actually have macros; the name is
used here as the operation is similar to a standard macro.*
For example, to include line numbers for a ``assertEquals()`` function call,
replace the ``assertEquals()`` with ``${_ASSERT_EQUALS_}``.
Example -- Asserts with and without line numbers ::
#! /bin/sh
# file: examples/lineno_test.sh
testLineNo()
{
# this assert will have line numbers included (e.g. "ASSERT:[123] ...")
echo "ae: ${_ASSERT_EQUALS_}"
${_ASSERT_EQUALS_} 'not equal' 1 2
# this assert will not have line numbers included (e.g. "ASSERT: ...")
assertEquals 'not equal' 1 2
}
# load shunit2
. ../src/shell/shunit2
Notes:
#. Due to how shell parses command-line arguments, all strings used with macros
should be quoted twice. Namely, single-quotes must be converted to
single-double-quotes, and vice-versa. If the string being passed is
absolutely for sure not empty, the extra quoting is not necessary.
Normal ``assertEquals`` call. ::
assertEquals 'some message' 'x' ''
Macro ``_ASSERT_EQUALS_`` call. Note the extra quoting around the *message*
and the *null* value. ::
_ASSERT_EQUALS_ '"some message"' 'x' '""'
#. Line numbers are not supported in all shells. If a shell does not support
them, no errors will be thrown. Supported shells include: **bash** (>=3.0),
**ksh**, **pdksh**, and **zsh**.
Test Skipping
-------------
There are times where the test code you have written is just not applicable to
the system you are running on. This section describes how to skip these tests
but maintain the total test count.
Probably the easiest example would be shell code that is meant to run under the
**bash** shell, but the unit test is running under the Bourne shell. There are
things that just won't work. The following test code demonstrates two sample
functions, one that will be run under any shell, and the another that will run
only under the **bash** shell.
Example -- math include ::
# available as examples/math.inc
add_generic()
{
num_a=$1
num_b=$2
expr $1 + $2
}
add_bash()
{
num_a=$1
num_b=$2
echo $(($1 + $2))
}
And here is a corresponding unit test that correctly skips the ``add_bash()``
function when the unit test is not running under the **bash** shell.
Example -- math unit test ::
#! /bin/sh
# available as examples/math_test.sh
testAdding()
{
result=`add_generic 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
# disable non-generic tests
[ -z "${BASH_VERSION:-}" ] && startSkipping
result=`add_bash 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
}
oneTimeSetUp()
{
# load include to test
. ./math.inc
}
# load and run shUnit2
. ../src/shell/shunit2
Running the above test under the **bash** shell will result in the following
output. ::
$ /bin/bash math_test.sh
testAdding
Ran 1 test.
OK
But, running the test under any other Unix shell will result in the following
output. ::
$ /bin/ksh math_test.sh
testAdding
Ran 1 test.
OK (skipped=1)
As you can see, the total number of tests has not changed, but the report
indicates that some tests were skipped.
Skipping can be controlled with the following functions: ``startSkipping()``,
``stopSkipping()``, and ``isSkipping()``. Once skipping is enabled, it will
remain enabled until the end of the current test function call, after which
skipping is disabled.
Appendix
========
Getting help
------------
For help, please send requests to either the shunit2-users@googlegroups.com
mailing list (archives available on the web at
http://groups.google.com/group/shunit2-users) or directly to
Kate Ward <kate dot ward at forestent dot com>.
Zsh
---
For compatibility with Zsh, there is one requirement that must be met -- the
``shwordsplit`` option must be set. There are three ways to accomplish this.
#. In the unit-test script, add the following shell code snippet before sourcing
the ``shunit2`` library. ::
setopt shwordsplit
#. When invoking **zsh** from either the command-line or as a script with
``#!``, add the ``-y`` parameter. ::
#! /bin/zsh -y
#. When invoking **zsh** from the command-line, add ``-o shwordsplit --`` as
parameters before the script name. ::
$ zsh -o shwordsplit -- some_script
.. _log4sh: http://log4sh.sourceforge.net/
.. _log4j: http://logging.apache.org/
.. _JUnit: http://www.junit.org/
.. _PyUnit: http://pyunit.sourceforge.net/
.. _shFlags: http://shflags.googlecode.com/
.. _shUnit2: http://shunit2.googlecode.com/
.. _xUnit: http://en.wikipedia.org/wiki/XUnit
.. generate HTML using rst2html from Docutils of
.. http://docutils.sourceforge.net/
..
.. vim:fileencoding=latin1:ft=rst:spell:sts=2:sw=2:tw=80
.. $Revision: 233 $

View File

@ -1,10 +0,0 @@
#! /bin/sh
# file: examples/equality_test.sh
testEquality()
{
assertEquals 1 1
}
# load shunit2
. ../src/shunit2

View File

@ -1,16 +0,0 @@
#! /bin/sh
# file: examples/lineno_test.sh
testLineNo()
{
# this assert will have line numbers included (e.g. "ASSERT:[123] ...") if
# they are supported.
echo "_ASSERT_EQUALS_ macro value: ${_ASSERT_EQUALS_}"
${_ASSERT_EQUALS_} 'not equal' 1 2
# this assert will not have line numbers included (e.g. "ASSERT: ...")
assertEquals 'not equal' 1 2
}
# load shunit2
. ../src/shunit2

View File

@ -1,17 +0,0 @@
# available as examples/math.inc
add_generic()
{
num_a=$1
num_b=$2
expr $1 + $2
}
add_bash()
{
num_a=$1
num_b=$2
echo $(($1 + $2))
}

View File

@ -1,27 +0,0 @@
#! /bin/sh
# available as examples/math_test.sh
testAdding()
{
result=`add_generic 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
# disable non-generic tests
[ -z "${BASH_VERSION:-}" ] && startSkipping
result=`add_bash 1 2`
assertEquals \
"the result of '${result}' was wrong" \
3 "${result}"
}
oneTimeSetUp()
{
# load include to test
. ./math.inc
}
# load and run shUnit2
. ../src/shunit2

View File

@ -1,89 +0,0 @@
#!/bin/sh
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# Example unit test for the mkdir command.
#
# There are times when an existing shell script needs to be tested. In this
# example, we will test several aspects of the the mkdir command, but the
# techniques could be used for any existing shell script.
#-----------------------------------------------------------------------------
# suite tests
#
testMissingDirectoryCreation()
{
${mkdirCmd} "${testDir}" >${stdoutF} 2>${stderrF}
rtrn=$?
th_assertTrueWithNoOutput ${rtrn} "${stdoutF}" "${stderrF}"
assertTrue 'directory missing' "[ -d '${testDir}' ]"
}
testExistingDirectoryCreationFails()
{
# create a directory to test against
${mkdirCmd} "${testDir}"
# test for expected failure while trying to create directory that exists
${mkdirCmd} "${testDir}" >${stdoutF} 2>${stderrF}
rtrn=$?
assertFalse 'expecting return code of 1 (false)' ${rtrn}
assertNull 'unexpected output to stdout' "`cat ${stdoutF}`"
assertNotNull 'expected error message to stderr' "`cat ${stderrF}`"
assertTrue 'directory missing' "[ -d '${testDir}' ]"
}
testRecursiveDirectoryCreation()
{
testDir2="${testDir}/test2"
${mkdirCmd} -p "${testDir2}" >${stdoutF} 2>${stderrF}
rtrn=$?
th_assertTrueWithNoOutput ${rtrn} "${stdoutF}" "${stderrF}"
assertTrue 'first directory missing' "[ -d '${testDir}' ]"
assertTrue 'second directory missing' "[ -d '${testDir2}' ]"
}
#-----------------------------------------------------------------------------
# suite functions
#
th_assertTrueWithNoOutput()
{
th_return_=$1
th_stdout_=$2
th_stderr_=$3
assertFalse 'unexpected output to STDOUT' "[ -s '${th_stdout_}' ]"
assertFalse 'unexpected output to STDERR' "[ -s '${th_stderr_}' ]"
unset th_return_ th_stdout_ th_stderr_
}
oneTimeSetUp()
{
outputDir="${SHUNIT_TMPDIR}/output"
mkdir "${outputDir}"
stdoutF="${outputDir}/stdout"
stderrF="${outputDir}/stderr"
mkdirCmd='mkdir' # save command name in variable to make future changes easy
testDir="${SHUNIT_TMPDIR}/some_test_dir"
}
tearDown()
{
rm -fr "${testDir}"
}
# load and run shUnit2
[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0
. ../src/shunit2

View File

@ -1,17 +0,0 @@
#! /bin/sh
# file: examples/party_test.sh
testEquality()
{
assertEquals 1 1
}
testPartyLikeItIs1999()
{
year=`date '+%Y'`
assertEquals "It's not 1999 :-(" \
'1999' "${year}"
}
# load shunit2
. ../src/shunit2

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
# $Id: shlib 14 2007-02-18 19:43:41Z sfsetse $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License).
# Author: kate.ward@forestent.com (Kate Ward)
#
# Library of shell functions.
# Convert a relative path into it's absolute equivalent.
#
# This function will automatically prepend the current working directory if the
# path is not already absolute. It then removes all parent references (../) to
# reconstruct the proper absolute path.
#
# Args:
# shlib_path_: string: relative path
# Outputs:
# string: absolute path
shlib_relToAbsPath()
{
shlib_path_=$1
# prepend current directory to relative paths
echo "${shlib_path_}" |grep '^/' >/dev/null 2>&1 \
|| shlib_path_="`pwd`/${shlib_path_}"
# clean up the path. if all seds supported true regular expressions, then
# this is what it would be:
shlib_old_=${shlib_path_}
while true; do
shlib_new_=`echo "${shlib_old_}" |sed 's/[^/]*\/\.\.\/*//g;s/\/\.\//\//'`
[ "${shlib_old_}" = "${shlib_new_}" ] && break
shlib_old_=${shlib_new_}
done
echo "${shlib_new_}"
unset shlib_path_ shlib_old_ shlib_new_
}

View File

@ -1,227 +0,0 @@
#! /bin/sh
# $Id: versions 100 2008-11-15 20:24:03Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# This library provides reusable functions that determine actual names and
# versions of installed shells and the OS. The library can also be run as a
# script if set execuatable.
ARGV0=`basename "$0"`
LSB_RELEASE='/etc/lsb-release'
VERSIONS_SHELLS="/bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/sh /bin/zsh"
TRUE=0
FALSE=1
ERROR=2
__versions_haveStrings=${ERROR}
#------------------------------------------------------------------------------
# functions
#
versions_osName()
{
os_name_='unrecognized'
os_system_=`uname -s`
case ${os_system_} in
CYGWIN_NT-*) os_name_='Cygwin' ;;
Darwin) os_name_='Mac OS X' ;;
FreeBSD) os_name_='FreeBSD' ;;
Linux) os_name_='Linux' ;;
SunOS)
if grep 'OpenSolaris' /etc/release >/dev/null; then
os_name_='OpenSolaris'
else
os_name_='Solaris'
fi
;;
esac
echo ${os_name_}
unset os_name_ os_system_
}
versions_osVersion()
{
os_version_='unrecognized'
os_system_=`uname -s`
os_release_=`uname -r`
case ${os_system_} in
CYGWIN_NT-*)
os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]\.[0-9]*\).*'`
;;
Darwin)
major_='10'
sub_=`echo ${os_release_} |sed 's/^[0-9]*\.\([0-9]*\)\.[0-9]*$/\1/'`
case ${os_release_} in
8.*) minor_='4' ;;
9.*) minor_='5' ;;
10.*) minor_='6' ;;
*) minor_='X'; sub_='X' ;;
esac
os_version_="${major_}.${minor_}.${sub_}"
;;
FreeBSD)
os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]*\)-.*'`
;;
Linux)
if [ -r "${LSB_RELEASE}" ]; then
if grep -q 'DISTRIB_ID=Ubuntu' "${LSB_RELEASE}"; then
os_version_=`cat "${LSB_RELEASE}" \
|awk -F= '$1~/DISTRIB_DESCRIPTION/{print $2}' \
|sed 's/"//g;s/ /-/g'`
fi
elif [ -r '/etc/redhat-release' ]; then
os_version_=`cat /etc/redhat-release`
fi
;;
SunOS)
if grep 'OpenSolaris' /etc/release >/dev/null; then
os_version_=`grep 'OpenSolaris' /etc/release |awk '{print $2"("$3")"}'`
else
major_=`echo ${os_release_} |sed 's/[0-9]*\.\([0-9]*\)/\1/'`
minor_=`grep Solaris /etc/release |sed 's/[^u]*\(u[0-9]*\).*/\1/'`
os_version_="${major_}${minor_}"
fi
;;
esac
echo ${os_version_}
unset os_name_ os_release_ os_version_ major_ minor_ sub_
}
versions_shellVersion()
{
shell_=$1
if [ ! -x "${shell_}" ]; then
echo 'not installed'
return
fi
version_=''
case ${shell_} in
*/sh)
# TODO(kward): fix this
## this could be one of any number of shells. try until one fits.
#version_=`versions_shell_bash ${shell_}`
## dash cannot be self determined yet
#[ -z "${version_}" ] && version_=`versions_shell_ksh ${shell_}`
## pdksh is covered in versions_shell_ksh()
#[ -z "${version_}" ] && version_=`versions_shell_zsh ${shell_}`
;;
*/bash) version_=`versions_shell_bash ${shell_}` ;;
*/dash)
# simply assuming Ubuntu Linux until somebody comes up with a better
# test. the following test will return an empty string if dash is not
# installed.
version_=`versions_shell_dash`
;;
*/ksh) version_=`versions_shell_ksh ${shell_}` ;;
*/pdksh) version_=`versions_shell_pdksh ${shell_}` ;;
*/zsh) version_=`versions_shell_zsh ${shell_}` ;;
*) version_='invalid'
esac
echo ${version_:-unknown}
unset shell_ version_
}
versions_shell_bash()
{
$1 --version 2>&1 |grep 'GNU bash' |sed 's/.*version \([^ ]*\).*/\1/'
}
versions_shell_dash()
{
eval dpkg >/dev/null 2>&1
[ $? -eq 127 ] && return # return if dpkg not found
dpkg -l |grep ' dash ' |awk '{print $3}'
}
versions_shell_ksh()
{
versions_shell_=$1
# see if --version gives a result
versions_version_=`${versions_shell_} --version 2>&1 \
|sed 's/.*\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/'`
# --version didn't work... look into the binary
if [ $? -ne ${TRUE} ]; then
_versions_have_strings
versions_version_=`strings ${versions_shell_} 2>&1 \
|grep Version \
|sed 's/^.*Version \(.*\)$/\1/;s/ s+ \$$//;s/ /-/g'`
[ -z "${versions_version_}" ] \
&& versions_version_=`versions_shell_pdksh ${versions_shell_}`
fi
echo ${versions_version_}
unset versions_shell_ versions_version_
}
versions_shell_pdksh()
{
_versions_have_strings
strings $1 2>&1 \
|grep 'PD KSH' \
|sed -e 's/.*PD KSH \(.*\)/\1/;s/ /-/g'
}
versions_shell_zsh()
{
versions_shell_=$1
versions_version_=`${versions_shell_} --version 2>&1 |awk '{print $2}'`
if [ $? -ne ${TRUE} ]; then
versions_version_=`echo 'echo ${ZSH_VERSION}' |${versions_shell_}`
fi
echo ${versions_version_}
unset versions_shell_ versions_version_
}
# Determine if the 'strings' binary installed.
_versions_have_strings()
{
[ ${__versions_haveStrings} -ne ${ERROR} ] && return
eval strings /dev/null >/dev/null 2>&1
if [ $? -eq 0 ]; then
__versions_haveStrings=${TRUE}
else
echo 'WARN: strings not installed. try installing binutils?' >&2
__versions_haveStrings=${FALSE}
fi
}
#------------------------------------------------------------------------------
# main
#
versions_main()
{
# treat unset variables as an error
set -u
os_name=`versions_osName`
os_version=`versions_osVersion`
echo "os: ${os_name} version: ${os_version}"
for shell in ${VERSIONS_SHELLS}; do
shell_version=`versions_shellVersion ${shell}`
echo "shell: ${shell} version: ${shell_version}"
done
}
if [ "${ARGV0}" = 'versions' ]; then
versions_main "$@"
fi

File diff suppressed because it is too large Load Diff

View File

@ -1,124 +0,0 @@
#! /bin/sh
# $Id: shunit2_test.sh 322 2011-04-24 00:09:45Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit test suite runner.
#
# This script runs all the unit tests that can be found, and generates a nice
# report of the tests.
MY_NAME=`basename $0`
MY_PATH=`dirname $0`
PREFIX='shunit2_test_'
SHELLS='/bin/sh /bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/zsh'
TESTS=''
for test in ${PREFIX}[a-z]*.sh; do
TESTS="${TESTS} ${test}"
done
# load common unit test functions
. ../lib/versions
. ./shunit2_test_helpers
usage()
{
echo "usage: ${MY_NAME} [-e key=val ...] [-s shell(s)] [-t test(s)]"
}
env=''
# process command line flags
while getopts 'e:hs:t:' opt; do
case ${opt} in
e) # set an environment variable
key=`expr "${OPTARG}" : '\([^=]*\)='`
val=`expr "${OPTARG}" : '[^=]*=\(.*\)'`
if [ -z "${key}" -o -z "${val}" ]; then
usage
exit 1
fi
eval "${key}='${val}'"
export ${key}
env="${env:+${env} }${key}"
;;
h) usage; exit 0 ;; # output help
s) shells=${OPTARG} ;; # list of shells to run
t) tests=${OPTARG} ;; # list of tests to run
*) usage; exit 1 ;;
esac
done
shift `expr ${OPTIND} - 1`
# fill shells and/or tests
shells=${shells:-${SHELLS}}
tests=${tests:-${TESTS}}
# error checking
if [ -z "${tests}" ]; then
th_error 'no tests found to run; exiting'
exit 1
fi
cat <<EOF
#------------------------------------------------------------------------------
# System data
#
# test run info
shells: ${shells}
tests: ${tests}
EOF
for key in ${env}; do
eval "echo \"${key}=\$${key}\""
done
echo
# output system data
echo "# system info"
echo "$ date"
date
echo
echo "$ uname -mprsv"
uname -mprsv
#
# run tests
#
for shell in ${shells}; do
echo
# check for existance of shell
if [ ! -x ${shell} ]; then
th_warn "unable to run tests with the ${shell} shell"
continue
fi
cat <<EOF
#------------------------------------------------------------------------------
# Running the test suite with ${shell}
#
EOF
SHUNIT_SHELL=${shell} # pass shell onto tests
shell_name=`basename ${shell}`
shell_version=`versions_shellVersion "${shell}"`
echo "shell name: ${shell_name}"
echo "shell version: ${shell_version}"
# execute the tests
for suite in ${tests}; do
suiteName=`expr "${suite}" : "${PREFIX}\(.*\).sh"`
echo
echo "--- Executing the '${suiteName}' test suite ---"
( exec ${shell} ./${suite} 2>&1; )
done
done

View File

@ -1,209 +0,0 @@
#! /bin/sh
# $Id: shunit2_test_asserts.sh 312 2011-03-14 22:41:29Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit test for assert functions
# load test helpers
. ./shunit2_test_helpers
#------------------------------------------------------------------------------
# suite tests
#
commonEqualsSame()
{
fn=$1
( ${fn} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'equal' $? "${stdoutF}" "${stderrF}"
( ${fn} "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'equal; with msg' $? "${stdoutF}" "${stderrF}"
( ${fn} 'abc def' 'abc def' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'equal with spaces' $? "${stdoutF}" "${stderrF}"
( ${fn} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'not equal' $? "${stdoutF}" "${stderrF}"
( ${fn} '' '' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'null values' $? "${stdoutF}" "${stderrF}"
( ${fn} arg1 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( ${fn} arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
commonNotEqualsSame()
{
fn=$1
( ${fn} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not same' $? "${stdoutF}" "${stderrF}"
( ${fn} "${MSG}" 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not same, with msg' $? "${stdoutF}" "${stderrF}"
( ${fn} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}"
( ${fn} '' '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}"
( ${fn} arg1 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( ${fn} arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testAssertEquals()
{
commonEqualsSame 'assertEquals'
}
testAssertNotEquals()
{
commonNotEqualsSame 'assertNotEquals'
}
testAssertSame()
{
commonEqualsSame 'assertSame'
}
testAssertNotSame()
{
commonNotEqualsSame 'assertNotSame'
}
testAssertNull()
{
( assertNull '' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'null' $? "${stdoutF}" "${stderrF}"
( assertNull "${MSG}" '' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'null, with msg' $? "${stdoutF}" "${stderrF}"
( assertNull 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'not null' $? "${stdoutF}" "${stderrF}"
( assertNull >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( assertNull arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testAssertNotNull()
{
( assertNotNull 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null' $? "${stdoutF}" "${stderrF}"
( assertNotNull "${MSG}" 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null, with msg' $? "${stdoutF}" "${stderrF}"
( assertNotNull 'x"b' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null, with double-quote' $? \
"${stdoutF}" "${stderrF}"
( assertNotNull "x'b" >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null, with single-quote' $? \
"${stdoutF}" "${stderrF}"
( assertNotNull 'x$b' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null, with dollar' $? \
"${stdoutF}" "${stderrF}"
( assertNotNull 'x`b' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'not null, with backtick' $? \
"${stdoutF}" "${stderrF}"
( assertNotNull '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'null' $? "${stdoutF}" "${stderrF}"
# there is no test for too few arguments as $1 might actually be null
( assertNotNull arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testAssertTrue()
{
( assertTrue 0 >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'true' $? "${stdoutF}" "${stderrF}"
( assertTrue "${MSG}" 0 >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'true, with msg' $? "${stdoutF}" "${stderrF}"
( assertTrue '[ 0 -eq 0 ]' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'true condition' $? "${stdoutF}" "${stderrF}"
( assertTrue 1 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'false' $? "${stdoutF}" "${stderrF}"
( assertTrue '[ 0 -eq 1 ]' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'false condition' $? "${stdoutF}" "${stderrF}"
( assertTrue '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'null' $? "${stdoutF}" "${stderrF}"
( assertTrue >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( assertTrue arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testAssertFalse()
{
( assertFalse 1 >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'false' $? "${stdoutF}" "${stderrF}"
( assertFalse "${MSG}" 1 >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'false, with msg' $? "${stdoutF}" "${stderrF}"
( assertFalse '[ 0 -eq 1 ]' >"${stdoutF}" 2>"${stderrF}" )
th_assertTrueWithNoOutput 'false condition' $? "${stdoutF}" "${stderrF}"
( assertFalse 0 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'true' $? "${stdoutF}" "${stderrF}"
( assertFalse '[ 0 -eq 0 ]' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'true condition' $? "${stdoutF}" "${stderrF}"
( assertFalse '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'true condition' $? "${stdoutF}" "${stderrF}"
( assertFalse >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( assertFalse arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
#------------------------------------------------------------------------------
# suite functions
#
oneTimeSetUp()
{
tmpDir="${__shunit_tmpDir}/output"
mkdir "${tmpDir}"
stdoutF="${tmpDir}/stdout"
stderrF="${tmpDir}/stderr"
MSG='This is a test message'
}
# load and run shUnit2
[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0
. ${TH_SHUNIT}

View File

@ -1,89 +0,0 @@
#! /bin/sh
# $Id: shunit2_test_failures.sh 286 2008-11-24 21:42:34Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit test for failure functions
# load common unit-test functions
. ./shunit2_test_helpers
#-----------------------------------------------------------------------------
# suite tests
#
testFail()
{
( fail >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'fail' $? "${stdoutF}" "${stderrF}"
( fail "${MSG}" >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'fail with msg' $? "${stdoutF}" "${stderrF}"
( fail arg1 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testFailNotEquals()
{
( failNotEquals 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}"
( failNotEquals "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}"
( failNotEquals 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}"
( failNotEquals '' '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}"
( failNotEquals >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( failNotEquals arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
testFailSame()
{
( failSame 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}"
( failSame "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}"
( failSame 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}"
( failSame '' '' >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}"
( failSame >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}"
( failSame arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" )
th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}"
}
#-----------------------------------------------------------------------------
# suite functions
#
oneTimeSetUp()
{
tmpDir="${__shunit_tmpDir}/output"
mkdir "${tmpDir}"
stdoutF="${tmpDir}/stdout"
stderrF="${tmpDir}/stderr"
MSG='This is a test message'
}
# load and run shUnit2
[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0
. ${TH_SHUNIT}

View File

@ -1,177 +0,0 @@
# $Id: shunit2_test_helpers 286 2008-11-24 21:42:34Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit test common functions
# treat unset variables as an error when performing parameter expansion
set -u
# set shwordsplit for zsh
[ -n "${ZSH_VERSION:-}" ] && setopt shwordsplit
#
# constants
#
# path to shUnit2 library. can be overridden by setting SHUNIT_INC
TH_SHUNIT=${SHUNIT_INC:-./shunit2}
# configure debugging. set the DEBUG environment variable to any
# non-empty value to enable debug output, or TRACE to enable trace
# output.
TRACE=${TRACE:+'th_trace '}
[ -n "${TRACE}" ] && DEBUG=1
[ -z "${TRACE}" ] && TRACE=':'
DEBUG=${DEBUG:+'th_debug '}
[ -z "${DEBUG}" ] && DEBUG=':'
#
# variables
#
th_RANDOM=0
#
# functions
#
# message functions
th_trace() { echo "${MY_NAME}:TRACE $@" >&2; }
th_debug() { echo "${MY_NAME}:DEBUG $@" >&2; }
th_info() { echo "${MY_NAME}:INFO $@" >&2; }
th_warn() { echo "${MY_NAME}:WARN $@" >&2; }
th_error() { echo "${MY_NAME}:ERROR $@" >&2; }
th_fatal() { echo "${MY_NAME}:FATAL $@" >&2; }
# output subtest name
th_subtest() { echo " $@" >&2; }
# generate a random number
th_generateRandom()
{
tfgr_random=${th_RANDOM}
while [ "${tfgr_random}" = "${th_RANDOM}" ]; do
if [ -n "${RANDOM:-}" ]; then
# $RANDOM works
tfgr_random=${RANDOM}${RANDOM}${RANDOM}$$
elif [ -r '/dev/urandom' ]; then
tfgr_random=`od -vAn -N4 -tu4 </dev/urandom |sed 's/^[^0-9]*//'`
else
tfgr_date=`date '+%H%M%S'`
tfgr_random=`expr ${tfgr_date} \* $$`
unset tfgr_date
fi
[ "${tfgr_random}" = "${th_RANDOM}" ] && sleep 1
done
th_RANDOM=${tfgr_random}
unset tfgr_random
}
# this section returns the data section from the specified section of a file. a
# datasection is defined by a [header], one or more lines of data, and then a
# blank line.
th_getDataSect()
{
th_sgrep "\\[$1\\]" "$2" |sed '1d'
}
# this function greps a section from a file. a section is defined as a group of
# lines preceeded and followed by blank lines.
th_sgrep()
{
th_pattern_=$1
shift
sed -e '/./{H;$!d;}' -e "x;/${th_pattern_}/"'!d;' $@ |sed '1d'
unset th_pattern_
}
# Custom assert that checks for true return value (0), and no output to STDOUT
# or STDERR. If a non-zero return value is encountered, the output of STDERR
# will be output.
#
# Args:
# th_test_: string: name of the subtest
# th_rtrn_: integer: the return value of the subtest performed
# th_stdout_: string: filename where stdout was redirected to
# th_stderr_: string: filename where stderr was redirected to
th_assertTrueWithNoOutput()
{
th_test_=$1
th_rtrn_=$2
th_stdout_=$3
th_stderr_=$4
assertTrue "${th_test_}; expected return value of zero" ${th_rtrn_}
[ ${th_rtrn_} -ne ${SHUNIT_TRUE} ] && cat "${th_stderr_}"
assertFalse "${th_test_}; expected no output to STDOUT" \
"[ -s '${th_stdout_}' ]"
assertFalse "${th_test_}; expected no output to STDERR" \
"[ -s '${th_stderr_}' ]"
unset th_test_ th_rtrn_ th_stdout_ th_stderr_
}
# Custom assert that checks for non-zero return value, output to STDOUT, but no
# output to STDERR.
#
# Args:
# th_test_: string: name of the subtest
# th_rtrn_: integer: the return value of the subtest performed
# th_stdout_: string: filename where stdout was redirected to
# th_stderr_: string: filename where stderr was redirected to
th_assertFalseWithOutput()
{
th_test_=$1
th_rtrn_=$2
th_stdout_=$3
th_stderr_=$4
assertFalse "${th_test_}; expected non-zero return value" ${th_rtrn_}
assertTrue "${th_test_}; expected output to STDOUT" \
"[ -s '${th_stdout_}' ]"
assertFalse "${th_test_}; expected no output to STDERR" \
"[ -s '${th_stderr_}' ]"
unset th_test_ th_rtrn_ th_stdout_ th_stderr_
}
# Custom assert that checks for non-zero return value, no output to STDOUT, but
# output to STDERR.
#
# Args:
# th_test_: string: name of the subtest
# th_rtrn_: integer: the return value of the subtest performed
# th_stdout_: string: filename where stdout was redirected to
# th_stderr_: string: filename where stderr was redirected to
th_assertFalseWithError()
{
th_test_=$1
th_rtrn_=$2
th_stdout_=$3
th_stderr_=$4
assertFalse "${th_test_}; expected non-zero return value" ${th_rtrn_}
assertFalse "${th_test_}; expected no output to STDOUT" \
"[ -s '${th_stdout_}' ]"
assertTrue "${th_test_}; expected output to STDERR" \
"[ -s '${th_stderr_}' ]"
unset th_test_ th_rtrn_ th_stdout_ th_stderr_
}
#
# main
#
${TRACE} 'trace output enabled'
${DEBUG} 'debug output enabled'

View File

@ -1,249 +0,0 @@
#! /bin/sh
# $Id: shunit2_test_macros.sh 299 2010-05-03 12:44:20Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit test for macros.
# load test helpers
. ./shunit2_test_helpers
#------------------------------------------------------------------------------
# suite tests
#
testAssertEquals()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_EQUALS_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_EQUALS_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_EQUALS_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_EQUALS_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testAssertNotEquals()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_NOT_EQUALS_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_EQUALS_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_NOT_EQUALS_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_EQUALS_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testSame()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_SAME_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_SAME_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_SAME_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_SAME_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testNotSame()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_NOT_SAME_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_SAME_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_NOT_SAME_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_SAME_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testNull()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_NULL_} 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NULL_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_NULL_} '"some msg"' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NULL_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testNotNull()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_NOT_NULL_} '' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_NULL_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_NOT_NULL_} '"some msg"' '""' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_NOT_NULL_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stdoutF}" "${stderrF}" >&2
}
testAssertTrue()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_TRUE_} ${SHUNIT_FALSE} >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_TRUE_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_TRUE_} '"some msg"' ${SHUNIT_FALSE} >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_TRUE_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testAssertFalse()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_ASSERT_FALSE_} ${SHUNIT_TRUE} >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_FALSE_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_ASSERT_FALSE_} '"some msg"' ${SHUNIT_TRUE} >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_ASSERT_FALSE_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testFail()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_FAIL_} >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_FAIL_} '"some msg"' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testFailNotEquals()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_FAIL_NOT_EQUALS_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_NOT_EQUALS_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_FAIL_NOT_EQUALS_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_NOT_EQUALS_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testFailSame()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_FAIL_SAME_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_SAME_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_FAIL_SAME_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_SAME_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testFailNotSame()
{
# start skipping if LINENO not available
[ -z "${LINENO:-}" ] && startSkipping
( ${_FAIL_NOT_SAME_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_NOT_SAME_ failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
( ${_FAIL_NOT_SAME_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" )
grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null
rtrn=$?
assertTrue '_FAIL_NOT_SAME_ w/ msg failure' ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
#------------------------------------------------------------------------------
# suite functions
#
oneTimeSetUp()
{
tmpDir="${__shunit_tmpDir}/output"
mkdir "${tmpDir}"
stdoutF="${tmpDir}/stdout"
stderrF="${tmpDir}/stderr"
}
# load and run shUnit2
[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0
. ${TH_SHUNIT}

View File

@ -1,165 +0,0 @@
#! /bin/sh
# $Id: shunit2_test_misc.sh 322 2011-04-24 00:09:45Z kate.ward@forestent.com $
# vim:et:ft=sh:sts=2:sw=2
#
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# shUnit2 unit tests of miscellaneous things
# load test helpers
. ./shunit2_test_helpers
#------------------------------------------------------------------------------
# suite tests
#
# Note: the test script is prefixed with '#' chars so that shUnit2 does not
# incorrectly interpret the embedded functions as real functions.
testUnboundVariable()
{
sed 's/^#//' >"${unittestF}" <<EOF
## treat unset variables as an error when performing parameter expansion
#set -u
#
#boom() { x=\$1; } # this function goes boom if no parameters are passed!
#test_boom()
#{
# assertEquals 1 1
# boom # No parameter given
# assertEquals 0 \$?
#}
#. ${TH_SHUNIT}
EOF
( exec ${SHUNIT_SHELL:-sh} "${unittestF}" >"${stdoutF}" 2>"${stderrF}" )
assertFalse 'expected a non-zero exit value' $?
grep '^ASSERT:Unknown failure' "${stdoutF}" >/dev/null
assertTrue 'assert message was not generated' $?
grep '^Ran [0-9]* test' "${stdoutF}" >/dev/null
assertTrue 'test count message was not generated' $?
grep '^FAILED' "${stdoutF}" >/dev/null
assertTrue 'failure message was not generated' $?
}
testIssue7()
{
( assertEquals 'Some message.' 1 2 >"${stdoutF}" 2>"${stderrF}" )
diff "${stdoutF}" - >/dev/null <<EOF
ASSERT:Some message. expected:<1> but was:<2>
EOF
rtrn=$?
assertEquals ${SHUNIT_TRUE} ${rtrn}
[ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2
}
testPrepForSourcing()
{
assertEquals '/abc' `_shunit_prepForSourcing '/abc'`
assertEquals './abc' `_shunit_prepForSourcing './abc'`
assertEquals './abc' `_shunit_prepForSourcing 'abc'`
}
testEscapeCharInStr()
{
actual=`_shunit_escapeCharInStr '\' ''`
assertEquals '' "${actual}"
assertEquals 'abc\\' `_shunit_escapeCharInStr '\' 'abc\'`
assertEquals 'abc\\def' `_shunit_escapeCharInStr '\' 'abc\def'`
assertEquals '\\def' `_shunit_escapeCharInStr '\' '\def'`
actual=`_shunit_escapeCharInStr '"' ''`
assertEquals '' "${actual}"
assertEquals 'abc\"' `_shunit_escapeCharInStr '"' 'abc"'`
assertEquals 'abc\"def' `_shunit_escapeCharInStr '"' 'abc"def'`
assertEquals '\"def' `_shunit_escapeCharInStr '"' '"def'`
actual=`_shunit_escapeCharInStr '$' ''`
assertEquals '' "${actual}"
assertEquals 'abc\$' `_shunit_escapeCharInStr '$' 'abc$'`
assertEquals 'abc\$def' `_shunit_escapeCharInStr '$' 'abc$def'`
assertEquals '\$def' `_shunit_escapeCharInStr '$' '$def'`
# actual=`_shunit_escapeCharInStr "'" ''`
# assertEquals '' "${actual}"
# assertEquals "abc\\'" `_shunit_escapeCharInStr "'" "abc'"`
# assertEquals "abc\\'def" `_shunit_escapeCharInStr "'" "abc'def"`
# assertEquals "\\'def" `_shunit_escapeCharInStr "'" "'def"`
# # must put the backtick in a variable so the shell doesn't misinterpret it
# # while inside a backticked sequence (e.g. `echo '`'` would fail).
# backtick='`'
# actual=`_shunit_escapeCharInStr ${backtick} ''`
# assertEquals '' "${actual}"
# assertEquals '\`abc' \
# `_shunit_escapeCharInStr "${backtick}" ${backtick}'abc'`
# assertEquals 'abc\`' \
# `_shunit_escapeCharInStr "${backtick}" 'abc'${backtick}`
# assertEquals 'abc\`def' \
# `_shunit_escapeCharInStr "${backtick}" 'abc'${backtick}'def'`
}
testEscapeCharInStr_specialChars()
{
# make sure our forward slash doesn't upset sed
assertEquals '/' `_shunit_escapeCharInStr '\' '/'`
# some shells escape these differently
#assertEquals '\\a' `_shunit_escapeCharInStr '\' '\a'`
#assertEquals '\\b' `_shunit_escapeCharInStr '\' '\b'`
}
# Test the various ways of declaring functions.
#
# Prefixing (then stripping) with comment symbol so these functions aren't
# treated as real functions by shUnit2.
testExtractTestFunctions()
{
f="${tmpD}/extract_test_functions"
sed 's/^#//' <<EOF >"${f}"
#testABC() { echo 'ABC'; }
#test_def() {
# echo 'def'
#}
#testG3 ()
#{
# echo 'G3'
#}
#function test4() { echo '4'; }
# test5() { echo '5'; }
#some_test_function() { echo 'some func'; }
#func_with_test_vars() {
# testVariable=1234
#}
EOF
actual=`_shunit_extractTestFunctions "${f}"`
assertEquals 'testABC test_def testG3 test4 test5' "${actual}"
}
#------------------------------------------------------------------------------
# suite functions
#
setUp()
{
for f in ${expectedF} ${stdoutF} ${stderrF}; do
cp /dev/null ${f}
done
rm -fr "${tmpD}"
mkdir "${tmpD}"
}
oneTimeSetUp()
{
tmpD="${SHUNIT_TMPDIR}/tmp"
expectedF="${SHUNIT_TMPDIR}/expected"
stdoutF="${SHUNIT_TMPDIR}/stdout"
stderrF="${SHUNIT_TMPDIR}/stderr"
unittestF="${SHUNIT_TMPDIR}/unittest"
}
# load and run shUnit2
[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0
. ${TH_SHUNIT}

Some files were not shown because too many files have changed in this diff Show More