├── .gitignore
├── GNUmakefile
├── LICENSE.txt
├── README.md
├── TODO.md
├── benchmarks
├── buffer.scm
├── editor.scm
├── run.scm
└── util.scm
├── bin
└── edward.scm
├── doc
├── .gitignore
├── GNUmakefile
├── README.md
├── index.md
└── page.theme
├── edward.egg
├── edward.release-info
├── lib
├── buffer.sld
├── buffer
│ ├── buffer.scm
│ ├── srfi214-minimal.scm
│ └── stack.scm
├── cli.scm
├── cli.sld
├── ed
│ ├── addr.scm
│ ├── addr.sld
│ ├── cmd.scm
│ ├── cmd.sld
│ ├── editor.scm
│ ├── editor.sld
│ ├── posix.scm
│ └── posix.sld
├── parse.sld
├── parse
│ ├── parse.scm
│ ├── repl.scm
│ └── util.scm
├── replace.scm
├── replace.sld
├── util.scm
└── util.sld
└── tests
├── buffer.scm
├── integration
├── address-chain-eval-order
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-chain-fully-eval
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-range-large-address
│ └── cmds
├── address-range-semicolon-list
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-range-semicolon-number
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-range-semicolon-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-ranges
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── address-regex-syntax-error
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-and-list
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-and-n
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-and-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-at-beginning
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-at-end
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-between
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-empty-not-modified
│ └── cmds
├── append-line-update
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── append-newlines
│ └── cmds
├── append-nth
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-and-n
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-default
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-delete-everything
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-insert-more-lines
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-line-update
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── change-no-input
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── command-mode-eof-modified
│ └── cmds
├── command-mode-eof
│ └── cmds
├── confirm-quit-when-no-tty
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── copy-to-end
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── copy-to-start
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── copy-with-offset
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── delete-and-append
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── delete-entire-buffer
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── delete-last-line
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── delete-partial
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── delete-single-addr
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── discard-first-addr
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── edit-confirm
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── edit-custom-file
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── edit-default
│ ├── cmds
│ └── testdata
│ │ └── input-file
├── edit-marks-discarded
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── edit-twice
│ ├── cmds
│ └── testdata
│ │ ├── first
│ │ └── second
├── edit-unset-modified
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── edit-with-command
│ └── cmds
├── filename-line-unchanged
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── filename-new-file
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── filename-same-file
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── filename-shell-command
│ └── cmds
├── filename-silent
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── forward-backward-current-matches
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-append-omit-terminator
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-append
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-change
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-delete-everything
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-delim
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-delimiter-omitted-substitute
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-empty
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-esc-delim
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-insert
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-multiline
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-multiple-commands
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-no-match
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-no-terminating-dot
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-non-matched
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-null-re
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-regex-syntax-error
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-substitute-nomatch1
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── global-substitute-nomatch2
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── input-mode-eof
│ └── cmds
├── insert-before
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── insert-zero
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-nested-global
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-no-previous
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-null-command
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-null-repeat
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-previous
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-repeat
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive-unmatched
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── interactive
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── invalid-range
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── join-all
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── join-lines
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── join-nothing
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── line-number-default
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── line-number-empty
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── line-number-zero
│ └── cmds
├── list-backslash
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── list-multiple-lines
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── list-pad-with-zeros
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── list-unicode
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-and-delete
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-and-move
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-empty-buffer
│ └── cmds
├── mark-first-line
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-invalid
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-overwrite
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── mark-zero-line
│ └── cmds
├── move-after
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── move-between
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── move-overlapping-range
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── move-to-end
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── move-to-start
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── move-update-current-on-single-line
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── multiple-addresses
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── no-null-re
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── nonexistend-file-read
│ └── cmds
├── nonexistend-file-write
│ └── cmds
├── null-command-with-address
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── null-command-with-zero-address
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── null-command
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── null-re-range
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── null-re
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── number-change-line
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── number-default
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── number-full
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── number-partial
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── omitting-re-delimiter
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── pass-shell-command-as-cmdarg
│ ├── cmds
│ └── opts
├── prefix-print-with-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-match-backward-multiple-matches
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-match-backward
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-match-forward-no-match
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-match-forward-wraparound
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-match-forward
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print-single
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── quit-address
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── quit-confirmed
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── quit-file-modified
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── quit-no-file
│ ├── cmds
│ └── opts
├── quit-not-modified
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── quit-without-checking
│ └── cmds
├── read-command-empty
│ └── cmds
├── read-command-twice
│ └── cmds
├── read-dont-remember-command
│ └── cmds
├── read-from-command
│ └── cmds
├── read-no-space
│ ├── cmds
│ └── testdata
│ │ └── in
├── read-set-default
│ ├── cmds
│ └── testdata
│ │ └── input-file
├── read-twice
│ ├── cmds
│ └── testdata
│ │ └── in
├── read-write-no-file
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── regex-empty-file
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── run.sh
├── shell-escape-filename
│ └── cmds
├── shell-filename-multiple
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first-file
│ │ └── second-file
├── shell-filename
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── shell-no-filename
│ └── cmds
├── shell-no-previous
│ └── cmds
├── shell-previous-append
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── shell-previous-with-filename
│ └── cmds
├── shell-previous
│ └── cmds
├── silent-mode
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first-file
│ │ └── second-file
├── special-addresses
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-and-number
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-and-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-append
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-backreference
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-change-line
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-delimiter-escaped
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-delimiter
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-differ-matched-twice
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-empty-replace
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-empty-submatch
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-first
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-global
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-insert-multiple-newlines
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-invalid-backref
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-mark-touched
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-mark-untouched
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-matched-twice
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-missing-pattern
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-modified-but-same
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-multiline-print
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-multiline
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-no-match
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-no-prev-replace
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-non-participating-submatch
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-null-re
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-percent-delim
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-prev-replace-empty
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-prev-replace
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── substitute-regex-syntax-error
│ └── cmds
├── substitute-simple
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── terminate-after-first-error
│ └── cmds
├── undo-append
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-change
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-copy
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-delete
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-edit-command
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── first
│ │ └── second
├── undo-global-non-matched
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-global
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-insert
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-join
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-move
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-nothing
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-read
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ ├── input-file
│ │ └── to-be-read
├── undo-redo
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-substitute
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── undo-undo
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── write-default-empty
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── write-default
│ ├── cmds
│ ├── opts
│ └── testdata
│ │ └── input-file
├── write-empty-to-command
│ └── cmds
├── write-no-file
│ └── cmds
├── write-partial
│ ├── cmds
│ ├── opts
│ ├── out
│ └── testdata
│ │ └── input-file
├── write-to-command-modified
│ ├── cmds
│ └── testdata
│ │ └── input-file
├── write-to-command
│ ├── cmds
│ └── testdata
│ │ └── input-file
├── write-update-filename-cmd
│ ├── cmds
│ └── testdata
│ │ └── file
├── write-update-filename
│ ├── cmds
│ └── testdata
│ │ └── file
└── zero-address
│ ├── cmds
│ ├── opts
│ └── testdata
│ └── input-file
├── interactive
├── README.md
├── eof-confirm-with-quit
│ ├── cmds
│ └── expected
├── eof-modified-reset
│ ├── cmds
│ └── expected
├── eof-modified
│ ├── cmds
│ └── expected
├── eof
│ ├── cmds
│ └── expected
├── input-mode-eof-partial-multiple
│ ├── cmds
│ └── expected
├── input-mode-eof-partial
│ ├── cmds
│ └── expected
├── input-mode-eof
│ ├── cmds
│ └── expected
├── interactive-global-eof
│ ├── cmds
│ └── expected
├── interactive-unmatched-eof
│ ├── cmds
│ └── expected
├── prompt
│ ├── cmds
│ └── expected
├── quit-confirm-with-eof
│ ├── cmds
│ └── expected
└── run.sh
├── parse-addr.scm
├── parse-cmd.scm
├── replace.scm
├── run.scm
└── util.scm
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/edward
2 | output/
3 | vendor/
4 | edward*.build.sh
5 | edward*.import.scm
6 | edward*.import.so
7 | edward*.install.sh
8 | edward*.link
9 | edward*.so
10 | edward*.static.o
11 | edward*.c
12 |
--------------------------------------------------------------------------------
/GNUmakefile:
--------------------------------------------------------------------------------
1 | # This Makefile is a wrapper around chicken-install(1) which eases building
2 | # edward without superuser rights and without requiring any configuration
3 | # of chicken-install. Furthermore, it supports optional dependency vendoring
4 | # to build edward without network access.
5 | #
6 | # By default, the Makefile builds a statically linked binary. For development
7 | # purposes it can be desirable to do dynamic linked builds instead. To do so
8 | # the PACKAGE environment variable can be set to zero.
9 | PREFIX ?= /usr/local
10 | BINDIR ?= $(PREFIX)/bin
11 | DOCDIR ?= $(PREFIX)/share/doc/edward
12 |
13 | # By default, build a statically linked version for packaging.
14 | # If package is zero, build a dynamically linked version instead.
15 | PACKAGE ?= 1
16 | ifneq ($(PACKAGE),0)
17 | INSTALL_FLAGS = -feature package
18 | endif
19 |
20 | # Install all CHICKEN files relative to ./output
21 | #
22 | # See: https://bugs.call-cc.org/ticket/1792
23 |
24 | # Respect CHICKEN_REPOSITORY_PATH if set in the environment
25 | CHICKEN_REPOSITORY_PATH ?= $(shell env -i chicken-install -repository)
26 |
27 | export CHICKEN_INSTALL_PREFIX := $(CURDIR)/output
28 | export CHICKEN_INSTALL_REPOSITORY := $(CURDIR)/output
29 | export CHICKEN_REPOSITORY_PATH := $(CURDIR)/output:$(CHICKEN_REPOSITORY_PATH)
30 |
31 | # Optional dependency vendoring to build without network access
32 | #
33 | # Release tarballs include vendored dependencies (see make dist).
34 |
35 | VENDOR_DIRECTORY = $(CURDIR)/vendor
36 | ifneq ($(wildcard $(VENDOR_DIRECTORY)/*),)
37 | VENDORED=1
38 | endif
39 |
40 | all:
41 | ifdef VENDORED
42 | chicken-install -location $(VENDOR_DIRECTORY) $(shell ls $(VENDOR_DIRECTORY))
43 | endif
44 | chicken-install $(INSTALL_FLAGS)
45 |
46 | check: export EDWARD=$(CHICKEN_INSTALL_PREFIX)/bin/edward
47 | check:
48 | chicken-install -test
49 | @./tests/integration/run.sh
50 | @./tests/interactive/run.sh
51 |
52 | bench:
53 | csi -quiet -script benchmarks/run.scm
54 |
55 | install:
56 | install -Dm755 $(CHICKEN_INSTALL_PREFIX)/bin/edward "$(DESTDIR)$(BINDIR)/edward"
57 | install -Dm644 README.md "$(DESTDIR)$(DOCDIR)/README.md"
58 |
59 | vendor:
60 | env -i CHICKEN_EGG_CACHE=$(VENDOR_DIRECTORY) chicken-install -r -recursive -test
61 | find $(VENDOR_DIRECTORY) \( -name STATUS -a -type f \) -exec rm {} +
62 | # XXX: Make sure to remove the vendor directory before running `make dist`.
63 | # As libraries are, unfortunately, build within the vendor directory.
64 | dist: VERSION = $(shell git describe --tags)
65 | dist: vendor
66 | mkdir -p edward-$(VERSION)
67 | cp -R LICENSE.txt GNUmakefile README.md bin edward.egg lib tests vendor edward-$(VERSION)
68 | tar -czf edward-$(VERSION).tar.gz edward-$(VERSION)
69 | rm -rf edward-$(VERSION)
70 |
71 | .PHONY: all check bench install vendor dist
72 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Library Interface
2 |
3 | * Introduce namespaces for command names
4 | * By making command names a list, e.g. `'(posix quit)`
5 | * POSIX namespace should be treated as reserved
6 | * Documentation: Clarify interaction between `edward ed addr` and `edward ed editor`
7 | * `(edward ed cli)`: Allow defining custom command-line options
8 | * Provide dedicated types for addresses and ranges
9 | * Add `(chicken type)` annotations for the public API to catch more
10 | usage errors during compile-time instead of run-time.
11 | * Provide an `(edward)` meta-library which imports all sub-libraries.
12 |
13 | # Miscellaneous
14 |
15 | * Consider using Declarations and (chicken type) to enable more optimizations
16 | * https://wiki.call-cc.org/programming-for-performance
17 | * https://wiki.call-cc.org/man/5/Declarations
18 | * https://wiki.call-cc.org/man/5/Foreign%20type%20specifiers
19 | * In append/insert/… command: Verify that the address is valid before
20 | entering insert mode. For example, when performing `2a` on an empty
21 | file the append will only error out after all text has been entered.
22 | * Figure out why edward is slower when compiled statically with eggs (linkage static)
23 | * Profile larger ed inputs (e.g. as generated by a fuzzer) with
24 | chicken-profile and figure identify (parsing) procedures which
25 | could be further optimized for performance
26 | * Improve parser error messages (mostly returns `failed char pred` currently)
27 | * Consider prefixing parser errors with command parser name
28 | (how should the `g` command be handled in this regard?)
29 | * Consider adding column information to parser errors
30 | * Add parse-with-failure-reason to more parser combinators
31 | * Refactor parse-line in a way that it can consume end-of-file.
32 | Requires refactoring of parse-input-mode.
33 | * Allow input with spaces in interactive tests
34 | * Probably requires rewriting the test runner in Python or something
35 | * Would enable adding tests for edge cases like c0fe7d15700cc1ca03198c05d3762f7516f185fe
36 |
--------------------------------------------------------------------------------
/benchmarks/buffer.scm:
--------------------------------------------------------------------------------
1 | (import (edward buffer)
2 | (edward util))
3 |
4 | (define-bench (buffer-append-single-at-end)
5 | (let ((buffer (make-buffer)))
6 | (repeat
7 | 10000
8 | (lambda ()
9 | (buffer-append!
10 | buffer
11 | (buffer-length buffer)
12 | (list (random-string)))))))
13 |
14 | (define-bench (buffer-append-multi-at-end)
15 | (let ((buffer (make-buffer)))
16 | (repeat
17 | 10000
18 | (let ((next-size 1)
19 | (max-size 10))
20 | (lambda ()
21 | (buffer-append!
22 | buffer
23 | (buffer-length buffer)
24 | (generate-list random-string next-size))
25 | (set! next-size (modulo (inc next-size) max-size)))))))
26 |
27 | (define-bench (buffer-append-single-randomly)
28 | (let ((buffer (make-buffer)))
29 | (repeat
30 | 10000
31 | (lambda ()
32 | (buffer-append!
33 | buffer
34 | (pseudo-random-integer (buffer-length buffer))
35 | (list (random-string)))))))
36 |
37 | (define-bench (buffer-remove-from-front)
38 | (let ((buffer (make-buffer))
39 | (elems 15000))
40 | (buffer-append! buffer 0 (generate-list random-string elems))
41 | (repeat elems
42 | (lambda ()
43 | (buffer-remove! buffer 1 1)))))
44 |
45 | (define-bench (buffer-remove-from-back)
46 | (let ((buffer (make-buffer))
47 | (elems 15000))
48 | (buffer-append! buffer 0 (generate-list random-string elems))
49 | (repeat elems
50 | (lambda ()
51 | (let ((len (buffer-length buffer)))
52 | (buffer-remove! buffer len len))))))
53 |
54 | (define-bench (buffer-remove-entire-content)
55 | (let ((buffer (make-buffer))
56 | (elems 100000))
57 | (buffer-append! buffer 0 (generate-list random-string elems))
58 | (buffer-remove! buffer 1 elems)))
59 |
60 | (define-bench (buffer-join-entire-content)
61 | (let ((buffer (make-buffer))
62 | (elems 30000))
63 | (buffer-append! buffer 0 (generate-list random-string elems))
64 | (buffer-join! buffer 1 elems)))
65 |
--------------------------------------------------------------------------------
/benchmarks/editor.scm:
--------------------------------------------------------------------------------
1 | (import (edward ed editor)
2 | (edward ed addr))
3 |
4 | (define-bench (editor-regex-match-line)
5 | (let ((e (make-text-editor #f "" "" #f))
6 | (n 100000))
7 | (editor-append! e 0 (generate-list random-string n))
8 | (editor-append! e n '("bla bla 23foobar42 foo bar"))
9 |
10 | (range->lpair e
11 | (make-range (make-addr '(regex-forward . "[0-9][0-9]*foobar[0-9][0-9]* foo"))))))
12 |
13 | (define-bench (editor-get-lines-partial)
14 | (let ((e (make-text-editor #f "" "" #f))
15 | (n 100000))
16 | (editor-append! e 0 (generate-list random-string n))
17 | (editor-get-lines e (cons 0 (/ n 2)))))
18 |
19 | (define-bench (editor-get-line-number-last)
20 | (let ((e (make-text-editor #f "" "" #f))
21 | (n 100000))
22 | (editor-append! e 0 (generate-list random-string n))
23 | (let ((p (editor-get-lines e (cons n n))))
24 | (editor-get-lnum e (car p)))))
25 |
--------------------------------------------------------------------------------
/benchmarks/run.scm:
--------------------------------------------------------------------------------
1 | (import r7rs)
2 |
3 | ;; Amount of execution per benchmark.
4 | (define BENCHMARK_ITERATIONS 3)
5 |
6 | (include-relative "util.scm")
7 | (include-relative "buffer.scm")
8 | (include-relative "editor.scm")
9 |
--------------------------------------------------------------------------------
/benchmarks/util.scm:
--------------------------------------------------------------------------------
1 | (import (edward util)
2 | (chicken random)
3 | (micro-benchmark))
4 |
5 | (define (repeat n thunk)
6 | (when (> n 0)
7 | (thunk)
8 | (repeat (dec n) thunk)))
9 |
10 | (define (random-string . rest)
11 | (let ((siz (if (null? rest) 100 (car rest))))
12 | (list->string
13 | (generate-list
14 | (lambda ()
15 | (let ((ascii (+ (pseudo-random-integer 126) 33)))
16 | (integer->char ascii)))
17 | siz))))
18 |
19 | (define (generate-list thunk size)
20 | (map
21 | (lambda (proc)
22 | (proc))
23 | (make-list size thunk)))
24 |
25 | (define (time-stat sym stats)
26 | (define (msec->sec msec)
27 | (/ msec 1000000))
28 |
29 | (define (round-off z n)
30 | (let ((power (expt 10 n)))
31 | (/ (round (* power z)) power)))
32 |
33 | (let ((el (assq sym stats)))
34 | (if (not el)
35 | (error (string-append "no element named '" (symbol->string sym) "' in statistics"))
36 | (round-off (msec->sec (cdr el)) 3))))
37 |
38 | (define (run-benchmark name proc)
39 | (let* ((stats (benchmark-run (BENCHMARK_ITERATIONS) (proc))))
40 | (display name)
41 | (display ":\t")
42 | (display (time-stat 'arithmetic-mean stats))
43 | (display "s")
44 | (display " +/- ")
45 | (display (time-stat 'standard-deviation stats))
46 | (display "s")
47 | (newline)))
48 |
49 | (define-syntax define-bench
50 | (syntax-rules ()
51 | ((define-bench (NAME) BODY ...)
52 | (run-benchmark
53 | (symbol->string (quote NAME))
54 | (lambda ()
55 | BODY ...)))))
56 |
--------------------------------------------------------------------------------
/bin/edward.scm:
--------------------------------------------------------------------------------
1 | (import (scheme base)
2 | (edward cli))
3 |
4 | (cond-expand
5 | ((or chicken-script compiling)
6 | (edward-main))
7 | (else #t))
8 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | style.css
3 |
--------------------------------------------------------------------------------
/doc/GNUmakefile:
--------------------------------------------------------------------------------
1 | # Can be set to an URL for any classless CSS framework.
2 | STYLESHEET ?= https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.css
3 |
4 | DISCOUNT = discount-theme
5 | DISCOUNT_FLAGS = -c +header,+idanchor
6 |
7 | SCMDOC = scmdoc
8 | SCMDOC_FLAGS = -s style.css
9 |
10 | SCMDOC_FILES = edward.ed.editor.html \
11 | edward.ed.cmd.html \
12 | edward.ed.addr.html \
13 | edward.ed.posix.html \
14 | edward.cli.html \
15 | edward.util.html \
16 | edward.parse.html \
17 | edward.replace.html \
18 | edward.buffer.html
19 |
20 | all: index.html style.css $(SCMDOC_FILES)
21 | clean:
22 | $(RM) index.html style.css $(SCMDOC_FILES)
23 | style.css:
24 | curl -sLo style.css $(STYLESHEET)
25 | index.html: index.md page.theme
26 | $(DISCOUNT) $(DISCOUNT_FLAGS) -o $@ $<
27 |
28 | edward.%.html: %.sld
29 | $(SCMDOC) $(SCMDOC_FLAGS) $<
30 | edward.ed.%.html: ed/%.sld
31 | $(SCMDOC) $(SCMDOC_FLAGS) $<
32 |
33 | # XXX: This essentially duplicates the dependency tracking of edward.egg.
34 | edward.ed.editor.html: ed/editor.sld ed/editor.scm
35 | edward.ed.cmd.html: ed/cmd.sld ed/cmd.scm
36 | edward.ed.addr.html: ed/addr.sld ed/addr.scm
37 | edward.ed.posix.html: ed/posix.sld ed/posix.scm
38 | edward.cli.html: cli.sld cli.scm
39 | edward.util.html: util.sld util.scm
40 | edward.replace.html: replace.sld replace.scm
41 | edward.parse.html: parse.sld parse/parse.scm parse/repl.scm parse/util.scm
42 | edward.buffer.html: buffer.sld buffer/buffer.scm buffer/stack.scm
43 |
44 | deploy: index.html style.css $(SCMDOC_FILES)
45 | rsync $^ magnesium:/var/www/htdocs/files.8pit.net/edward/latest/doc
46 |
47 | VPATH = ../lib
48 | .PHONY: all clean deploy
49 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | # API Documentation
2 |
3 | This generates the API documentation for the edward library interface.
4 |
5 | ## Dependencies
6 |
7 | In order to generate the documentation the following packages need to be installed:
8 |
9 | * [GNU make][gnu make]
10 | * [Discount][discount web]
11 | * [scmdoc][scmdoc github]
12 |
13 | ## Usage
14 |
15 | After installing the aforementioned dependency, run the following command:
16 |
17 | $ make -C doc
18 |
19 | This will generate several HTML files which provide an API documentation for R7RS libraries provided by edward.
20 | An index page which links to these files is also generated.
21 | Open `doc/index.html` in your favorite web browser to view this index page.
22 |
23 | [gnu make]: https://www.gnu.org/software/make
24 | [discount web]: http://www.pell.portland.or.us/~orc/Code/discount/
25 | [scmdoc github]: https://github.com/nmeum/scmdoc
26 |
--------------------------------------------------------------------------------
/doc/index.md:
--------------------------------------------------------------------------------
1 | % Edward API
2 | % author(s)
3 | % date
4 |
5 | # Edward Documentation
6 |
7 | This is the API documentation for the extensible [edward][edward github] text editor.
8 |
9 | ## Libraries
10 |
11 | The edward [CHICKEN][chicken web] [egg][chicken eggs] provides the following R7RS libraries:
12 |
13 | * [(edward ed editor)][edward editor]: The central text editor abstraction.
14 | * [(edward ed cmd)][edward cmd]: Marcos for defining new editor commands.
15 | * [(edward ed posix)][edward posix]: The implementation of POSIX editor commands.
16 | * [(edward ed addr)][edward addr]: Implementation of POSIX ed addressing.
17 | * [(edward parse)][edward parse]: The edward parser combinator library.
18 | * [(edward cli)][edward cli]: The command line interface abstraction.
19 | * [(edward replace)][edward replace]: Implementation of regex replacements.
20 | * [(edward util)][edward util]: Various utility procedures.
21 | * [(edward buffer)][edward buffer]: Line buffer implementation used internally.
22 |
23 | [chicken web]: https://call-cc.org
24 | [chicken eggs]: https://wiki.call-cc.org/eggs
25 | [edward github]: https://github.com/nmeum/edward
26 | [r7rs scheme]: https://small.r7rs.org/
27 | [edward editor]: edward.ed.editor.html
28 | [edward cmd]: edward.ed.cmd.html
29 | [edward addr]: edward.ed.addr.html
30 | [edward posix]: edward.ed.posix.html
31 | [edward cli]: edward.cli.html
32 | [edward util]: edward.util.html
33 | [edward parse]: edward.parse.html
34 | [edward replace]: edward.replace.html
35 | [edward buffer]: edward.buffer.html
36 |
--------------------------------------------------------------------------------
/doc/page.theme:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/edward.egg:
--------------------------------------------------------------------------------
1 | ((author "Sören Tempel")
2 | (synopsis "An extensible implementation of the ed text editor as defined in POSIX.1-2008")
3 | (version "1.1.0")
4 | (category tools)
5 | (license "GPLv3")
6 | (platform unix)
7 | (dependencies r7rs srfi-1 srfi-14 srfi-37 matchable posix-regex)
8 | (test-dependencies test)
9 | (component-options (csc-options "-d3" "-O3" "-X" "r7rs" "-R" "r7rs"))
10 | (cond-expand
11 | (package
12 | (component-options
13 | ;; need static linkange for program component, dynamic for tests
14 | (linkage dynamic static)))
15 | (else
16 | (component-options
17 | ;; don't build static libraries to reduce compile time
18 | (linkage dynamic))))
19 | (components
20 | (extension edward.util
21 | (source "./lib/util.sld")
22 | (source-dependencies
23 | "./lib/util.scm"))
24 | (extension edward.parse
25 | (component-dependencies edward.util)
26 |
27 | (source "./lib/parse.sld")
28 | (source-dependencies
29 | "./lib/parse/parse.scm"
30 | "./lib/parse/util.scm"
31 | "./lib/parse/repl.scm"))
32 | (extension edward.replace
33 | (component-dependencies edward.parse)
34 |
35 | (source "./lib/replace.sld")
36 | (source-dependencies
37 | "./lib/replace.scm"))
38 | (extension edward.buffer
39 | (component-dependencies edward.util)
40 |
41 | (source "./lib/buffer.sld")
42 | (source-dependencies
43 | "./lib/buffer/stack.scm"
44 | "./lib/buffer/srfi214-minimal.scm"
45 | "./lib/buffer/buffer.scm"))
46 | (extension edward.ed.addr
47 | (component-dependencies edward.parse)
48 |
49 | (source "./lib/ed/addr.sld")
50 | (source-dependencies
51 | "./lib/ed/addr.scm"))
52 | (extension edward.ed.editor
53 | (component-dependencies
54 | edward.util
55 | edward.parse
56 | edward.replace
57 | edward.buffer
58 | edward.ed.addr)
59 |
60 | (source "./lib/ed/editor.sld")
61 | (source-dependencies
62 | "./lib/ed/editor.scm"))
63 | (extension edward.ed.cmd
64 | (component-dependencies
65 | edward.util
66 | edward.parse
67 | edward.ed.addr
68 | edward.ed.editor)
69 |
70 | (source "./lib/ed/cmd.sld")
71 | (source-dependencies
72 | "./lib/ed/cmd.scm"))
73 | (extension edward.ed.posix
74 | (component-dependencies
75 | edward.util
76 | edward.parse
77 | edward.replace
78 | edward.ed.cmd
79 | edward.ed.addr
80 | edward.ed.editor)
81 |
82 | (source "./lib/ed/posix.sld")
83 | (source-dependencies
84 | "./lib/ed/posix.scm"))
85 | (extension edward.cli
86 | (component-dependencies
87 | edward.ed.cmd
88 | edward.ed.posix
89 | edward.ed.editor)
90 |
91 | (source "./lib/cli.sld")
92 | (source-dependencies
93 | "./lib/cli.scm"))
94 | (program bin/edward
95 | ;; In package mode, link statically against Egg dependencies.
96 | (cond-expand
97 | (package
98 | (linkage static))
99 | (else
100 | (linkage dynamic)))
101 | ;; Uncomment to also link against C libraries statically.
102 | ;(link-options "-L" "-static")
103 |
104 | (install-name "edward")
105 | (component-dependencies edward.cli))))
106 |
--------------------------------------------------------------------------------
/edward.release-info:
--------------------------------------------------------------------------------
1 | (repo git "https://github.com/nmeum/{egg-name}.git")
2 |
3 | (uri targz "https://codeload.github.com/nmeum/{egg-name}/tar.gz/{egg-release}")
4 | (release "1.0.1")
5 | (release "1.1.0")
6 |
--------------------------------------------------------------------------------
/lib/buffer.sld:
--------------------------------------------------------------------------------
1 | ;;> A text buffer for line-based data with [undo support][undo section].
2 | ;;> Operations on the buffer address lines, the first line starts at
3 | ;;> index 1. The special index 0 can be used with the [append command][append command]
4 | ;;> to insert text before the first line. For other commands, index 0 is
5 | ;;> equivalent to index 1. Targeting a line outside the current buffer
6 | ;;> bounds causes an error to be raised.
7 | ;;>
8 | ;;> [undo section]: #section-undo-stack
9 | ;;> [append command]: #buffer-append!
10 |
11 | (define-library (edward.buffer)
12 | (import (scheme base)
13 | (scheme case-lambda)
14 |
15 | (srfi 1)
16 |
17 | (only (chicken base) vector-resize)
18 |
19 | (edward util))
20 |
21 | (export make-buffer buffer->list buffer-length buffer-empty? buffer-ref
22 | buffer-append! buffer-remove! buffer-with-undo buffer-has-undo?
23 | buffer-undo! buffer-replace! buffer-join! buffer-move!)
24 |
25 | (include "buffer/stack.scm"
26 | "buffer/srfi214-minimal.scm"
27 | "buffer/buffer.scm"))
28 |
--------------------------------------------------------------------------------
/lib/buffer/buffer.scm:
--------------------------------------------------------------------------------
1 | ;;>| Buffer Interface
2 | ;;>
3 | ;;> Procedures for creating new buffers and related accessors.
4 |
5 | (define-record-type Line-Buffer
6 | (%make-buffer lines undo? undo-stack)
7 | line-buffer?
8 | (lines buffer-lines)
9 | (undo? buffer-undo? buffer-undo-set!)
10 | (undo-stack buffer-undo-stack buffer-undo-stack-set!))
11 |
12 | ;;> Create a new, initially empty, line buffer.
13 |
14 | (define (make-buffer)
15 | (%make-buffer (flexvector) #f (make-stack)))
16 |
17 | ;;> Returns the element at `index` in the `buffer`, starting at zero.
18 |
19 | (define (buffer-ref buffer index)
20 | (flexvector-ref (buffer-lines buffer) index))
21 |
22 | ;;> Convert the line buffer to a list of lines. Additionally, this
23 | ;;> procedure accepts an optional `start` and `end` parameter. If
24 | ;;> these parameters are given the list only contains the elements
25 | ;;> between `start` and `end`. By default the whole buffer is converted.
26 |
27 | (define (buffer->list buffer . o)
28 | (apply flexvector->list (buffer-lines buffer) o))
29 |
30 | ;;> Length of the buffer, i.e. amount of lines currently stored in it.
31 |
32 | (define (buffer-length buffer)
33 | (flexvector-length (buffer-lines buffer)))
34 |
35 | ;;> Predicate which returns true if the buffer is empty.
36 |
37 | (define (buffer-empty? buffer)
38 | (zero? (buffer-length buffer)))
39 |
40 | (define (buffer-register-undo buffer proc)
41 | (when (buffer-undo? buffer)
42 | (stack-push (buffer-undo-stack buffer) proc)))
43 |
44 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45 |
46 | ;;>| Undo Stack
47 | ;;>
48 | ;;> Procedures for managing the undo stack of the line buffer.
49 | ;;> The undo stack does not support multilevel undo.
50 | ;;> That is, the last undo can itself be undone using [buffer-undo!](#buffer-undo!).
51 |
52 | ;;> Execute the given `thunk` and make all `buffer` operations performed
53 | ;;> in thunk undoable.
54 |
55 | (define (buffer-with-undo buffer thunk)
56 | (stack-clear! (buffer-undo-stack buffer)) ;; no multi-level undo
57 | (buffer-undo-set! buffer #t)
58 |
59 | (guard
60 | (eobj
61 | (else
62 | (buffer-undo-set! buffer #f)
63 | (raise eobj)))
64 | (let ((r (thunk)))
65 | (buffer-undo-set! buffer #f)
66 | r)))
67 |
68 | ;;> Predicate to check if the undo stack is empty, returns false if it is.
69 |
70 | (define (buffer-has-undo? buffer)
71 | (not (stack-empty? (buffer-undo-stack buffer))))
72 |
73 | ;;> Revert last operation tracked by [buffer-with-undo](#buffer-with-undo).
74 | ;;> The undo is itself reversible via [buffer-undo!](#buffer-undo!).
75 |
76 | (define (buffer-undo! buffer)
77 | (define (%buffer-undo! buffer procs)
78 | (buffer-with-undo buffer
79 | (lambda ()
80 | (for-each (lambda (proc)
81 | (proc buffer))
82 | procs))))
83 |
84 | (let* ((stk (buffer-undo-stack buffer))
85 | (stksiz (stack-size stk)))
86 | (unless (zero? stksiz)
87 | (let ((procs (stack-pops stk stksiz)))
88 | (%buffer-undo! buffer procs)))))
89 |
90 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
91 |
92 | ;;>| Buffer Operations
93 | ;;>
94 | ;;> Procedures which modify the buffer content.
95 | ;;> All operations can be undone using [buffer-undo!](#buffer-undo!).
96 |
97 | ;;> Append the given `text` to the `buffer` after the given `line` number.
98 | ;;> The special line number 0 can be used here to add lines to the
99 | ;;> beginning of the buffer.
100 |
101 | (define (buffer-append! buffer line text)
102 | (flexvector-add-all! (buffer-lines buffer) line text)
103 | (buffer-register-undo buffer
104 | (lambda (buffer)
105 | ;; Will add an undo procedure to the stack, thus making
106 | ;; the undo of the append operation itself reversible.
107 | (buffer-remove! buffer (inc line) (+ line (length text))))))
108 |
109 | ;;> Removes all lines within the `buffer` at the given inclusive range
110 | ;;> range between `start` and `end`.
111 |
112 | (define (buffer-remove! buffer start end)
113 | (let* ((lines (buffer-lines buffer))
114 | (sline (max (dec start) 0))
115 | (bkvec (flexvector->list lines sline end)))
116 | (flexvector-remove-range! (buffer-lines buffer) sline end)
117 | (buffer-register-undo buffer
118 | (lambda (buffer)
119 | ;; Will add an undo procedure to the stack, thus making
120 | ;; the undo of the remove operation itself reversible.
121 | (buffer-append! buffer sline bkvec)))))
122 |
123 | ;; The following operations are all implemented in terms of
124 | ;; buffer-append! and buffer-undo! and are therefore reversible.
125 |
126 | ;;> Replace lines in the inclusive range between `start` and `end`
127 | ;;> with the data given by `text` which must be a list of lines
128 | ;;> (i.e. strings).
129 |
130 | (define (buffer-replace! buffer start end text)
131 | (let* ((sline (max (dec start) 0))
132 | (cap (- (buffer-length buffer) sline)))
133 | (buffer-remove! buffer start end)
134 | (buffer-append! buffer sline text)))
135 |
136 | ;;> Join lines in the inclusive range between `start` and `end`
137 | ;;> into a single line by removing all newline characters within
138 | ;;> the specified range.
139 |
140 | (define (buffer-join! buffer start end)
141 | (let* ((lines (buffer-lines buffer))
142 | (sindex (max (dec start) 0))
143 | (joined (apply
144 | string-append
145 | "" (flexvector->list lines sindex end))))
146 | (buffer-remove! buffer start end)
147 | (buffer-append!
148 | buffer
149 | sindex
150 | (list joined))))
151 |
152 | ;;> Move lines in the inclusive range between `start` and `end`
153 | ;;> to the destination line number `dest`. The destination *must*
154 | ;;> always be outside the specified inclusive range.
155 |
156 | (define (buffer-move! buffer start end dest)
157 | ;; Assumption: dest is always outside [start, end].
158 | (let* ((lines (buffer-lines buffer))
159 | (sindex (max (dec start) 0))
160 | (move (flexvector->list lines sindex end))
161 |
162 | (remove! (lambda () (buffer-remove! buffer start end)))
163 | (append! (lambda () (buffer-append! buffer dest move))))
164 | (if (> dest start)
165 | (begin (append!) (remove!))
166 | (begin (remove!) (append!)))))
167 |
--------------------------------------------------------------------------------
/lib/buffer/srfi214-minimal.scm:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) 2020-2021 Adam Nelson.
2 | ;;
3 | ;; Permission is hereby granted, free of charge, to any person obtaining a copy
4 | ;; of this software and associated documentation files (the "Software"), to
5 | ;; deal in the Software without restriction, including without limitation the
6 | ;; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | ;; sell copies of the Software, and to permit persons to whom the Software is
8 | ;; furnished to do so, subject to the following conditions:
9 | ;;
10 | ;; The above copyright notice and this permission notice (including the next
11 | ;; paragraph) shall be included in all copies or substantial portions of the
12 | ;; Software.
13 | ;;
14 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | ;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | ;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | ;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | ;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | ;; IN THE SOFTWARE.
21 |
22 | (define-record-type Flexvector
23 | (%make-flexvector fv-vector fv-length)
24 | flexvector?
25 | (fv-vector vec set-vec!)
26 | (fv-length flexvector-length set-flexvector-length!))
27 |
28 | (define (grow! fv)
29 | (define old-vec (vec fv))
30 | (define
31 | new-vec
32 | (vector-resize old-vec (quotient (* (vector-length old-vec) 3) 2)))
33 | (set-vec! fv new-vec)
34 | new-vec)
35 |
36 | (define (flexvector)
37 | (%make-flexvector (make-vector 4) 0))
38 |
39 | (define (flexvector-ref fv index)
40 | (vector-ref (vec fv) index))
41 |
42 | (define (flexvector-add-all! fv i xs)
43 | (let* ((len (flexvector-length fv))
44 | (xv (list->vector xs))
45 | (xvlen (vector-length xv))
46 | (v (let lp ((v (vec fv)))
47 | (if (< (+ len xvlen) (vector-length v)) v (lp (grow! fv))))))
48 | (vector-copy! v (+ i xvlen) v i len)
49 | (vector-copy! v i xv 0 xvlen)
50 | (set-flexvector-length! fv (+ len xvlen))
51 | fv))
52 |
53 | (define (flexvector-remove-range! fv start end)
54 | (let ((len (flexvector-length fv)))
55 | (when (< start 0) (set! start 0))
56 | (when (>= end len) (set! end len))
57 | (vector-copy! (vec fv) start (vec fv) end)
58 | (let ((new-len (- len (- end start))))
59 | (vector-fill! (vec fv) #f new-len len)
60 | (set-flexvector-length! fv new-len)))
61 | fv)
62 |
63 | ;; Inspired by chez-scheme's SRFI 214 flexvector->list implementation.
64 | (define (%flexvector->list fv start end)
65 | (if (< end start)
66 | (error "invalid sublist specification")
67 | (let ((vec (vec fv)))
68 | (let lp ((acc '()) (idx (dec end)))
69 | (if (< idx start)
70 | acc
71 | (lp (cons (vector-ref vec idx) acc)
72 | (dec idx)))))))
73 |
74 | (define flexvector->list
75 | (case-lambda
76 | ((fv)
77 | (flexvector->list fv 0 (flexvector-length fv)))
78 | ((fv start)
79 | (flexvector->list fv start (flexvector-length fv)))
80 | ((fv start end)
81 | (%flexvector->list fv start end))))
82 |
--------------------------------------------------------------------------------
/lib/buffer/stack.scm:
--------------------------------------------------------------------------------
1 | (define-record-type Stack
2 | (%make-stack store)
3 | stack?
4 | (store stack-store stack-store-set!))
5 |
6 | (define (make-stack)
7 | (%make-stack '()))
8 |
9 | (define (stack-clear! stack)
10 | (stack-store-set! stack '()))
11 |
12 | (define (stack-size stack)
13 | (length (stack-store stack)))
14 |
15 | (define (stack-empty? stack)
16 | (zero? (stack-size stack)))
17 |
18 | (define (stack-push stack elem)
19 | (stack-store-set!
20 | stack
21 | (cons elem (stack-store stack))))
22 |
23 | (define (stack-pop stack)
24 | (let* ((lst (stack-store stack))
25 | (top (car lst)))
26 | (stack-store-set! stack (cdr lst))
27 | top))
28 |
29 | (define (stack-pops stack amount)
30 | (if (<= amount 1)
31 | (list (stack-pop stack))
32 | (cons
33 | (stack-pop stack)
34 | (stack-pops stack (dec amount)))))
35 |
--------------------------------------------------------------------------------
/lib/cli.scm:
--------------------------------------------------------------------------------
1 | (define prompt "")
2 | (define silent? #f)
3 |
4 | (define (err msg)
5 | (let ((port (current-error-port)))
6 | (display "edward: " port)
7 | (display msg port)
8 | (newline port)))
9 |
10 | (define prompt-opt
11 | (option
12 | '(#\p "prompt") #t #f
13 | (lambda (o n x vals)
14 | (set! prompt x)
15 | vals)))
16 |
17 | (define silent-opt
18 | (option
19 | '(#\s "silent") #f #f
20 | (lambda (o n x vals)
21 | (set! silent? #t)
22 | vals)))
23 |
24 | (define (parse-args args flags)
25 | (reverse
26 | (args-fold
27 | args
28 | flags
29 | (lambda (o n x vals)
30 | (error "unrecognized option" n))
31 | cons
32 | '())))
33 |
34 | (define (run-editor filename)
35 | (let ((editor (make-text-editor exec-edit filename prompt silent?)))
36 | (editor-start editor (parse-cmd))))
37 |
38 | ;;> Entry point of the edward text editor. This function parses the
39 | ;;> provided command line arguments `args` and starts the
40 | ;;> read-eval-print loop. This command should therefore only be called
41 | ;;> after registering all editor commands.
42 |
43 | (define (edward-main . args)
44 | (let* ((flags (list prompt-opt silent-opt))
45 | (argv (if (null? args) (command-line) args))
46 | (files (cdr (parse-args argv flags))))
47 | (if prompt
48 | (case (length files)
49 | ((1) (run-editor (car files)))
50 | ((0) (run-editor ""))
51 | (else (err "specify one file or no files")))
52 | (err "missing prompt option argument"))))
53 |
--------------------------------------------------------------------------------
/lib/cli.sld:
--------------------------------------------------------------------------------
1 | ;;> Library implementing the edward command line interface.
2 | ;;> Most importantly, this library is responsible for parsing
3 | ;;> the command line options mandated by [POSIX][ed options]
4 | ;;> and afterward starts the read-eval-print loop of the editor.
5 | ;;>
6 | ;;> [ed options]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38_04
7 |
8 | (define-library (edward.cli)
9 | (import (scheme base)
10 | (scheme write)
11 | (scheme process-context)
12 |
13 | (srfi 37)
14 |
15 | (edward ed cmd)
16 | (edward ed posix)
17 | (edward ed editor))
18 |
19 | (export edward-main)
20 |
21 | (include "cli.scm"))
22 |
--------------------------------------------------------------------------------
/lib/ed/addr.sld:
--------------------------------------------------------------------------------
1 | ;;> This library provides an abstraction for parsing, representing, and
2 | ;;> operating on [ed addresses][ed addresses]. Conceptually, the library
3 | ;;> distinguishes single addresses and ranges. The latter consisting of a
4 | ;;> start and end address as well as a address separator (as defined in
5 | ;;> POSIX). The [parse-addrs][parse-addrs] procedure returns a list of
6 | ;;> address ranges. The editor implementation is capable of converting
7 | ;;> this list to a pair of line numbers using the [addrlst->lpair][addrlst->lpair]
8 | ;;> procedure. Command implementations expecting a range address receive
9 | ;;> this pair, commands which only expect a single address only receive
10 | ;;> the last element of the pair as an argument.
11 | ;;>
12 | ;;> [parse-addrs]: #parse-addrs
13 | ;;> [addrlst->lpair]: edward.ed.editor.html#addrlst->lpair
14 | ;;> [ed addresses]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38_13_02
15 |
16 | (define-library (edward.ed.addr)
17 | (import (scheme base)
18 | (scheme case-lambda)
19 |
20 | (srfi 1)
21 | (srfi 14)
22 |
23 | (matchable)
24 |
25 | (edward parse))
26 |
27 | (export make-addr make-range range? addr->range range->addr
28 | parse-addrs parse-addr-with-off expand-addr address-separator?)
29 |
30 | (include "addr.scm"))
31 |
--------------------------------------------------------------------------------
/lib/ed/cmd.sld:
--------------------------------------------------------------------------------
1 | ;;> Library for defining custom ed editor commands through provided
2 | ;;> macros. For each command, a parser and an executor needs to be defined.
3 | ;;> The parser is defined using edward [parser combinators][edward parse].
4 | ;;> The executor receives an [editor object][editor object] as well as the
5 | ;;> return value of the parser combinator as procedure arguments and modifies
6 | ;;> the editor state accordingly. Additionally, this library defines several
7 | ;;> utility procedures that are useful for defining [executor procedures][executor util]
8 | ;;> and ed [parser combinators][parser util].
9 | ;;>
10 | ;;> [edward parse]: edward.parse.html
11 | ;;> [editor object]: edward.ed.editor.html#section-text-editor-object
12 | ;;> [executor util]: #section-executor-utilities
13 | ;;> [parser util]: #section-parser-utilities
14 |
15 | (define-library (edward.ed.cmd)
16 | (import (scheme base)
17 | (scheme file)
18 | (scheme lazy)
19 |
20 | (srfi 1)
21 | (srfi 14)
22 |
23 | (only (chicken process) call-with-input-pipe call-with-output-pipe)
24 |
25 | (edward util)
26 | (edward parse)
27 | (edward ed addr)
28 | (edward ed editor))
29 |
30 | ;; Utility procedures to define custom editor commands.
31 | (export define-edit-cmd define-input-cmd define-print-cmd define-file-cmd
32 | parse-cmd-char parse-cmd parse-re parse-re-pair unwrap-command-list
33 | exec-command-list parse-filename parse-file-cmd write-lines
34 | read-from call-when-confirmed subst-nomatch-handler
35 | filename-cmd? register-command exec-command-list-interactive)
36 |
37 | ;; Editor command executors mandated by POSIX.
38 | (include "cmd.scm"))
39 |
--------------------------------------------------------------------------------
/lib/ed/editor.sld:
--------------------------------------------------------------------------------
1 | ;;> This library implements a [text editor object][section text-editor]
2 | ;;> which tracks an internal state that can be modified through defined
3 | ;;> [editor operations][section operations]. These operations operate on
4 | ;;> a pair of line numbers. POSIX [ed addresses][edward ed addr] can be
5 | ;;> translated to a pair of line numbers using
6 | ;;> [address translation][section translation] procedures described below.
7 | ;;>
8 | ;;> [section text-editor]: #section-text-editor-object
9 | ;;> [section operations]: #section-editor-operations
10 | ;;> [section translation]: #section-address-translation
11 | ;;> [edward ed addr]: edward.ed.addr.html
12 | ;;> [range->lpair]: #range->lpair
13 |
14 | (define-library (edward.ed.editor)
15 | (import (scheme base)
16 | (scheme file)
17 | (scheme case-lambda)
18 | (scheme process-context)
19 |
20 | (srfi 1)
21 |
22 | (matchable)
23 | (posix-regex)
24 |
25 | (only (chicken process signal) signal-mask!
26 | signal/quit signal/hup set-signal-handler!)
27 | (only (chicken port) terminal-port?)
28 |
29 | (edward util)
30 | (edward parse)
31 | (edward buffer)
32 | (edward ed addr))
33 |
34 | (export make-text-editor text-editor? text-editor-prevcmd
35 | text-editor-modified? text-editor-filename
36 | text-editor-filename-set! text-editor-modified-set!
37 | text-editor-help? text-editor-help-set!
38 | text-editor-line text-editor-error
39 | text-editor-last-cmd-set!)
40 |
41 | (export editor-start editor-error editor-filename editor-make-regex
42 | editor-exec-cmdlist editor-mark-line editor-shell-cmd
43 | editor-xexec editor-exec make-cmd editor-cmd? cmd-args editor-raise
44 | editor-goto! editor-interactive editor-restr editor-verbose
45 | editor-reset! editor-get-lnum editor-get-lines editor-in-range?
46 | editor-undo! editor-lines editor-append! editor-replace!
47 | editor-join! editor-remove! editor-move! editor-line-numbers
48 | addr->line range->lpair editor-toggle-prompt! addrlst->lpair)
49 |
50 | (include "editor.scm"))
51 |
--------------------------------------------------------------------------------
/lib/ed/posix.sld:
--------------------------------------------------------------------------------
1 | ;;> This library implements the editor commands mandated by the
2 | ;;> [POSIX.1-2008 ed(1)][posix commands] specification. This is achieved
3 | ;;> by leveraging the [edward ed cmd][edward ed cmd] abstraction. The
4 | ;;> executor for all POSIX ed commands is exported and can be reused to
5 | ;;> implement new commands.
6 | ;;>
7 | ;;> [posix commands]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38_13_03
8 | ;;> [edward ed cmd]: edward.ed.cmd.html
9 |
10 | (define-library (edward.ed.posix)
11 | (import (scheme base)
12 | (scheme write)
13 | (scheme process-context)
14 |
15 | (srfi 1)
16 | (srfi 14)
17 |
18 | (posix-regex)
19 | (matchable)
20 |
21 | (only (chicken process) system)
22 | (only (chicken string) string-split)
23 |
24 | (edward util)
25 | (edward parse)
26 | (edward replace)
27 | (edward ed cmd)
28 | (edward ed addr)
29 | (edward ed editor))
30 |
31 | (export %exec-edit %exec-quit exec-append exec-change exec-command
32 | exec-copy exec-delete exec-edit exec-filename exec-global
33 | exec-help exec-insert exec-interactive exec-join
34 | exec-line-number exec-list exec-mark exec-move exec-null
35 | exec-number exec-print exec-prompt exec-quit exec-read
36 | exec-subst exec-undo exec-write)
37 |
38 | (include "posix.scm"))
39 |
--------------------------------------------------------------------------------
/lib/parse.sld:
--------------------------------------------------------------------------------
1 | ;;> This is a stripped-down and minimally modified version of [chibi parse][chibi parse],
2 | ;;> a parser combinator library with optional memoization. This version of the library
3 | ;;> is specifically designed to faciliate building read-eval-print loops with parser
4 | ;;> combinators.
5 | ;;>
6 | ;;> Apart from [parse streams][stream section], the central abstraction of this libary
7 | ;;> is therefore a [REPL][repl section] type which continously reads data from standard
8 | ;;> input and parses this data with parsers constructed using provided parser combinators.
9 | ;;>
10 | ;;> An exemplary parser may be constructed as follows:
11 | ;;>
12 | ;;> ```
13 | ;;> (import (srfi 14) (edward parse))
14 | ;;>
15 | ;;> (define hexadecimal
16 | ;;> (parse-map
17 | ;;> (parse-seq
18 | ;;> (parse-string "0x")
19 | ;;> (parse-map
20 | ;;> (parse-token char-set:hex-digit)
21 | ;;> (lambda (str)
22 | ;;> (string->number str 16))))
23 | ;;> cadr))
24 | ;;> ```
25 | ;;>
26 | ;;> This parser recognizes hexadecimal integers using the character set definition
27 | ;;> provided by [SRFI 14][srfi 14] and transform these characters into a Scheme
28 | ;;> number type using [parse-map][parse-map]. Refer to the documentation below
29 | ;;> for more information on available combinators.
30 | ;;>
31 | ;;> [chibi parse]: https://synthcode.com/scheme/chibi/lib/chibi/parse.html
32 | ;;> [stream section]: #section-parse-streams
33 | ;;> [repl section]: #section-read–eval–print-loop
34 | ;;> [srfi 14]: https://srfi.schemers.org/srfi-14/srfi-14.html
35 | ;;> [parse-map]: #parse-map
36 |
37 | (define-library (edward.parse)
38 | (import (scheme base)
39 | (scheme char)
40 | (scheme file)
41 | (scheme write)
42 |
43 | (srfi 1)
44 | (srfi 14)
45 |
46 | (edward util)
47 |
48 | (only (chicken file posix) file-read file-close fileno/stdin)
49 | (only (chicken process signal) set-signal-handler! signal/int))
50 |
51 | ;; repl.scm
52 | (export make-repl repl? repl-run repl-interactive repl-prompt? repl-set-prompt!)
53 |
54 | ;; parse.scm
55 | (export call-with-parse parse parse-fully parse-fold parse-failure
56 | parse->list parse-fully->list
57 | file->parse-stream string->parse-stream parse-stream-substring
58 | parse-stream-start? parse-stream-end? parse-stream-ref
59 | parse-anything parse-nothing parse-epsilon
60 | parse-seq parse-and parse-or parse-not list->parse-seq
61 | parse-repeat parse-repeat+ parse-optional
62 | parse-map parse-map-substring parse-ignore parse-assert
63 | parse-atomic parse-commit parse-lazy parse-memoize
64 | parse-char parse-not-char
65 | parse-string parse-token
66 | parse-beginning parse-end
67 | parse-beginning-of-line parse-end-of-line
68 | parse-with-failure-reason
69 | make-parse-stream)
70 |
71 | ;; parse-util.scm
72 | (export parse-fail parse-bind parse-as-string parse-digits parse-lowercase
73 | parse-default parse-newline parse-blank
74 | parse-blanks+ parse-blanks parse-between parse-esc
75 | parse-strip-blanks parse-blanks-seq parse-line parse-alist
76 | parse-with-context parse-regex-lit* parse-regex-lit)
77 |
78 | (include "parse/repl.scm"
79 | "parse/parse.scm"
80 | "parse/util.scm"))
81 |
--------------------------------------------------------------------------------
/lib/parse/repl.scm:
--------------------------------------------------------------------------------
1 | ;;>| Read–Eval–Print Loop
2 | ;;>
3 | ;;> REPL abstraction which provides a read-eval-print loop that
4 | ;;> continously reads data from standard input and parses this
5 | ;;> input data using provided parser combinators. The REPL
6 | ;;> operates on a [parse stream](#section-parse-streams) internally.
7 |
8 | ;;> Create an new REPL instance with the given input `prompt` string.
9 |
10 | (define (make-repl prompt)
11 | (let ((prompt? (not (empty-string? prompt))))
12 | (%make-repl
13 | (if prompt? prompt "*")
14 | prompt?
15 | (make-parse-stream "stdin" fileno/stdin)
16 | 0)))
17 |
18 | (define (repl-state-set! repl source index)
19 | (repl-stream-set! repl source)
20 | (repl-index-set! repl index))
21 |
22 | ;;> Record type representing the REPL.
23 | (define-record-type Read-Eval-Print-Loop
24 | (%make-repl prompt-str prompt? stream index)
25 | ;;> Predicate which returns true if the given object was created using [make-repl](#make-repl).
26 | repl?
27 | ;; Prompt string used for input prompt.
28 | (prompt-str repl-prompt-str)
29 | ;; Whether the prompt should be shown or hidden.
30 | (prompt?
31 | ;;> Predicate which returns true if the prompt should be shown.
32 | repl-prompt?
33 |
34 | ;;> Change prompt visibility, a truth value means the prompt is shown.
35 | repl-set-prompt!)
36 | ;; Parse stream used for the parser combinator.
37 | (stream repl-stream repl-stream-set!)
38 | ;; Last index in parse stream.
39 | (index repl-index repl-index-set!))
40 |
41 | ;; Skip all buffered chunks, i.e. next read will block.
42 |
43 | (define (repl-skip-chunks! repl)
44 | (define (%repl-skip-chunks! source i)
45 | (if (>= (+ i 1) (vector-length (parse-stream-buffer source)))
46 | (%repl-skip-chunks! (parse-stream-tail source) i) ;; go to last chunck
47 | (values
48 | source
49 | ;; inc to go beyond last char.
50 | (inc (parse-stream-max-char source)))))
51 |
52 | (let-values (((source i)
53 | (%repl-skip-chunks!
54 | (repl-stream repl)
55 | (repl-index repl))))
56 | (repl-state-set! repl source i)))
57 |
58 | (define (repl-parse repl f sk fk)
59 | (define (stream-next-line source idx)
60 | (let* ((next-index (parse-stream-next-index source idx))
61 | (next-source (parse-stream-next-source source idx))
62 | (char (parse-stream-ref source idx)))
63 | (if (or (eof-object? char) (char=? char #\newline))
64 | (cons next-source next-index) ;; first index after newline/eof
65 | (stream-next-line
66 | next-source
67 | next-index))))
68 |
69 | (call-with-parse f
70 | (repl-stream repl)
71 | (repl-index repl)
72 | (lambda (r s i fk)
73 | (repl-state-set! repl s i)
74 | (sk (repl-line repl i) r))
75 | (lambda (s i reason)
76 | (let ((line (repl-line repl i))
77 | (next (stream-next-line (repl-stream repl) i)))
78 | (repl-state-set! repl (car next) (cdr next))
79 | (fk line reason)))))
80 |
81 | (define (repl-line repl index)
82 | (let ((s (repl-stream repl)))
83 | (inc ;; XXX: For some reason line start at zero.
84 | (+
85 | (parse-stream-line s)
86 | (car (parse-stream-count-lines s (parse-stream-max-char s)))))))
87 |
88 | ;;> Start the REPL given by `repl`, and continuously parse input using
89 | ;;> the provided parser `f`. Successfully parsed input is passed to
90 | ;;> the success continuation `sk`, which receives the line number and
91 | ;;> parser result as procedure arguments. If the parser failed for the
92 | ;;> current input, the failure continuation `fk` is invoked. This
93 | ;;> continuation receives the line number and failure reason as
94 | ;;> procedure arguments. Lastly, an interrupt continuation must
95 | ;;> also be provided which is invoked on `SIGINT`. This continuation
96 | ;;> is not passed any arguments.
97 |
98 | (define (repl-run repl f sk fk ik)
99 | (when (repl-prompt? repl)
100 | (display (repl-prompt-str repl))
101 | (flush-output-port))
102 |
103 | ;; Allow parsing itself (especially of input mode commands) to be
104 | ;; interrupted by SIGINT signals. See "Asynchronous Events" in ed(1).
105 | (call-with-current-continuation
106 | (lambda (k)
107 | (set-signal-handler!
108 | signal/int
109 | (lambda (signum)
110 | (ik)
111 | (repl-skip-chunks! repl)
112 | (k #f)))
113 |
114 | (begin
115 | (repl-parse repl f sk fk)
116 | (k #f))))
117 |
118 | (repl-run repl f sk fk ik))
119 |
120 | ;;> Run a parser interactively within the REPL. That is, deviate from
121 | ;;> the standard REPL parser and instead parse the next input line
122 | ;;> with the given parser `f`. On success, returns the result of `f`
123 | ;;> otherwise, invokes the provided failure continuation `fk`.
124 |
125 | (define (repl-interactive repl f fk)
126 | (repl-parse repl f (lambda (line value) value) fk))
127 |
--------------------------------------------------------------------------------
/lib/parse/util.scm:
--------------------------------------------------------------------------------
1 | ;;>| Utility Parsing Combinators
2 | ;;>
3 | ;;> Additional high-level combinators implemented using the aforementioned
4 | ;;> [basic combinators][basic section]. The provided high-level combinators,
5 | ;;> return more useful parser error messages then the basic ones.
6 | ;;>
7 | ;;> [basic section]: #section-basic-parsing-combinators
8 |
9 | ;;> Parser which always fails with the given error message.
10 |
11 | (define (parse-fail msg)
12 | (lambda (source index sk fk)
13 | (fk source index msg)))
14 |
15 | ;;> Bind a constant `value` to a given `parser`.
16 | ;;> That is, always return this value if the parser succeeds.
17 |
18 | (define (parse-bind value parser)
19 | (parse-map
20 | parser
21 | (lambda (x) value)))
22 |
23 | ;;> Run a parser `f`, which *must* return a list, and convert
24 | ;;> its return value to a string using the `list->string` procedure.
25 |
26 | (define (parse-as-string parser)
27 | (parse-map
28 | parser
29 | list->string))
30 |
31 | ;;> Parse one or more digits (i.e. `0-9`), interpret them as a
32 | ;;> decimal number, and return this number.
33 |
34 | (define parse-digits
35 | (parse-with-failure-reason
36 | (parse-map
37 | (parse-token char-set:digit)
38 | string->number)
39 | "expected digits"))
40 |
41 | ;;> Parse an ASCII lowercase character (i.e. `a-z`).
42 |
43 | (define parse-lowercase
44 | (parse-with-failure-reason
45 | (parse-char char-set:lower-case)
46 | "expected lowercase character"))
47 |
48 | ;;> Attempt parsing using the given parser `f`, if it fails return a default value `def`.
49 |
50 | (define (parse-default f def)
51 | (parse-map
52 | (parse-optional f)
53 | (lambda (x)
54 | (if x x def))))
55 |
56 | ;;> Parse a newline character.
57 |
58 | (define parse-newline
59 | (parse-with-failure-reason
60 | (parse-char #\newline)
61 | "expected newline"))
62 |
63 | ;;> Parse a single blank character (i.e. horizontal whitespace).
64 |
65 | (define parse-blank
66 | (parse-with-failure-reason
67 | (parse-char char-set:blank)
68 | "expected whitespace"))
69 |
70 | ;;> Parse one or more blank characters.
71 |
72 | (define parse-blanks+
73 | (parse-with-failure-reason
74 | (parse-token char-set:blank)
75 | "expected whitespaces"))
76 |
77 | ;;> Parse zero or more blank characters.
78 |
79 | (define parse-blanks
80 | (parse-optional parse-blanks+))
81 |
82 | ;;> Invokes parser `f` between the parsers `lhs` and `rhs`.
83 |
84 | (define (parse-between lhs f rhs)
85 | (parse-map
86 | (parse-seq lhs f rhs)
87 | cadr))
88 |
89 | ;;> Returns the result of parser `f` but allows preceding its input
90 | ;;> with a backslash character to escape it in the parsed input format.
91 |
92 | (define (parse-esc f)
93 | (parse-map
94 | (parse-seq
95 | (parse-char #\\)
96 | f)
97 | cadr))
98 |
99 | ;;> Parse an `alist` mapping chars to values which should be returned for each char.
100 |
101 | (define (parse-alist alist)
102 | (apply
103 | parse-or
104 | (map
105 | (lambda (x)
106 | (parse-map
107 | (parse-char (car x))
108 | (lambda (_)
109 | (cdr x))))
110 | alist)))
111 |
112 | ;; Utility procedure for parsing ed(1) BRE addresses.
113 |
114 | (define (%parse-regex-lit ch end)
115 | (parse-with-failure-reason
116 | (parse-atomic
117 | (parse-as-string
118 | (parse-between
119 | (parse-char ch)
120 | (parse-repeat (parse-or
121 | (parse-esc (parse-char ch))
122 | (parse-char (char-set-complement (char-set ch #\newline)))))
123 | end)))
124 | "expected regex"))
125 |
126 | ;;> Parse a regex literal which is enclosed by the character `ch`.
127 |
128 | (define (parse-regex-lit ch)
129 | (%parse-regex-lit
130 | ch
131 | (parse-char ch)))
132 |
133 | ;;> Parse a regex literal which starts with character `ch` and is
134 | ;;> terminated by the same character or the end of line.
135 |
136 | (define (parse-regex-lit* ch)
137 | (%parse-regex-lit
138 | ch
139 | (parse-or
140 | (parse-char ch)
141 | parse-end-of-line)))
142 |
143 | ;;> Invoke given parser and strip trailing blanks (if any).
144 |
145 | (define (parse-strip-blanks parser)
146 | (parse-map
147 | (parse-seq
148 | parser
149 | parse-blanks)
150 | car))
151 |
152 | ;;> Like [parse-seq](#parse-seq) but skip blanks *before* each parser.
153 |
154 | (define (parse-blanks-seq . o)
155 | (define (%parse-blanks-seq lst)
156 | (parse-seq-list
157 | (apply append
158 | (zip (make-list
159 | (length lst)
160 | (parse-ignore parse-blanks))
161 | lst))))
162 |
163 | (%parse-blanks-seq o))
164 |
165 | ;;> Parse a single line (excluding the terminating newline character).
166 |
167 | (define parse-line
168 | (parse-atomic
169 | (parse-or
170 | (parse-bind "" parse-newline) ;; empty line
171 | (parse-map
172 | (parse-seq
173 | (parse-token (lambda (x) (not (char=? x #\newline))))
174 | ;; XXX: parse-end-of-line does _not_ consume the end-of-file.
175 | ;; This is crucial for parse-input-mode to work correctly.
176 | (parse-or parse-newline parse-end-of-line))
177 | car))))
178 |
179 | ;;> Feed the result of the parser `ctx` to a single argument procedure `f`.
180 | ;;> The procedure must then return a new parser which is executed
181 | ;;> afterwards on the same index as `ctx`.
182 |
183 | (define (parse-with-context ctx f)
184 | (lambda (source index sk fk)
185 | (let* ((yield (lambda (r s i fk) r))
186 | (value (call-with-parse ctx source index yield)))
187 | (if value ;; default fk returns #f on error
188 | ((f value) source index sk fk)
189 | (fk source index "context parser failed")))))
190 |
--------------------------------------------------------------------------------
/lib/replace.scm:
--------------------------------------------------------------------------------
1 | ;;>| Replacement Parser
2 | ;;>
3 | ;;> Edward [parser combinators][edward parse] for parsing replacement strings.
4 | ;;>
5 | ;;> [edward parse]: edward.parse.html
6 |
7 | (define parse-backref
8 | (parse-map
9 | (parse-seq
10 | (parse-char #\\)
11 | parse-digits)
12 | (lambda (lst)
13 | (cons 'backref (cadr lst)))))
14 |
15 | (define parse-matched
16 | (parse-map
17 | (parse-char #\&)
18 | (lambda (ch)
19 | (cons 'matched ch))))
20 |
21 | (define (parse-restr delim)
22 | (define replace-ctrl
23 | (char-set-adjoin (char-set #\\ #\& #\newline) delim))
24 |
25 | (parse-map
26 | (parse-as-string
27 | (parse-repeat+
28 | (parse-or
29 | ;; special handling for '%' as it does not neccessarily
30 | ;; need to be escaped unless it's the only character.
31 | (parse-esc
32 | (parse-char (char-set-adjoin replace-ctrl #\%)))
33 | (parse-not-char replace-ctrl))))
34 | (lambda (str)
35 | (cons 'restr str))))
36 |
37 | ;;> Parse a replacement string within text enclosed with the delimiter
38 | ;;> `delim`. While the combinator does not parse the enclosed character,
39 | ;;> it ensures that this `delim` character is escaped (using a `\`)
40 | ;;> within the replacement.
41 | ;;>
42 | ;;> Refer to the documentation of the [ed substitute][ed substitute]
43 | ;;> command for more information on special character support within
44 | ;;> the replacement. All of these special characters can also be
45 | ;;> escaped.
46 | ;;>
47 | ;;> [ed substitute]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38_13_25
48 |
49 | (define (parse-replace delim)
50 | (parse-map
51 | (parse-repeat
52 | (parse-atomic
53 | (parse-or
54 | parse-backref
55 | parse-matched
56 | (parse-restr delim))))
57 | (lambda (lst)
58 | ;; If the replacement is empty replace matched text with an empty string.
59 | (if (null? lst)
60 | (cons '(restr . "") lst)
61 | lst))))
62 |
63 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64 |
65 | ;;>| Replacement Procedures
66 | ;;>
67 | ;;> Procedures for performing replacements using a parsed replacement string.
68 |
69 | (define (submatch subm bv n)
70 | (if (>= n (vector-length subm))
71 | (string->utf8 (number->string n)) ;; XXX: Handling for invalid backreferences
72 | (let ((match (vector-ref subm n)))
73 | (if match
74 | (bytevector-copy bv (car match) (cdr match))
75 | #u8()))))
76 |
77 | (define (regex-replace* regex subst bv nth)
78 | (define (apply-replacement subm bv replacement)
79 | (fold (lambda (x y)
80 | (bytevector-append y
81 | (match x
82 | (('restr . s) (string->utf8 s))
83 | (('matched . _) (submatch subm bv 0))
84 | (('backref . n) (submatch subm bv n)))))
85 | #u8() replacement))
86 |
87 | ;; TODO: Refactor this function and make it more readable.
88 | ;; Also don't rely on (values …) truncation (not in R7RS).
89 | (define (%regex-replace* re start n)
90 | (let* ((v (bytevector-copy bv start))
91 | (subm (regex-exec regex v)))
92 | (if subm
93 | (let* ((m (vector-ref subm 0)) ;; submatch for entire regex
94 | (s (car m)) ;; start of submatch
95 | (e (cdr m)) ;; end of submatch
96 |
97 | (i (+ start e)) ;; next index in bv
98 | (r (delay (bytevector-append
99 | (bytevector-copy v 0 s)
100 | (apply-replacement subm v re)))))
101 | (values
102 | (if (eqv? n nth)
103 | (bytevector-append (force r) (bytevector-copy bv i))
104 | (bytevector-append
105 | (if (zero? nth) (force r) (bytevector-copy v 0 e))
106 | (%regex-replace* re i (+ n 1))))
107 | #t))
108 | (values v #f))))
109 |
110 | (%regex-replace* subst 0 1))
111 |
112 | ;;> Replace `nth` occurrence of `regex` in `str` with `subst`. If `nth`
113 | ;;> is zero, all occurrences are replaced. Returns two results: The string
114 | ;;> after performing all replacement and a boolean indicating if any
115 | ;;> replacements were successfully performed. The `regex` must be
116 | ;;> created using [make-regex][make-regex], while the replacement string
117 | ;;> `subst` must be parsed using [parse-replace][parse-replace].
118 | ;;>
119 | ;;> [make-regex]: https://wiki.call-cc.org/eggref/5/posix-regex#make-regex
120 | ;;> [parse-replace]: #parse-replace
121 |
122 | (define (regex-replace regex subst str nth)
123 | ;; regexec(3p) offsets are byte, not character offsets.
124 | ;; Thus, the string needs to be converted to a bytevector.
125 | (let-values (((result modified) (regex-replace* regex subst (string->utf8 str) nth)))
126 | (values (utf8->string result) modified)))
127 |
--------------------------------------------------------------------------------
/lib/replace.sld:
--------------------------------------------------------------------------------
1 | ;;> This library implementes [BRE][bre posix] regex replacements on top
2 | ;;> of the existing [posix-regex][posix-regex egg] library.
3 | ;;>
4 | ;;> [posix-regex egg]: https://wiki.call-cc.org/eggref/5/posix-regex
5 | ;;> [bre posix]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html
6 |
7 | (define-library (edward.replace)
8 | (import (scheme base)
9 | (scheme lazy)
10 |
11 | (srfi 1)
12 | (srfi 14)
13 |
14 | (matchable)
15 | (posix-regex)
16 |
17 | (edward parse))
18 |
19 | (export parse-replace regex-replace)
20 |
21 | (include "replace.scm"))
22 |
--------------------------------------------------------------------------------
/lib/util.scm:
--------------------------------------------------------------------------------
1 | ;;>| String Procedures
2 | ;;>
3 | ;;> Utility procedures which operate on strings.
4 |
5 | ;;> Return true if the given string `str` is the empty string.
6 |
7 | (define (empty-string? str)
8 | (zero? (string-length str)))
9 |
10 | ;;> Pad given string `str` with given padding string `pad` to `length`.
11 |
12 | (define (pad-string str pad length)
13 | (if (>= (string-length str) length)
14 | str
15 | (pad-string (string-append pad str) pad length)))
16 |
17 | ;;> Convert string to a human readable representation as mandated
18 | ;;> by the ed [list command][ed list].
19 | ;;>
20 | ;;> [ed list]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38_13_17
21 |
22 | (define (string->human-readable str)
23 | ;; Length at which lines are folded.
24 | (define fold-length
25 | (let*-values (((padding) 8)
26 | ((port) (current-output-port))
27 | ((_ cols) (if (terminal-port? port)
28 | (terminal-size port)
29 | (values 0 0))))
30 | (if (> cols padding)
31 | (- cols padding)
32 | 72)))
33 |
34 | (define (byte->human-readable byte)
35 | (case byte
36 | ;; Mapping according to Table 5-1 in POSIX-1.2008.
37 | ((#x5C) "\\\\")
38 | ((#x07) "\\a")
39 | ((#x08) "\\b")
40 | ((#x0C) "\\f")
41 | ((#x0D) "\\r")
42 | ((#x09) "\\t")
43 | ((#x0B) "\\v")
44 |
45 | ;; End of each line shall be marked with a `$` character.
46 | ((#x0A) "$\n")
47 | ;; `$` character within the line should be escaped.
48 | ((#x24) "\\$")
49 |
50 | ;; Non-printable characters are represented in octal.
51 | (else
52 | (if (ascii-printable? byte)
53 | (string (integer->char byte))
54 | (string-append "\\" (pad-string (number->string byte 8) "0" 3))))))
55 |
56 | ;; Fold lines at fold-length and convert bytes according to procedure above.
57 | (let ((bv (string->utf8 str)))
58 | (fold (lambda (idx out)
59 | (let* ((byte (bytevector-u8-ref bv idx))
60 | (ret (string-append out (byte->human-readable byte))))
61 | (if (and (not (zero? idx))
62 | (zero? (modulo idx fold-length)))
63 | (string-append ret "\\\n")
64 | ret)))
65 | "" (iota (bytevector-length bv)))))
66 |
67 | ;;> Join a list of path elements (i.e. strings) using `/` as a path separator.
68 |
69 | (define (path-join . elems)
70 | (fold-right
71 | (lambda (elem path)
72 | (if (empty-string? path)
73 | elem
74 | (string-append elem "/" path)))
75 | "" elems))
76 |
77 | ;;> Return amount of bytes in a string.
78 |
79 | (define (count-bytes str)
80 | ;; Technically, we would have to convert the string to a bytevector here and
81 | ;; then count the length of that bytevector to obtain the number of bytes
82 | ;; and not the number of characters. However, CHICKEN 5 is not fully unicode
83 | ;; aware and hence string-length actually counts bytes and not characters.
84 | ;;
85 | ;; Additionally a string->utf8 conversion is very expensive especially when
86 | ;; loading large files using edward. Therefore, ideally, we would obtain the
87 | ;; amount of bytes directly through the read procedure in the future.
88 | (string-length str))
89 |
90 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
91 |
92 | ;;>| IO Procedures
93 | ;;>
94 | ;;> Procedures which deal with input/output.
95 |
96 | ;;> Write `lines`, i.e. a list of non-newline terminated strings to a
97 | ;;> given `port`. Returns the amount of bytes written to the port
98 | ;;> (including any newline characters).
99 |
100 | (define (lines->port lines port)
101 | (fold (lambda (line num)
102 | (let ((line (string-append line "\n")))
103 | (write-string line port)
104 | (+ num (count-bytes line))))
105 | 0 lines))
106 |
107 | ;;> Read from given `port` as a list of lines. Returns pair of retrieved
108 | ;;> lines and total amount of bytes read from the port (including
109 | ;;> newlines).
110 |
111 | (define (port->lines port)
112 | (let ((lines (read-lines port)))
113 | (cons
114 | lines
115 | (fold (lambda (l n)
116 | ;; +1 for newline stripped by read-lines.
117 | ;; XXX: Buggy if last line is not not terminated with \n.
118 | (+ 1 n (count-bytes l))) 0 lines))))
119 |
120 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
121 |
122 | ;;>| Miscellaneous
123 | ;;>
124 | ;;> Miscellaneous utility procedures.
125 |
126 | ;;> Syntactic sugar to increment a number by one.
127 | (define (inc n) (+ n 1))
128 | ;;> Syntactic sugar to decrement a number by one.
129 | (define (dec n) (- n 1))
130 |
131 | ;;> Identity function, always returns the given value.
132 |
133 | (define (id x) x)
134 |
135 | ;;> Returns all values of an `alist`, discarding the keys.
136 |
137 | (define (alist-values alist)
138 | (map cdr alist))
139 |
140 | ;;> Like `display` but prints multiple objects and adds a trailing newline.
141 |
142 | (define (println . objs)
143 | (apply fprintln (current-output-port) objs))
144 |
145 | ;;> Like [println](#println) but allows specification of a custom output `port`.
146 |
147 | (define (fprintln port . objs)
148 | (for-each (lambda (obj) (display obj port)) objs)
149 | (newline port))
150 |
151 | ;;> Whether the given `integer` does not represent an ASCII control character.
152 |
153 | (define (ascii-printable? integer)
154 | (and (>= integer #x20) (<= integer #x7e)))
155 |
156 | ;;> Return path to home directory of current user.
157 | ;;> This procedure emits an error if the environment variable `HOME` is unset.
158 |
159 | (define (user-home)
160 | (let ((home (get-environment-variable "HOME")))
161 | (if home
162 | home
163 | (error "environment variable 'HOME' not set"))))
164 |
--------------------------------------------------------------------------------
/lib/util.sld:
--------------------------------------------------------------------------------
1 | ;;> This library provides various generic utility procedures.
2 |
3 | (define-library (edward.util)
4 | (import (scheme base)
5 | (scheme write)
6 | (scheme file)
7 | (scheme process-context)
8 |
9 | (srfi 1)
10 |
11 | (only (chicken port) terminal-port? terminal-size)
12 | (only (chicken io) read-lines))
13 |
14 | (export inc dec id alist-values fprintln println empty-string?
15 | pad-string string->human-readable path-join user-home
16 | count-bytes lines->port port->lines)
17 |
18 | (include "util.scm"))
19 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-eval-order/cmds:
--------------------------------------------------------------------------------
1 | ;1;n
2 | ;,1,;n
3 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-eval-order/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-eval-order/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | foo
5 | bar
6 | foo
7 | test
8 | foo
9 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-fully-eval/cmds:
--------------------------------------------------------------------------------
1 | 3;/foo/;+2p
2 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-fully-eval/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-chain-fully-eval/testdata/input-file:
--------------------------------------------------------------------------------
1 | this line already contains the string "foo"
2 | however, we only start searching at line 3
3 | <--we start searching here-->
4 | hence "foo" will not be matched before line 3.
5 | line 1 after match
6 | line 2 after match
7 | last line
8 |
--------------------------------------------------------------------------------
/tests/integration/address-range-large-address/cmds:
--------------------------------------------------------------------------------
1 | 9223372036854775808,3947209347923759032m256
2 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-list/cmds:
--------------------------------------------------------------------------------
1 | /foo/;+3l
2 | /foo/;+3l
3 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-list/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-list/testdata/input-file:
--------------------------------------------------------------------------------
1 | this line contains the word 'foo'
2 | and aftr this line there are
3 | 5 more lines
4 | which can be printed
5 | by an ed range
6 |
7 | however, this line also has the word 'foo'
8 | but no 5 lines after it, hence causing an error when selected as a range start.
9 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-number/cmds:
--------------------------------------------------------------------------------
1 | /foo/;+5n
2 | /foo/;+5n
3 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-number/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-number/testdata/input-file:
--------------------------------------------------------------------------------
1 | this line contains the word 'foo'
2 | and aftr this line there are
3 | 5 more lines
4 | which can be printed
5 | by an ed range
6 |
7 | however, this line also has the word 'foo'
8 | but no 5 lines after it, hence causing an error when selected as a range start.
9 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-print/cmds:
--------------------------------------------------------------------------------
1 | /foo/;+5p
2 | /foo/;+5p
3 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-range-semicolon-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | this line contains the word 'foo'
2 | and aftr this line there are
3 | 5 more lines
4 | which can be printed
5 | by an ed range
6 |
7 | however, this line also has the word 'foo'
8 | but no 5 lines after it, hence causing an error when selected as a range start.
9 |
--------------------------------------------------------------------------------
/tests/integration/address-ranges/cmds:
--------------------------------------------------------------------------------
1 | /^## Foobar/,/^##/p
2 | /^## Foobar/;/^##/p
3 |
--------------------------------------------------------------------------------
/tests/integration/address-ranges/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-ranges/testdata/input-file:
--------------------------------------------------------------------------------
1 | The file starts here.
2 |
3 | ## Foobar
4 |
5 | Bla
6 | bla
7 | bla
8 |
9 | ## Foobaz
10 |
11 | Foo bar bla.
12 |
13 | ## Test
14 |
15 | test 123
16 | 456.
17 |
--------------------------------------------------------------------------------
/tests/integration/address-regex-syntax-error/cmds:
--------------------------------------------------------------------------------
1 | /\{foo,foo\}/p
2 |
--------------------------------------------------------------------------------
/tests/integration/address-regex-syntax-error/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/address-regex-syntax-error/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/append-and-list/cmds:
--------------------------------------------------------------------------------
1 | al
2 | τ
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-and-list/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-and-list/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/append-and-n/cmds:
--------------------------------------------------------------------------------
1 | an
2 | baz
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-and-n/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-and-n/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/append-and-print/cmds:
--------------------------------------------------------------------------------
1 | ap
2 | baz
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-and-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-and-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/append-at-beginning/cmds:
--------------------------------------------------------------------------------
1 | 0a
2 | 123
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-at-beginning/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-at-beginning/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/append-at-end/cmds:
--------------------------------------------------------------------------------
1 | a
2 | 123
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-at-end/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-at-end/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/append-between/cmds:
--------------------------------------------------------------------------------
1 | 0+1a
2 | ---
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-between/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-between/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | baz
3 |
--------------------------------------------------------------------------------
/tests/integration/append-empty-not-modified/cmds:
--------------------------------------------------------------------------------
1 | a
2 | .
3 | q
4 |
--------------------------------------------------------------------------------
/tests/integration/append-line-update/cmds:
--------------------------------------------------------------------------------
1 | 2a
2 | 3
3 | .
4 | a
5 | 4
6 | .
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/append-line-update/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-line-update/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 5
4 | 6
5 |
--------------------------------------------------------------------------------
/tests/integration/append-newlines/cmds:
--------------------------------------------------------------------------------
1 | a
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | foo
10 |
11 |
12 |
13 |
14 |
15 | .
16 |
--------------------------------------------------------------------------------
/tests/integration/append-nth/cmds:
--------------------------------------------------------------------------------
1 | 2a
2 | foobar
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/append-nth/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/append-nth/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/change-and-n/cmds:
--------------------------------------------------------------------------------
1 | 3,$cn
2 | test
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/change-and-n/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-and-n/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/change-default/cmds:
--------------------------------------------------------------------------------
1 | c
2 | foobar
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/change-default/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/change-delete-everything/cmds:
--------------------------------------------------------------------------------
1 | 1,$c
2 | .
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/change-delete-everything/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-delete-everything/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/change-insert-more-lines/cmds:
--------------------------------------------------------------------------------
1 | c
2 | foo
3 | bar
4 | .
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/change-insert-more-lines/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-insert-more-lines/testdata/input-file:
--------------------------------------------------------------------------------
1 | 123
2 |
--------------------------------------------------------------------------------
/tests/integration/change-line-update/cmds:
--------------------------------------------------------------------------------
1 | 3,c
2 | 3
3 | .
4 | a
5 | 4
6 | .
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/change-line-update/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-line-update/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 9
4 | 5
5 |
--------------------------------------------------------------------------------
/tests/integration/change-no-input/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 1,3c
3 | .
4 | a
5 | end
6 | .
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/change-no-input/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/change-no-input/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/command-mode-eof-modified/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foobar
3 | .
4 |
--------------------------------------------------------------------------------
/tests/integration/command-mode-eof/cmds:
--------------------------------------------------------------------------------
1 | a
2 | .
3 |
--------------------------------------------------------------------------------
/tests/integration/confirm-quit-when-no-tty/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | .
4 | q
5 | .=
6 |
--------------------------------------------------------------------------------
/tests/integration/confirm-quit-when-no-tty/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/confirm-quit-when-no-tty/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-end/cmds:
--------------------------------------------------------------------------------
1 | 1,1t$
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-end/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-end/testdata/input-file:
--------------------------------------------------------------------------------
1 | ---
2 | 1
3 | 2
4 | 3
5 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-start/cmds:
--------------------------------------------------------------------------------
1 | $,$t 0
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-start/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/copy-to-start/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | ---
5 |
--------------------------------------------------------------------------------
/tests/integration/copy-with-offset/cmds:
--------------------------------------------------------------------------------
1 | 1,1t/2/+1
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/copy-with-offset/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/copy-with-offset/testdata/input-file:
--------------------------------------------------------------------------------
1 | ---
2 | 1
3 | 2
4 | +++
5 | 3
6 |
--------------------------------------------------------------------------------
/tests/integration/delete-and-append/cmds:
--------------------------------------------------------------------------------
1 | 1,2d
2 | a
3 | foo
4 | bar
5 | .
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/delete-and-append/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-and-append/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 |
--------------------------------------------------------------------------------
/tests/integration/delete-entire-buffer/cmds:
--------------------------------------------------------------------------------
1 | d
2 | a
3 | foobar
4 | .
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/delete-entire-buffer/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-entire-buffer/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-last-line/cmds:
--------------------------------------------------------------------------------
1 | 3,3d
2 | a
3 | -
4 | .
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/delete-last-line/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-last-line/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/delete-partial/cmds:
--------------------------------------------------------------------------------
1 | 1,2d
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/delete-partial/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-partial/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 |
--------------------------------------------------------------------------------
/tests/integration/delete-single-addr/cmds:
--------------------------------------------------------------------------------
1 | 2d
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/delete-single-addr/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/delete-single-addr/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/discard-first-addr/cmds:
--------------------------------------------------------------------------------
1 | 1;/stdout/
2 |
--------------------------------------------------------------------------------
/tests/integration/discard-first-addr/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/discard-first-addr/testdata/input-file:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE LambdaCase #-}
2 | import System.IO (hFlush, hPutStrLn, stdout)
3 |
--------------------------------------------------------------------------------
/tests/integration/edit-confirm/cmds:
--------------------------------------------------------------------------------
1 | a
2 | fooanerdinaerwrtine iaredn daeur
3 | .
4 | e testdata/second
5 |
--------------------------------------------------------------------------------
/tests/integration/edit-confirm/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-confirm/testdata/first:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/edit-confirm/testdata/second:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-custom-file/cmds:
--------------------------------------------------------------------------------
1 | E testdata/second
2 | 1,$p
3 |
--------------------------------------------------------------------------------
/tests/integration/edit-custom-file/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-custom-file/testdata/first:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/edit-custom-file/testdata/second:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-default/cmds:
--------------------------------------------------------------------------------
1 | E testdata/input-file
2 | E
3 |
--------------------------------------------------------------------------------
/tests/integration/edit-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/edit-marks-discarded/cmds:
--------------------------------------------------------------------------------
1 | ka
2 | 'a,'ap
3 | E testdata/second
4 | 'ap
5 |
--------------------------------------------------------------------------------
/tests/integration/edit-marks-discarded/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-marks-discarded/testdata/first:
--------------------------------------------------------------------------------
1 | foobar
2 | barfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/edit-marks-discarded/testdata/second:
--------------------------------------------------------------------------------
1 | first line
2 | second line
3 |
--------------------------------------------------------------------------------
/tests/integration/edit-twice/cmds:
--------------------------------------------------------------------------------
1 | e testdata/first
2 | a
3 | first edit
4 | .
5 | w
6 | e testdata/second
7 | a
8 | second edit
9 | .
10 | w
11 |
--------------------------------------------------------------------------------
/tests/integration/edit-twice/testdata/first:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/edit-twice/testdata/second:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-unset-modified/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | .
4 | E testdata/second
5 | q
6 |
--------------------------------------------------------------------------------
/tests/integration/edit-unset-modified/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-unset-modified/testdata/first:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-unset-modified/testdata/second:
--------------------------------------------------------------------------------
1 | bar
2 |
--------------------------------------------------------------------------------
/tests/integration/edit-with-command/cmds:
--------------------------------------------------------------------------------
1 | e !printf "foo\nbar\nfoobar\n"
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-line-unchanged/cmds:
--------------------------------------------------------------------------------
1 | a
2 | 4
3 | .
4 | f testdata/second
5 | a
6 | 6
7 | .
8 | w
9 |
--------------------------------------------------------------------------------
/tests/integration/filename-line-unchanged/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-line-unchanged/testdata/first:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/filename-line-unchanged/testdata/second:
--------------------------------------------------------------------------------
1 | 5
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-new-file/cmds:
--------------------------------------------------------------------------------
1 | f testdata/second
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-new-file/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-new-file/testdata/first:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/filename-new-file/testdata/second:
--------------------------------------------------------------------------------
1 | .
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-same-file/cmds:
--------------------------------------------------------------------------------
1 | f
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-same-file/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-same-file/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-shell-command/cmds:
--------------------------------------------------------------------------------
1 | f !echo foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-silent/cmds:
--------------------------------------------------------------------------------
1 | f testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-silent/opts:
--------------------------------------------------------------------------------
1 | -s
2 |
--------------------------------------------------------------------------------
/tests/integration/filename-silent/testdata/input-file:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/filename-silent/testdata/input-file
--------------------------------------------------------------------------------
/tests/integration/forward-backward-current-matches/cmds:
--------------------------------------------------------------------------------
1 | 2p
2 | /matches/p
3 | 2p
4 | ?matches?p
5 |
--------------------------------------------------------------------------------
/tests/integration/forward-backward-current-matches/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/forward-backward-current-matches/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:no match
2 | 2:this line matches
3 | 3:this line matches too
4 |
--------------------------------------------------------------------------------
/tests/integration/global-append-omit-terminator/cmds:
--------------------------------------------------------------------------------
1 | g/foo/a\
2 | this line was inserted
3 | .=
4 | g/foo/a\
5 | also inserted this line\
6 | and this one too
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/global-append-omit-terminator/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-append-omit-terminator/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/global-append/cmds:
--------------------------------------------------------------------------------
1 | g/foo/a\
2 | append1 \
3 | append2 \
4 | .
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/global-append/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-append/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 | 3:foo
4 |
--------------------------------------------------------------------------------
/tests/integration/global-change/cmds:
--------------------------------------------------------------------------------
1 | g/foo/c\
2 | change1 \
3 | change2 \
4 | .
5 | .=
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/global-change/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-change/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 | 3:foobar
4 |
--------------------------------------------------------------------------------
/tests/integration/global-delete-everything/cmds:
--------------------------------------------------------------------------------
1 | g/foo/1,$d
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/global-delete-everything/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-delete-everything/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 | 3:foobar
4 |
--------------------------------------------------------------------------------
/tests/integration/global-delim/cmds:
--------------------------------------------------------------------------------
1 | 1,$g|foo|p
2 |
--------------------------------------------------------------------------------
/tests/integration/global-delim/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-delim/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:test
2 | 2:foo
3 | 3:test
4 | 4:foobar
5 | 5:blaba foo blabla
6 |
--------------------------------------------------------------------------------
/tests/integration/global-delimiter-omitted-substitute/cmds:
--------------------------------------------------------------------------------
1 | g/x/s/x/y
2 |
--------------------------------------------------------------------------------
/tests/integration/global-delimiter-omitted-substitute/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-delimiter-omitted-substitute/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bxx
3 |
--------------------------------------------------------------------------------
/tests/integration/global-empty/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 1,$g/foo/
3 |
--------------------------------------------------------------------------------
/tests/integration/global-empty/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-empty/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:test
2 | 2:foo
3 |
--------------------------------------------------------------------------------
/tests/integration/global-esc-delim/cmds:
--------------------------------------------------------------------------------
1 | 1,$g/f\//p
2 |
--------------------------------------------------------------------------------
/tests/integration/global-esc-delim/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-esc-delim/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:f//
2 | 2:foo
3 | 3:f/
4 |
--------------------------------------------------------------------------------
/tests/integration/global-insert/cmds:
--------------------------------------------------------------------------------
1 | g/foo/i\
2 | insert1 \
3 | insert2 \
4 | .
5 | .=
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/global-insert/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-insert/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 | 3:foobar
4 |
--------------------------------------------------------------------------------
/tests/integration/global-multiline/cmds:
--------------------------------------------------------------------------------
1 | H
2 | g|foo|d\
3 | 1s/^/test/\
4 | p
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/global-multiline/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-multiline/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foobar
2 | 2:bar
3 | 3:baz
4 |
--------------------------------------------------------------------------------
/tests/integration/global-multiple-commands/cmds:
--------------------------------------------------------------------------------
1 | g/foo/c\
2 | change1\
3 | . \
4 | a\
5 | append1\
6 | .\
7 | 1d
8 | .=
9 | w
10 |
--------------------------------------------------------------------------------
/tests/integration/global-multiple-commands/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-multiple-commands/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 | 3:foobar
4 |
--------------------------------------------------------------------------------
/tests/integration/global-no-match/cmds:
--------------------------------------------------------------------------------
1 | .=
2 | /foo/g
3 | .=
4 |
--------------------------------------------------------------------------------
/tests/integration/global-no-match/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-no-match/testdata/input-file:
--------------------------------------------------------------------------------
1 | bar
2 | baz
3 | 123
4 |
--------------------------------------------------------------------------------
/tests/integration/global-no-terminating-dot/cmds:
--------------------------------------------------------------------------------
1 | g/foobar/a\
2 | no\
3 | terminating\
4 | period\
5 | character\
6 | .
7 | .=
8 | w
9 |
--------------------------------------------------------------------------------
/tests/integration/global-no-terminating-dot/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-no-terminating-dot/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/global-non-matched/cmds:
--------------------------------------------------------------------------------
1 | v/foo/
2 | .=
3 | v/foo/p
4 | .=
5 | v/foo/s|^[a-z]*|foo|
6 | .=
7 | v/foo/p
8 | .=
9 | 1,$p
10 | Q
11 |
--------------------------------------------------------------------------------
/tests/integration/global-non-matched/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-non-matched/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/global-null-re/cmds:
--------------------------------------------------------------------------------
1 | 1,$g/foo/p
2 | 1,$g//p
3 | .=
4 |
--------------------------------------------------------------------------------
/tests/integration/global-null-re/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-null-re/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:test
2 | 2:foo
3 | 3:test
4 |
--------------------------------------------------------------------------------
/tests/integration/global-print/cmds:
--------------------------------------------------------------------------------
1 | 1,$g/foo/p
2 | .=
3 |
--------------------------------------------------------------------------------
/tests/integration/global-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:test
2 | 2:foo
3 | 3:test
4 | 4:foobar
5 | 5:blaba foo blabla
6 |
--------------------------------------------------------------------------------
/tests/integration/global-regex-syntax-error/cmds:
--------------------------------------------------------------------------------
1 | g/[/p
2 |
--------------------------------------------------------------------------------
/tests/integration/global-regex-syntax-error/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-regex-syntax-error/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch1/cmds:
--------------------------------------------------------------------------------
1 | g/baz/p\
2 | s/baz/replaced/
3 | .=
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch1/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch1/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch2/cmds:
--------------------------------------------------------------------------------
1 | g/baz/p\
2 | s/doesn't match any line/replaced/
3 | .=
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch2/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/global-substitute-nomatch2/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/input-mode-eof/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | bar
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/insert-before/cmds:
--------------------------------------------------------------------------------
1 | 2i
2 | bla
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/insert-before/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/insert-before/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/insert-zero/cmds:
--------------------------------------------------------------------------------
1 | 0 i
2 | 123
3 | .
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/insert-zero/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/insert-zero/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/interactive-nested-global/cmds:
--------------------------------------------------------------------------------
1 | G/foo/
2 | g/foo/
3 |
--------------------------------------------------------------------------------
/tests/integration/interactive-nested-global/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-nested-global/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/interactive-no-previous/cmds:
--------------------------------------------------------------------------------
1 | G/foo/
2 | &
3 |
--------------------------------------------------------------------------------
/tests/integration/interactive-no-previous/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-no-previous/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-command/cmds:
--------------------------------------------------------------------------------
1 | H
2 | G/foo/
3 | s/foo/test1/
4 |
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-command/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-command/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | bar
3 | foobar2
4 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-repeat/cmds:
--------------------------------------------------------------------------------
1 | G/foo/
2 | s/foo/test/
3 |
4 | &
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-repeat/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-null-repeat/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | bar1
3 | foo2
4 | bar2
5 | foo3
6 |
--------------------------------------------------------------------------------
/tests/integration/interactive-previous/cmds:
--------------------------------------------------------------------------------
1 | G/foo/
2 | d
3 | &
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/interactive-previous/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-previous/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | bar
3 | foobar2
4 |
--------------------------------------------------------------------------------
/tests/integration/interactive-repeat/cmds:
--------------------------------------------------------------------------------
1 | G/^f/
2 | s/foo/test/
3 | &
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/interactive-repeat/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-repeat/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | 1234
3 | foo2
4 |
--------------------------------------------------------------------------------
/tests/integration/interactive-unmatched/cmds:
--------------------------------------------------------------------------------
1 | H
2 | V/foo/
3 | d
4 |
5 | &
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/interactive-unmatched/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive-unmatched/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | bar
3 | 123
4 | foobar2
5 | 456
6 |
--------------------------------------------------------------------------------
/tests/integration/interactive/cmds:
--------------------------------------------------------------------------------
1 | H
2 | G/foo/
3 | s/foo/test1/
4 | s/foo/test2/
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/interactive/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/interactive/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo1
2 | bar
3 | foobar2
4 |
--------------------------------------------------------------------------------
/tests/integration/invalid-range/cmds:
--------------------------------------------------------------------------------
1 | 3,1p
2 |
--------------------------------------------------------------------------------
/tests/integration/invalid-range/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/invalid-range/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/join-all/cmds:
--------------------------------------------------------------------------------
1 | 1,$j
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/join-all/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/join-all/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/join-lines/cmds:
--------------------------------------------------------------------------------
1 | 2,3j
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/join-lines/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/join-lines/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 |
--------------------------------------------------------------------------------
/tests/integration/join-nothing/cmds:
--------------------------------------------------------------------------------
1 | 1,1j
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/join-nothing/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/join-nothing/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | >>>
4 | <<<
5 |
--------------------------------------------------------------------------------
/tests/integration/line-number-default/cmds:
--------------------------------------------------------------------------------
1 | H
2 | =
3 | 2,3c
4 | .
5 | =
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/line-number-default/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/line-number-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/line-number-empty/cmds:
--------------------------------------------------------------------------------
1 | =
2 |
--------------------------------------------------------------------------------
/tests/integration/line-number-empty/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/line-number-empty/testdata/input-file:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/line-number-empty/testdata/input-file
--------------------------------------------------------------------------------
/tests/integration/line-number-zero/cmds:
--------------------------------------------------------------------------------
1 | =
2 |
--------------------------------------------------------------------------------
/tests/integration/list-backslash/cmds:
--------------------------------------------------------------------------------
1 | 1,$l
2 |
--------------------------------------------------------------------------------
/tests/integration/list-backslash/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/list-backslash/testdata/input-file:
--------------------------------------------------------------------------------
1 | b\ar$f\oo\
2 |
--------------------------------------------------------------------------------
/tests/integration/list-multiple-lines/cmds:
--------------------------------------------------------------------------------
1 | 1,$l
2 |
--------------------------------------------------------------------------------
/tests/integration/list-multiple-lines/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/list-multiple-lines/testdata/input-file:
--------------------------------------------------------------------------------
1 | ιoι
2 | bσr
3 |
--------------------------------------------------------------------------------
/tests/integration/list-pad-with-zeros/cmds:
--------------------------------------------------------------------------------
1 | 1,$l
2 |
--------------------------------------------------------------------------------
/tests/integration/list-pad-with-zeros/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/list-pad-with-zeros/testdata/input-file:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/integration/list-unicode/cmds:
--------------------------------------------------------------------------------
1 | 1,$l
2 |
--------------------------------------------------------------------------------
/tests/integration/list-unicode/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/list-unicode/testdata/input-file:
--------------------------------------------------------------------------------
1 | λ
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-delete/cmds:
--------------------------------------------------------------------------------
1 | 2kx
2 | 'xp
3 | 'xd
4 | 'xp
5 | Q
6 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-delete/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-delete/testdata/input-file:
--------------------------------------------------------------------------------
1 | first line
2 | second line
3 | third line
4 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-move/cmds:
--------------------------------------------------------------------------------
1 | 2kx
2 | 'xp
3 | 2m$
4 | 'xp
5 | Q
6 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-move/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-and-move/testdata/input-file:
--------------------------------------------------------------------------------
1 | first line
2 | second line
3 | third line
4 |
--------------------------------------------------------------------------------
/tests/integration/mark-empty-buffer/cmds:
--------------------------------------------------------------------------------
1 | 2kx
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-first-line/cmds:
--------------------------------------------------------------------------------
1 | H
2 | =
3 | a
4 | 5
5 | 6
6 | .
7 | 1kf
8 | 'fi
9 | 1
10 | .
11 | w
12 |
--------------------------------------------------------------------------------
/tests/integration/mark-first-line/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-first-line/testdata/input-file:
--------------------------------------------------------------------------------
1 | 2
2 | 3
3 | 4
4 | 5
5 | 6
6 | 5
7 | 6
8 |
--------------------------------------------------------------------------------
/tests/integration/mark-invalid/cmds:
--------------------------------------------------------------------------------
1 | 1kfoobar
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-invalid/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-invalid/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/mark-overwrite/cmds:
--------------------------------------------------------------------------------
1 | =
2 | a
3 | 4
4 | 5
5 | 6
6 | .
7 | 1kf
8 | $kf
9 | a
10 | 7
11 | 8
12 | 9
13 | .
14 | w
15 |
--------------------------------------------------------------------------------
/tests/integration/mark-overwrite/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/mark-overwrite/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/mark-zero-line/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | bar
4 | baz
5 | .
6 | 0kf
7 |
--------------------------------------------------------------------------------
/tests/integration/move-after/cmds:
--------------------------------------------------------------------------------
1 | 2,3m5
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/move-after/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-after/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 | test
5 | ---
6 |
7 | bla
8 |
--------------------------------------------------------------------------------
/tests/integration/move-between/cmds:
--------------------------------------------------------------------------------
1 | 5,6m2
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/move-between/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-between/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 5
4 | 6
5 | 3
6 | 4
7 | 7
8 | 8
9 |
--------------------------------------------------------------------------------
/tests/integration/move-overlapping-range/cmds:
--------------------------------------------------------------------------------
1 | 1,3m2
2 | 1,2m2
3 |
--------------------------------------------------------------------------------
/tests/integration/move-overlapping-range/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-overlapping-range/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/move-to-end/cmds:
--------------------------------------------------------------------------------
1 | 1,1m3
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/move-to-end/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-to-end/testdata/input-file:
--------------------------------------------------------------------------------
1 | 3
2 | 1
3 | 2
4 |
--------------------------------------------------------------------------------
/tests/integration/move-to-start/cmds:
--------------------------------------------------------------------------------
1 | 2,$m0
2 | .=
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/move-to-start/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-to-start/testdata/input-file:
--------------------------------------------------------------------------------
1 | 3
2 | 1
3 | 2
4 |
--------------------------------------------------------------------------------
/tests/integration/move-update-current-on-single-line/cmds:
--------------------------------------------------------------------------------
1 | 2m3
2 | .=
3 | Q
4 |
--------------------------------------------------------------------------------
/tests/integration/move-update-current-on-single-line/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/move-update-current-on-single-line/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 | bla
5 | blubb
6 |
--------------------------------------------------------------------------------
/tests/integration/multiple-addresses/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 7,p
3 | 7,5,p
4 | 7,5,9p
5 | 7,9p
6 | 7,+p
7 | ,p
8 | ,7p
9 | ,,p
10 | ,;p
11 | 7;p
12 | 7;5;p
13 | 7;5;9p
14 | 7;5,9p
15 | 7;9p
16 | 7;+p
17 | ;p
18 | 1p
19 | ;7p
20 | ;;p
21 | ;,p
22 |
--------------------------------------------------------------------------------
/tests/integration/multiple-addresses/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/multiple-addresses/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 | 6
7 | 7
8 | 8
9 | 9
10 | 10
11 | 11
12 | 12
13 | 13
14 | 14
15 | 15
16 | 16
17 | 17
18 | 18
19 | 19
20 | 20
21 |
--------------------------------------------------------------------------------
/tests/integration/no-null-re/cmds:
--------------------------------------------------------------------------------
1 | //p
2 |
--------------------------------------------------------------------------------
/tests/integration/no-null-re/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/no-null-re/testdata/input-file:
--------------------------------------------------------------------------------
1 | 123
2 | foobar
3 | 234
4 |
--------------------------------------------------------------------------------
/tests/integration/nonexistend-file-read/cmds:
--------------------------------------------------------------------------------
1 | e testdata/does/not/exist
2 |
--------------------------------------------------------------------------------
/tests/integration/nonexistend-file-write/cmds:
--------------------------------------------------------------------------------
1 | a
2 | write should error and therefore quit should require confirmation
3 | .
4 | w /tmp/does/not/exist
5 | q
6 | Q
7 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-address/cmds:
--------------------------------------------------------------------------------
1 | 4
2 | .=
3 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-address/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-address/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-zero-address/cmds:
--------------------------------------------------------------------------------
1 | 0
2 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-zero-address/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/null-command-with-zero-address/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 |
--------------------------------------------------------------------------------
/tests/integration/null-command/cmds:
--------------------------------------------------------------------------------
1 | 1,1p
2 |
3 |
4 | .=
5 |
--------------------------------------------------------------------------------
/tests/integration/null-command/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/null-command/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 |
--------------------------------------------------------------------------------
/tests/integration/null-re-range/cmds:
--------------------------------------------------------------------------------
1 | /main/-1,/main/+1p
2 | g//p
3 | 1,$s//program/g
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/null-re-range/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/null-re-range/testdata/input-file:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | void
4 | main_loop(void)
5 | {
6 | /* … */
7 | }
8 |
9 | int
10 | main(void)
11 | {
12 | puts("Hello, World");
13 | return 0;
14 | }
15 |
--------------------------------------------------------------------------------
/tests/integration/null-re/cmds:
--------------------------------------------------------------------------------
1 | /foo/p
2 | //p
3 | +1p
4 | //p
5 | +1p
6 | ??p
7 |
--------------------------------------------------------------------------------
/tests/integration/null-re/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/null-re/testdata/input-file:
--------------------------------------------------------------------------------
1 | 123
2 | foobar
3 | 234
4 |
--------------------------------------------------------------------------------
/tests/integration/number-change-line/cmds:
--------------------------------------------------------------------------------
1 | 2,3n
2 | .=
3 |
--------------------------------------------------------------------------------
/tests/integration/number-change-line/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/number-change-line/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/number-default/cmds:
--------------------------------------------------------------------------------
1 | n
2 |
--------------------------------------------------------------------------------
/tests/integration/number-default/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/number-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/number-full/cmds:
--------------------------------------------------------------------------------
1 | 1,$n
2 |
--------------------------------------------------------------------------------
/tests/integration/number-full/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/number-full/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/number-partial/cmds:
--------------------------------------------------------------------------------
1 | 2,3n
2 |
--------------------------------------------------------------------------------
/tests/integration/number-partial/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/number-partial/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/omitting-re-delimiter/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test
2 | g/bar
3 | v/bar
4 | ?test
5 | /baz
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/omitting-re-delimiter/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/omitting-re-delimiter/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/pass-shell-command-as-cmdarg/cmds:
--------------------------------------------------------------------------------
1 | 1,$p
2 |
--------------------------------------------------------------------------------
/tests/integration/pass-shell-command-as-cmdarg/opts:
--------------------------------------------------------------------------------
1 | !uname|head
2 |
--------------------------------------------------------------------------------
/tests/integration/prefix-print-with-print/cmds:
--------------------------------------------------------------------------------
1 | 1,$ll
2 | 1,$nn
3 | 1,$pp
4 |
--------------------------------------------------------------------------------
/tests/integration/prefix-print-with-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/prefix-print-with-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward-multiple-matches/cmds:
--------------------------------------------------------------------------------
1 | 3p
2 | ?^foobar$?p
3 | .=
4 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward-multiple-matches/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward-multiple-matches/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 | $
3 | current-line
4 | $
5 | foobar
6 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward/cmds:
--------------------------------------------------------------------------------
1 | H
2 | ?foobar?p
3 | .=
4 | ?foobar?p
5 | .=
6 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-match-backward/testdata/input-file:
--------------------------------------------------------------------------------
1 | this is a testfile
2 |
3 | this line contains foobar
4 | this line contains blaoo
5 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-no-match/cmds:
--------------------------------------------------------------------------------
1 | /no match/p
2 | .=
3 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-no-match/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-no-match/testdata/input-file:
--------------------------------------------------------------------------------
1 | this is a testfile
2 |
3 | this line contains foobar
4 | this line contains blaoo
5 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-wraparound/cmds:
--------------------------------------------------------------------------------
1 | /foobar/p
2 | /te[a-z][a-z]*/p
3 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-wraparound/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward-wraparound/testdata/input-file:
--------------------------------------------------------------------------------
1 | this is a testfile
2 |
3 | this line contains foobar
4 | this line contains blaoo
5 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward/cmds:
--------------------------------------------------------------------------------
1 | /foobar/p
2 | .=
3 | /foobar/p
4 | .=
5 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-match-forward/testdata/input-file:
--------------------------------------------------------------------------------
1 | this is a testfile
2 |
3 | this line contains foobar
4 | this line contains blaoo
5 |
--------------------------------------------------------------------------------
/tests/integration/print-single/cmds:
--------------------------------------------------------------------------------
1 | 2p
2 | .=
3 | Q
4 |
--------------------------------------------------------------------------------
/tests/integration/print-single/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print-single/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/print/cmds:
--------------------------------------------------------------------------------
1 | 2,3p
2 | .=
3 |
--------------------------------------------------------------------------------
/tests/integration/print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/print/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/quit-address/cmds:
--------------------------------------------------------------------------------
1 | 2q
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-address/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-address/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/quit-confirmed/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foobar
3 | .
4 | q
5 | q
6 | .=
7 |
--------------------------------------------------------------------------------
/tests/integration/quit-confirmed/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-confirmed/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-file-modified/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foobar
3 | .
4 | q
5 |
--------------------------------------------------------------------------------
/tests/integration/quit-file-modified/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-file-modified/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-no-file/cmds:
--------------------------------------------------------------------------------
1 | q
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-no-file/opts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/quit-no-file/opts
--------------------------------------------------------------------------------
/tests/integration/quit-not-modified/cmds:
--------------------------------------------------------------------------------
1 | q
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-not-modified/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/quit-not-modified/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | bla
4 | baz
5 |
--------------------------------------------------------------------------------
/tests/integration/quit-without-checking/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | .
4 | Q
5 |
--------------------------------------------------------------------------------
/tests/integration/read-command-empty/cmds:
--------------------------------------------------------------------------------
1 | r !true
2 |
--------------------------------------------------------------------------------
/tests/integration/read-command-twice/cmds:
--------------------------------------------------------------------------------
1 | r !printf "foo\n12345\n"
2 | r !echo "test test test"
3 | Q
4 |
--------------------------------------------------------------------------------
/tests/integration/read-dont-remember-command/cmds:
--------------------------------------------------------------------------------
1 | read !printf "λ\nfoo\nbar\nbaz\nλ\n"
2 | f
3 |
--------------------------------------------------------------------------------
/tests/integration/read-from-command/cmds:
--------------------------------------------------------------------------------
1 | read !printf "λ\nfoo\nbar\nbaz\nλ\n"
2 | 1,$p
3 |
--------------------------------------------------------------------------------
/tests/integration/read-no-space/cmds:
--------------------------------------------------------------------------------
1 | rtestdata/in
2 |
--------------------------------------------------------------------------------
/tests/integration/read-no-space/testdata/in:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/read-set-default/cmds:
--------------------------------------------------------------------------------
1 | r testdata/input-file
2 | $a
3 | foobar
4 | .
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/read-set-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/read-twice/cmds:
--------------------------------------------------------------------------------
1 | r testdata/in
2 | r testdata/in
3 | w out
4 |
--------------------------------------------------------------------------------
/tests/integration/read-twice/testdata/in:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/read-write-no-file/cmds:
--------------------------------------------------------------------------------
1 | r
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/read-write-no-file/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/read-write-no-file/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/regex-empty-file/cmds:
--------------------------------------------------------------------------------
1 | /foo/p
2 |
--------------------------------------------------------------------------------
/tests/integration/regex-empty-file/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/regex-empty-file/testdata/input-file:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/regex-empty-file/testdata/input-file
--------------------------------------------------------------------------------
/tests/integration/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 |
5 | abort() {
6 | printf "${1}\n" 1>&2
7 | exit 1
8 | }
9 |
10 | run_editor() {
11 | [ $# -eq 4 ] || exit 1
12 | cmd="${1}"
13 | cwd="${2}"
14 | dat="${3}"
15 | opt="${4}"
16 |
17 | mkdir "${cwd}"
18 | [ -d "${dat}" ] && cp -r "${dat}" "${cwd}"
19 | cd "${cwd}"
20 |
21 | if [ -s "${opt}" ]; then
22 | set -- $(cat "${opt}")
23 | "${cmd}" $@ 2>/dev/null
24 | else
25 | "${cmd}" 2>/dev/null
26 | fi
27 |
28 | cd - >/dev/null
29 | unset cmd cwd dat opt
30 | }
31 |
32 | EDWARD="${EDWARD:-$(pwd)/../../bin/edward}"
33 | [ -x "${EDWARD}" ] || \
34 | abort "Couldn't find edward executable '${EDWARD}'."
35 |
36 | REF_IMPL="$(command -v ed)"
37 | [ -x "${REF_IMPL}" ] || \
38 | abort "Reference implementation not found."
39 |
40 | TESTDIR="/tmp/edward-test"
41 | TESTCWD="${TESTDIR}/cwd"
42 | EXPECTED="${TESTDIR}/expected"
43 | ACTUAL="${TESTDIR}/actual"
44 |
45 | mkdir -p "${TESTDIR}"
46 | trap "rm -rf '${TESTDIR}'" INT EXIT
47 |
48 | for test in *; do
49 | [ -d "${test}" ] || continue
50 |
51 | name="${test##*/}"
52 | printf "Running test case '%s': " "${name}"
53 |
54 | cmds="$(pwd)/${test}/cmds"
55 | opts="$(pwd)/${test}/opts"
56 |
57 | run_editor "${REF_IMPL}" "${TESTCWD}.expected" "${test}/testdata" "${opts}" \
58 | > "${EXPECTED}" < "${cmds}"
59 |
60 | run_editor "${EDWARD}" "${TESTCWD}.actual" "${test}/testdata" "${opts}" \
61 | > "${ACTUAL}" < "${cmds}"
62 |
63 | diff=$(diff -ur "${TESTCWD}.expected" "${TESTCWD}.actual")
64 | if [ $? -ne 0 ]; then
65 | printf "FAIL: Modified files differ.\n\n"
66 | printf "%s\n" "${diff}"
67 | exit 1
68 | fi
69 |
70 | diff=$(diff -u "${EXPECTED}" "${ACTUAL}")
71 | if [ $? -ne 0 ]; then
72 | printf "FAIL: Standard output didn't match.\n\n"
73 | printf "%s\n" "${diff}"
74 | exit 1
75 | fi
76 |
77 | printf "OK.\n"
78 | rm -rf "${TESTCWD}.actual" "${TESTCWD}.expected"
79 | done
80 |
--------------------------------------------------------------------------------
/tests/integration/shell-escape-filename/cmds:
--------------------------------------------------------------------------------
1 | !echo foo \% bar
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename-multiple/cmds:
--------------------------------------------------------------------------------
1 | !echo current filename is %
2 | e testdata/second-file
3 | !echo filename is % and % still
4 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename-multiple/opts:
--------------------------------------------------------------------------------
1 | testdata/first-file
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename-multiple/testdata/first-file:
--------------------------------------------------------------------------------
1 | some text
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename-multiple/testdata/second-file:
--------------------------------------------------------------------------------
1 | this is the second file
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename/cmds:
--------------------------------------------------------------------------------
1 | !echo filename: %
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-filename/testdata/input-file:
--------------------------------------------------------------------------------
1 | some text
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-no-filename/cmds:
--------------------------------------------------------------------------------
1 | !echo %
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-no-previous/cmds:
--------------------------------------------------------------------------------
1 | !!
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-previous-append/cmds:
--------------------------------------------------------------------------------
1 | !echo foo bar baz
2 | !! and the filename is %
3 |
--------------------------------------------------------------------------------
/tests/integration/shell-previous-append/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-previous-append/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/shell-previous-with-filename/cmds:
--------------------------------------------------------------------------------
1 | !echo \%\% filename = % \%\%
2 | !!
3 |
--------------------------------------------------------------------------------
/tests/integration/shell-previous/cmds:
--------------------------------------------------------------------------------
1 | !printf "1\n2\n3\n"
2 | !!
3 |
--------------------------------------------------------------------------------
/tests/integration/silent-mode/cmds:
--------------------------------------------------------------------------------
1 | E testdata/first-file
2 | a
3 | foo
4 | .
5 | w
6 | e testdata/second-file
7 | r testdata/first-file
8 | w
9 | !echo %
10 |
--------------------------------------------------------------------------------
/tests/integration/silent-mode/opts:
--------------------------------------------------------------------------------
1 | -s
2 |
--------------------------------------------------------------------------------
/tests/integration/silent-mode/testdata/first-file:
--------------------------------------------------------------------------------
1 | first
2 |
--------------------------------------------------------------------------------
/tests/integration/silent-mode/testdata/second-file:
--------------------------------------------------------------------------------
1 | second
2 |
--------------------------------------------------------------------------------
/tests/integration/special-addresses/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 1p
3 | +++
4 | /foo/-
5 | -2
6 | 3 ---- 2
7 | 1 2 3
8 |
--------------------------------------------------------------------------------
/tests/integration/special-addresses/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/special-addresses/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:bar
2 | 2:blbababab
3 | 3:bazbababa
4 | 4:foo
5 | 5:testtesttest
6 | 6:rienradenrunaedt
7 | 7:duarenduane
8 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-number/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test/gn
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-number/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-number/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foobarfoo
2 | 2:
3 | 3:foobarfoo
4 | 4:
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-print/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test/gp
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-and-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foobarfoo
2 | 2:foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-append/cmds:
--------------------------------------------------------------------------------
1 | H
2 | s/foo/&bar/
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-append/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-append/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-backreference/cmds:
--------------------------------------------------------------------------------
1 | H
2 | s/\([a-z]\)oo/\1ar/
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-backreference/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-backreference/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-change-line/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test/
2 | .=
3 | Q
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-change-line/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-change-line/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | 123
3 | foobarfoo
4 | 345
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter-escaped/cmds:
--------------------------------------------------------------------------------
1 | 1|foo/bar|123\|345|
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter-escaped/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter-escaped/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo/bar
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter/cmds:
--------------------------------------------------------------------------------
1 | 1|foo/bar|123/345|
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-delimiter/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo/bar
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-differ-matched-twice/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/T[a-z]*/T.&/g
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-differ-matched-twice/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-differ-matched-twice/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo : Text -> Testing
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-replace/cmds:
--------------------------------------------------------------------------------
1 | 2s/bar//
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-replace/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-replace/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-submatch/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/[a-z ][a-z ]* '\(.*\)'.*/matched: '\1'/
2 | 1,$p
3 | Q
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-submatch/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-empty-submatch/testdata/input-file:
--------------------------------------------------------------------------------
1 | first example text 'see figure 1'
2 | second example text ''
3 | third example text '' foo bar
4 | last example text 'something' blabab
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-first/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test/
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-first/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-first/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-global/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/test/g
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-global/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-global/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-insert-multiple-newlines/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/]*>\([^<][^<]*\)<\/h2>$/\
2 | === \1\
3 | \
4 |
5 | w
6 | q
7 |
--------------------------------------------------------------------------------
/tests/integration/substitute-insert-multiple-newlines/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-insert-multiple-newlines/testdata/input-file:
--------------------------------------------------------------------------------
1 | Status
2 | This SRFI is currently in final status.
3 | Abstract
4 | A flexvector, also known as a dynamic array or an arraylist
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-invalid-backref/cmds:
--------------------------------------------------------------------------------
1 | 1s/foo/\1/
2 | 2s/\(bar\)/\2"\1"\3/
3 | 3s/\(baz\)/'\1'/
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-invalid-backref/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-invalid-backref/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-touched/cmds:
--------------------------------------------------------------------------------
1 | 2kf
2 | 1,$s/bar/the line containing the mark has been modified, the mark is now invalid/
3 | 'fp
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-touched/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-touched/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-untouched/cmds:
--------------------------------------------------------------------------------
1 | 2kf
2 | 1,$s/f/z/
3 | 'fp
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-untouched/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-mark-untouched/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-matched-twice/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/Text/T.&/g
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-matched-twice/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-matched-twice/testdata/input-file:
--------------------------------------------------------------------------------
1 | trim :: T.Text -> T.Text
2 | trim = rtrim . ltrim
3 | where
4 | ltrim :: T.Text -> T.Text
5 | ltrim = T.dropWhile isSpace
6 |
--------------------------------------------------------------------------------
/tests/integration/substitute-missing-pattern/cmds:
--------------------------------------------------------------------------------
1 | s/sample
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-missing-pattern/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-missing-pattern/testdata/input-file:
--------------------------------------------------------------------------------
1 | sample input
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-modified-but-same/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/foo/n
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-modified-but-same/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-modified-but-same/testdata/input-file:
--------------------------------------------------------------------------------
1 | bar
2 | barfootest
3 | foo
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline-print/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/foo\
2 | inserted line/p
3 | .=
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline-print/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline-print/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline/cmds:
--------------------------------------------------------------------------------
1 | s/foo\(.*\)/foo \
2 | \1/
3 | .=
4 | w
5 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-multiline/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-match/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/no match/test/g
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-match/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-match/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-prev-replace/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo/%/g
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-prev-replace/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-no-prev-replace/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-non-participating-submatch/cmds:
--------------------------------------------------------------------------------
1 | s/foo \(..*\)* \(..*\)/\1/
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-non-participating-submatch/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-non-participating-submatch/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo baz
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-null-re/cmds:
--------------------------------------------------------------------------------
1 | /foo/p
2 | s//./
3 | w
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-null-re/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-null-re/testdata/input-file:
--------------------------------------------------------------------------------
1 | 123
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-percent-delim/cmds:
--------------------------------------------------------------------------------
1 | s%foo%%%
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-percent-delim/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-percent-delim/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace-empty/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/foo//
2 | 1,$p
3 | .=
4 | 1,$s/bar/%/
5 | 1,$p
6 | w
7 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace-empty/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace-empty/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo123bar
2 | 2:foo456bar
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 1,$s/foo/test/1
3 | 1,$p
4 | .=
5 | 1,$s/foo/%/g
6 | 1,$p
7 | .=
8 | 1,$s/test/\%/g
9 | 1,$p
10 | .=
11 | Q
12 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-prev-replace/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobarfoo
2 | foobarfoo
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-regex-syntax-error/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foo
3 | bar
4 | baz
5 | .
6 | 1,$s/[//
7 |
--------------------------------------------------------------------------------
/tests/integration/substitute-simple/cmds:
--------------------------------------------------------------------------------
1 | s/foo/bar/
2 | w
3 |
--------------------------------------------------------------------------------
/tests/integration/substitute-simple/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/substitute-simple/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/integration/terminate-after-first-error/cmds:
--------------------------------------------------------------------------------
1 | a
2 | 123
3 | .
4 | W
5 | W
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-append/cmds:
--------------------------------------------------------------------------------
1 | a
2 | baz
3 | .
4 | .=
5 | u
6 | .=
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/undo-append/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-append/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-change/cmds:
--------------------------------------------------------------------------------
1 | 1,2c
2 | insert
3 | three
4 | more lines
5 | .
6 | .=
7 | u
8 | .=
9 | w
10 |
--------------------------------------------------------------------------------
/tests/integration/undo-change/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-change/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-copy/cmds:
--------------------------------------------------------------------------------
1 | 1,2c3
2 | .=
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-copy/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-copy/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | ---
4 |
--------------------------------------------------------------------------------
/tests/integration/undo-delete/cmds:
--------------------------------------------------------------------------------
1 | 4,8d
2 | .=
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-delete/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-delete/testdata/input-file:
--------------------------------------------------------------------------------
1 | fronduuia
2 | e
3 | ae
4 | uae
5 | u
6 | ae
7 | u
8 | ae
9 | oo
10 | bar
11 |
--------------------------------------------------------------------------------
/tests/integration/undo-edit-command/cmds:
--------------------------------------------------------------------------------
1 | 1,$p
2 | .=
3 | a
4 | foo
5 | .
6 | .=
7 | 1,$p
8 | .=
9 | E testdata/second
10 | .=
11 | 1,$p
12 | .=
13 | u
14 |
--------------------------------------------------------------------------------
/tests/integration/undo-edit-command/opts:
--------------------------------------------------------------------------------
1 | testdata/first
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-edit-command/testdata/first:
--------------------------------------------------------------------------------
1 | first
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-edit-command/testdata/second:
--------------------------------------------------------------------------------
1 | second
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-global-non-matched/cmds:
--------------------------------------------------------------------------------
1 | v/foo/a\
2 | append1\
3 | append2\
4 | .\
5 | i\
6 | insert1\
7 | .
8 | .=
9 | 1,$p
10 | u
11 | .=
12 | w
13 |
--------------------------------------------------------------------------------
/tests/integration/undo-global-non-matched/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-global-non-matched/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-global/cmds:
--------------------------------------------------------------------------------
1 | g/^/a\
2 | append1\
3 | append2\
4 | .\
5 | s/[0-9]/2342/
6 | .=
7 | 1,$p
8 | .=
9 | u
10 | .=
11 | 1,$p
12 | u
13 | .=
14 | w
15 |
--------------------------------------------------------------------------------
/tests/integration/undo-global/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-global/testdata/input-file:
--------------------------------------------------------------------------------
1 | 1:foo
2 | 2:bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-insert/cmds:
--------------------------------------------------------------------------------
1 | 2i
2 | newly inserted
3 | .
4 | .=
5 | u
6 | .=
7 | w
8 |
--------------------------------------------------------------------------------
/tests/integration/undo-insert/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-insert/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | 123
4 |
--------------------------------------------------------------------------------
/tests/integration/undo-join/cmds:
--------------------------------------------------------------------------------
1 | 1,$j
2 | .=
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-join/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-join/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-move/cmds:
--------------------------------------------------------------------------------
1 | 2,3m$
2 | .=
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-move/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-move/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | 123
3 | 456
4 | bar
5 |
--------------------------------------------------------------------------------
/tests/integration/undo-nothing/cmds:
--------------------------------------------------------------------------------
1 | .=
2 | 1p
3 | .=
4 | u
5 | .=
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-nothing/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-nothing/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 | foo
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/undo-read/cmds:
--------------------------------------------------------------------------------
1 | r testdata/to-be-read
2 | 1,$p
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-read/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-read/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | ---
4 |
--------------------------------------------------------------------------------
/tests/integration/undo-read/testdata/to-be-read:
--------------------------------------------------------------------------------
1 | this file is read
2 | using the r command.
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-redo/cmds:
--------------------------------------------------------------------------------
1 | i
2 | baz
3 | .
4 | u
5 | .=
6 | 1,$p
7 | u
8 | .=
9 | 1,$p
10 | u
11 | .=
12 | w
13 |
--------------------------------------------------------------------------------
/tests/integration/undo-redo/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-redo/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/undo-substitute/cmds:
--------------------------------------------------------------------------------
1 | 1,$s/bar/lol/p
2 | .=
3 | u
4 | .=
5 | w
6 |
--------------------------------------------------------------------------------
/tests/integration/undo-substitute/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-substitute/testdata/input-file:
--------------------------------------------------------------------------------
1 | foobar
2 | bar
3 | ---
4 |
--------------------------------------------------------------------------------
/tests/integration/undo-undo/cmds:
--------------------------------------------------------------------------------
1 | i
2 | baz
3 | .
4 | .=
5 | 1,$p
6 | .=
7 | u
8 | .=
9 | 1,$p
10 | .=
11 | u
12 | .=
13 | w
14 |
--------------------------------------------------------------------------------
/tests/integration/undo-undo/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/undo-undo/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/write-default-empty/cmds:
--------------------------------------------------------------------------------
1 | w testfile
2 |
--------------------------------------------------------------------------------
/tests/integration/write-default-empty/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/write-default-empty/testdata/input-file:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/write-default-empty/testdata/input-file
--------------------------------------------------------------------------------
/tests/integration/write-default/cmds:
--------------------------------------------------------------------------------
1 | w testfile
2 |
--------------------------------------------------------------------------------
/tests/integration/write-default/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/write-default/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/write-empty-to-command/cmds:
--------------------------------------------------------------------------------
1 | w !wc -l
2 |
--------------------------------------------------------------------------------
/tests/integration/write-no-file/cmds:
--------------------------------------------------------------------------------
1 | w
2 |
--------------------------------------------------------------------------------
/tests/integration/write-partial/cmds:
--------------------------------------------------------------------------------
1 | 1,2w out
2 |
--------------------------------------------------------------------------------
/tests/integration/write-partial/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/write-partial/out:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 |
--------------------------------------------------------------------------------
/tests/integration/write-partial/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/write-to-command-modified/cmds:
--------------------------------------------------------------------------------
1 | a
2 | foobar
3 | .
4 | w !wc -l
5 | q
6 |
--------------------------------------------------------------------------------
/tests/integration/write-to-command-modified/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/write-to-command/cmds:
--------------------------------------------------------------------------------
1 | w !wc -l
2 |
--------------------------------------------------------------------------------
/tests/integration/write-to-command/testdata/input-file:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/integration/write-update-filename-cmd/cmds:
--------------------------------------------------------------------------------
1 | a
2 | 123
3 | .
4 | w !wc -l
5 | f
6 |
--------------------------------------------------------------------------------
/tests/integration/write-update-filename-cmd/testdata/file:
--------------------------------------------------------------------------------
1 | foobarbarfoo
2 |
--------------------------------------------------------------------------------
/tests/integration/write-update-filename/cmds:
--------------------------------------------------------------------------------
1 | w testdata/file
2 | f
3 |
--------------------------------------------------------------------------------
/tests/integration/write-update-filename/testdata/file:
--------------------------------------------------------------------------------
1 | foobarbarfoo
2 |
--------------------------------------------------------------------------------
/tests/integration/zero-address/cmds:
--------------------------------------------------------------------------------
1 | 0a
2 | foo
3 | bar
4 | .
5 | 0r !echo foo
6 | 0i
7 | test
8 | .
9 | w
10 | 0c
11 | change
12 | .
13 |
--------------------------------------------------------------------------------
/tests/integration/zero-address/opts:
--------------------------------------------------------------------------------
1 | testdata/input-file
2 |
--------------------------------------------------------------------------------
/tests/integration/zero-address/testdata/input-file:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nmeum/edward/3d7b0ff9d425a6eb39397eb9cab3df70b83eaab8/tests/integration/zero-address/testdata/input-file
--------------------------------------------------------------------------------
/tests/interactive/README.md:
--------------------------------------------------------------------------------
1 | # Interactive tests
2 |
3 | The test cases in this directory covers behavior which requires standard input to be a tty.
4 | For example, EOF in input mode or command mode.
5 | The tests require `tmux` to be installed.
6 | Contrary to the default integration tests, these tests require an `expected` output file.
7 |
--------------------------------------------------------------------------------
/tests/interactive/eof-confirm-with-quit/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | .
5 | 1,$p
6 | C-d \
7 | q
8 |
--------------------------------------------------------------------------------
/tests/interactive/eof-confirm-with-quit/expected:
--------------------------------------------------------------------------------
1 | foo
2 | ?
3 | Warning: buffer modified
4 |
--------------------------------------------------------------------------------
/tests/interactive/eof-modified-reset/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | modified
4 | .
5 | C-d \
6 | 1,$p
7 | C-d \
8 | 1,$p
9 | C-d \
10 | C-d \
11 |
--------------------------------------------------------------------------------
/tests/interactive/eof-modified-reset/expected:
--------------------------------------------------------------------------------
1 | ?
2 | Warning: buffer modified
3 | modified
4 | ?
5 | Warning: buffer modified
6 | modified
7 | ?
8 | Warning: buffer modified
9 |
--------------------------------------------------------------------------------
/tests/interactive/eof-modified/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | bar
5 | baz
6 | .
7 | 1,$p
8 | C-d \
9 | C-d \
10 |
--------------------------------------------------------------------------------
/tests/interactive/eof-modified/expected:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 | ?
5 | Warning: buffer modified
6 |
--------------------------------------------------------------------------------
/tests/interactive/eof/cmds:
--------------------------------------------------------------------------------
1 | .=
2 | C-d \
3 |
--------------------------------------------------------------------------------
/tests/interactive/eof/expected:
--------------------------------------------------------------------------------
1 | 0
2 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof-partial-multiple/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | bar
5 | baz C-d C-d \
6 | 1,$p
7 | Q
8 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof-partial-multiple/expected:
--------------------------------------------------------------------------------
1 | foo
2 | bar
3 | baz
4 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof-partial/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo C-d C-d \
4 | 1,$p
5 | Q
6 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof-partial/expected:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | C-d \
5 | 1,$p
6 | Q
7 |
--------------------------------------------------------------------------------
/tests/interactive/input-mode-eof/expected:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/interactive/interactive-global-eof/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | bar
5 | faz
6 | .
7 | G/^f/
8 | s/foo/test/
9 | C-d \
10 | 1,$p
11 | Q
12 |
--------------------------------------------------------------------------------
/tests/interactive/interactive-global-eof/expected:
--------------------------------------------------------------------------------
1 | foo
2 | faz
3 | ?
4 | unexpected end-of-file
5 | test
6 | bar
7 | faz
8 |
--------------------------------------------------------------------------------
/tests/interactive/interactive-unmatched-eof/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | bar
5 | faz
6 | .
7 | V/^f/
8 | C-d \
9 | 1,$p
10 | Q
11 |
--------------------------------------------------------------------------------
/tests/interactive/interactive-unmatched-eof/expected:
--------------------------------------------------------------------------------
1 | bar
2 | ?
3 | unexpected end-of-file
4 | foo
5 | bar
6 | faz
7 |
--------------------------------------------------------------------------------
/tests/interactive/prompt/cmds:
--------------------------------------------------------------------------------
1 | H
2 | 0p
3 | P
4 | 0p
5 | P
6 | 0p
7 | 0p
8 | q
9 |
--------------------------------------------------------------------------------
/tests/interactive/prompt/expected:
--------------------------------------------------------------------------------
1 | ?
2 | ranges cannot start at address zero
3 | *?
4 | ranges cannot start at address zero
5 | *?
6 | ranges cannot start at address zero
7 | ?
8 | ranges cannot start at address zero
9 |
--------------------------------------------------------------------------------
/tests/interactive/quit-confirm-with-eof/cmds:
--------------------------------------------------------------------------------
1 | H
2 | a
3 | foo
4 | .
5 | 1,$p
6 | q
7 | C-d \
8 |
--------------------------------------------------------------------------------
/tests/interactive/quit-confirm-with-eof/expected:
--------------------------------------------------------------------------------
1 | foo
2 | ?
3 | Warning: buffer modified
4 |
--------------------------------------------------------------------------------
/tests/interactive/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 |
5 | if [ -n "$TMUX" ] || ! command -v tmux 1>/dev/null 2>&1; then
6 | echo "Skipping interactive tests" 1>&2
7 | exit 0
8 | fi
9 |
10 | EDWARD="${EDWARD:-$(pwd)/../../bin/edward}"
11 | [ -x "${EDWARD}" ] || \
12 | abort "Couldn't find edward executable '${EDWARD}'."
13 |
14 | session="ed-test"
15 | cmd="sh -c 'stty -echo && tmux wait-for -S term-setup; env CHICKEN_REPOSITORY_PATH="${CHICKEN_REPOSITORY_PATH}" ${EDWARD}'"
16 |
17 | read_cmd() {
18 | [ $# -eq 0 ] || return 1
19 |
20 | # Terminate all lines with an Enter key unless the line escapes
21 | # the newline with a '\' which is useful for sending control keys.
22 | sed -e 's/\([^\]\)$/\1\nEnter/' -e 's/\\$//'
23 | }
24 |
25 | run_tmux() {
26 | tmux new-session -d -s "${session}" "${cmd}" \; \
27 | set-option -t "${session}" -w remain-on-exit "on" \; \
28 | set-option -t "${session}" -w remain-on-exit-format "" \; \
29 | \
30 | set-hook -w pane-died \
31 | "wait-for -S exit-channel" \; \
32 | \
33 | wait-for term-setup \; \
34 | send-keys -t "${session}" $(read_cmd) \; \
35 | \
36 | wait-for exit-channel \; \
37 | capture-pane -S - -E - -t "${session}" -p -C
38 | }
39 |
40 | ret=0
41 | for test in *; do
42 | [ -d "${test}" ] || continue
43 |
44 | name="${test##*/}"
45 | printf "Running test case '%s': " "${name}"
46 |
47 | run_tmux < "${test}/cmds" | awk '
48 | # Filter out all empty lines between the last non-empty line and EOF.
49 | {
50 | output = output $0
51 | if (length($0) != 0) {
52 | print(output)
53 | output = ""
54 | }
55 | }
56 | ' | cmp -s "${test}/expected" -
57 |
58 | if [ $? -eq 0 ]; then
59 | printf "OK\n"
60 | else
61 | printf "FAIL\n"
62 | ret=1
63 | fi
64 |
65 | tmux kill-session -t "${session}"
66 | done
67 |
68 | exit "${ret}"
69 |
--------------------------------------------------------------------------------
/tests/parse-addr.scm:
--------------------------------------------------------------------------------
1 | (import (edward ed addr))
2 |
3 | (test-parse (addr->range '((current-line) ())) parse-addrs ".")
4 | (test-parse (addr->range '((last-line) ())) parse-addrs "$")
5 |
6 | (define (test-addr-error desc expected input)
7 | (test-parse-error desc expected parse-addrs input))
8 |
9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 |
11 | (test-group "parse nth line"
12 | (test-parse (addr->range '((nth-line . 42) ())) parse-addrs "42")
13 | (test-addr-error "character in address" "unknown address format" "4x2")
14 | (test-addr-error "chained address without seperator" "unknown address format" "42."))
15 |
16 | (test-group "parse mark"
17 | (test-parse (addr->range '((marked-line . #\x) ())) parse-addrs "'x")
18 | (test-addr-error "multi-character mark" "invalid mark: expected lowercase character" "'FOO")
19 | (test-addr-error "mark with digit" "invalid mark: expected lowercase character" "'F23"))
20 |
21 | (test-group "parse-forward-bre"
22 | (test-parse (addr->range '((regex-forward . "foo") ())) parse-addrs "/foo/")
23 | (test-parse (addr->range '((regex-forward . "") ())) parse-addrs "//")
24 | (test-parse (addr->range '((regex-forward . "foo/bar") ())) parse-addrs "/foo\\/bar/")
25 | (test-parse (addr->range '((regex-forward . "f.*") ())) parse-addrs "/f.*")
26 | (test-parse (addr->range '((regex-forward . "f??") ())) parse-addrs "/f??/"))
27 |
28 | (test-group "parse-backward-bre"
29 | (test-parse
30 | (addr->range '((regex-backward . "foo") ()))
31 | parse-addrs
32 | "?foo?")
33 | (test-parse
34 | (addr->range '((regex-backward . "") ()))
35 | parse-addrs
36 | "??")
37 | (test-parse
38 | (addr->range '((regex-backward . "foo?bar") ()))
39 | parse-addrs
40 | "?foo\\?bar?")
41 | (test-parse
42 | (addr->range '((regex-backward . "fo\\([a-z]\\)") ()))
43 | parse-addrs
44 | "?fo\\([a-z]\\)?"))
45 |
46 | (test-group "parse-relative"
47 | (test-parse (addr->range '((relative . 5) ())) parse-addrs "+5")
48 | (test-parse (addr->range '((relative . -42) ())) parse-addrs "-42")
49 | (test-parse (addr->range '((relative . 1) ())) parse-addrs "+")
50 | (test-parse (addr->range '((relative . -1) ())) parse-addrs "-"))
51 |
52 | (test-group "parse offsets"
53 | (test-parse (addr->range '((nth-line . 2342) (1))) parse-addrs "2342 +1")
54 | (test-parse (addr->range '((relative . 5) (1 2 3))) parse-addrs "+5 1 2 3")
55 | (test-parse (addr->range '((marked-line . #\f) (23 42))) parse-addrs "'f 23 42")
56 | (test-parse (addr->range '((regex-forward . "foo") (-1 2 -3))) parse-addrs "/foo/ -1 2 -3")
57 | (test-parse (addr->range '((regex-backward . "bar") (+2342))) parse-addrs "?bar?+2342")
58 | (test-parse (addr->range '((nth-line . 23) (-5 +5))) parse-addrs "23-5+5")
59 | (test-addr-error "offset with char" "unknown address format" "23+5-f"))
60 |
61 | (test-group "address ranges"
62 | (test-parse
63 | (list #\,)
64 | parse-addrs ",")
65 |
66 | (test-parse
67 | (list
68 | #\,
69 | (make-addr '(nth-line . 2342)))
70 | parse-addrs ",2342")
71 |
72 | (test-parse
73 | (list
74 | (make-addr '(nth-line . 4223))
75 | #\,)
76 | parse-addrs "4223,")
77 |
78 | (test-parse
79 | (list #\;)
80 | parse-addrs ";")
81 |
82 | (test-parse
83 | (list
84 | #\;
85 | (make-addr '(nth-line . 9001)))
86 | parse-addrs ";9001")
87 |
88 | (test-parse
89 | (list
90 | (make-addr '(nth-line . 42))
91 | #\;)
92 | parse-addrs "42;")
93 |
94 | (test-parse
95 | (make-range
96 | (make-addr '(nth-line . 2342))
97 | #\;
98 | (make-addr '(nth-line . 4223)))
99 | parse-addrs "2342;4223")
100 |
101 | (test-parse
102 | (make-range
103 | (make-addr '(nth-line . 9000))
104 | #\,
105 | (make-addr '(nth-line . 9001)))
106 | parse-addrs "9000,9001")
107 |
108 | (test-parse
109 | (make-range
110 | (make-addr '(nth-line . 23))
111 | #\,
112 | (make-addr '(nth-line . 42)))
113 | parse-addrs "23 , 42")
114 |
115 | (test-parse
116 | (make-range
117 | (make-addr '(nth-line . 23) '(23 42))
118 | #\,
119 | (make-addr '(nth-line . 42) '(42 23)))
120 | parse-addrs "23 +23 +42, 42 +42 +23"))
121 |
122 | (test-group "multiple addresses"
123 | (test-parse
124 | (list
125 | (make-addr '(nth-line . 1))
126 | #\,
127 | (make-addr '(nth-line . 2))
128 | #\,
129 | (make-addr '(nth-line . 3)))
130 | parse-addrs "1,2,3")
131 |
132 | (test-parse
133 | (list #\, #\,)
134 | parse-addrs ",,")
135 |
136 | (test-parse
137 | (list #\, #\;)
138 | parse-addrs ",;")
139 |
140 | (test-parse
141 | (list
142 | (make-addr '(nth-line . 7))
143 | #\,
144 | (make-addr '(nth-line . 5))
145 | #\,)
146 | parse-addrs "7,5,"))
147 |
--------------------------------------------------------------------------------
/tests/parse-cmd.scm:
--------------------------------------------------------------------------------
1 | (import (edward ed cmd)
2 | (edward ed posix)
3 | (edward ed addr)
4 | (edward ed editor))
5 |
6 | (define (test-parse-cmd desc expected input)
7 | (test desc expected
8 | (let* ((cmd-input (string-append input "\n"))
9 | (cmd-pair (%test-parse (parse-cmd) cmd-input))
10 | (cmd-addr (car cmd-pair))
11 | (cmd-args (cmd-args (cdr cmd-pair))))
12 | (append (list cmd-addr) cmd-args))))
13 |
14 | (define (test-cmd-error desc expected input)
15 | (test-parse-error desc expected (parse-cmd) input))
16 |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18 |
19 | (test-group "append command"
20 | (test-parse-cmd "no arguments"
21 | (list #f '()) "a\n.")
22 | (test-parse-cmd "preceeding whitespaces"
23 | (list #f '()) " a\n.")
24 | (test-parse-cmd "custom address without offset"
25 | (list
26 | (addr->range (make-addr '(nth-line . 2342)))
27 | '())
28 | "2342 a\n.")
29 | (test-parse-cmd "custom address with offset"
30 | (list
31 | (addr->range (make-addr '(last-line . ()) '(42)))
32 | '())
33 | "$+42 a\n."))
34 |
35 | (test-group "read command"
36 | (test-parse-cmd "no arguments"
37 | (list
38 | #f
39 | "") "r")
40 |
41 | (test-parse-cmd "custom address"
42 | (list
43 | (addr->range (make-addr '(nth-line . 42)))
44 | "") "42r")
45 |
46 | (test-parse-cmd "custom address and file"
47 | (list
48 | (addr->range (make-addr '(regex-backward . "foo") '(23 -42)))
49 | "foobar") "?foo? +23 -42 r foobar")
50 |
51 | (test-cmd-error "filename w/o whitespace" "expected newline" "rfoo"))
52 |
53 | (test-group "write command"
54 | (test-parse-cmd "no arguments"
55 | (list
56 | #f
57 | "") "w")
58 |
59 | (test-parse-cmd "custom address and offset, no whitespaces"
60 | (list
61 | (make-range
62 | (make-addr '(current-line))
63 | (make-addr '(current-line) '(10)))
64 | "foobar") ".,.+10w foobar")
65 |
66 | (test-cmd-error "filename w/o whitespace" "expected newline" "wfoo"))
67 |
68 | (test-group "shell command"
69 | (test-parse-cmd "no replacements"
70 | (list #f (list "echo foobar")) "!echo foobar")
71 | (test-parse-cmd "command with replacement"
72 | (list #f (list "echo " 'current-file)) "!echo %")
73 | (test-parse-cmd "previous command"
74 | (list #f '(previous-command)) "!!")
75 | (test-parse-cmd "previous command appended"
76 | (list #f '(previous-command "foobar")) "!!foobar")
77 | (test-parse-cmd "previous command syntax not start"
78 | (list #f '("foobar !! barfoo")) "!foobar !! barfoo")
79 | (test-parse-cmd "escaped replacement"
80 | (list #f (list "echo %")) "!echo \\%")
81 | (test-parse-cmd "multiple replacements"
82 | (list #f (list "echo " 'current-file " " 'current-file)) "!echo % %"))
83 |
84 | (test-group "global command"
85 | (test-parse-cmd "single command no newline"
86 | (list
87 | (make-range
88 | (make-addr '(nth-line . 1))
89 | (make-addr '(last-line)))
90 | "foo"
91 | "p\n") "1,$g/foo/p")
92 |
93 | (test-parse-cmd "empty command-list"
94 | (list
95 | #f
96 | "bar"
97 | "p\n") "g/bar/")
98 |
99 | (test-parse-cmd "single trailing whitespace"
100 | (list
101 | (make-range
102 | (make-addr '(nth-line . 1))
103 | (make-addr '(last-line)))
104 | "foobar"
105 | "p \n") "1,$g/foobar/p ")
106 |
107 | (test-parse-cmd "single command no newline"
108 | (list
109 | (make-range
110 | (make-addr '(nth-line . 23))
111 | (make-addr '(nth-line . 42)))
112 | "test"
113 | "p \np\n") "23,42g/test/p \\\np")
114 |
115 | (test-cmd-error "missing regex" "expected regex" "1,$gp"))
116 |
117 | (test-group "miscellaneous"
118 | (test-parse-cmd "parse command with trailing blanks"
119 | (list (addr->range (make-addr '(nth-line . 2342)))
120 | '())
121 | "2342a \n.")
122 |
123 | (test-parse-cmd "append command with suffixed printing command"
124 | (list (addr->range (make-addr '(nth-line . 42)))
125 | '())
126 | "42an\n.")
127 |
128 | (test-cmd-error "unknown command character" "unknown command" "X")
129 | (test-cmd-error "quit command with argument" "expected newline" "Qn")
130 | (test-cmd-error "append command with argument" "expected newline" "a n"))
131 |
--------------------------------------------------------------------------------
/tests/replace.scm:
--------------------------------------------------------------------------------
1 | (import posix-regex (edward replace))
2 |
3 | (define (test-re str pattern replacement . o)
4 | (let-values (((result modified)
5 | (regex-replace
6 | (make-regex pattern)
7 | (parse (parse-replace #\/) replacement)
8 | str
9 | (if (null? o) 0 (car o)))))
10 | (cons result modified)))
11 |
12 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 |
14 | (test-group "backreferences"
15 | (test "single backreference"
16 | '("faz" . #t)
17 | (test-re "foo" "\\([a-z]\\)oo" "\\1az"))
18 | (test "multiple backreferences"
19 | '("bar foo" . #t)
20 | (test-re "foo bar" "\\([a-z]*\\) \\([a-z]*\\)" "\\2 \\1"))
21 | (test "unused backreferences"
22 | '("2" . #t)
23 | (test-re "123" "\\([0-9]\\)\\([0-9]\\)\\([0-9]\\)" "\\2"))
24 | (test "escape subexpression"
25 | '("bar" . #t)
26 | (test-re "\\(foo\\)" "\\\\(foo\\\\)" "bar")))
27 |
28 | (test-group "ampersand"
29 | (test "append text"
30 | '("foobar" . #t)
31 | (test-re "foo" "foo" "&bar"))
32 | (test "append in middle"
33 | '("foo123bar" . #t)
34 | (test-re "foo1bar" "1" "&23"))
35 | (test "escape ampersand"
36 | '("&bar" . #t)
37 | (test-re "foo" "foo" "\\&bar")))
38 |
39 | (test-group "replacement amount"
40 | (test "replace first match only"
41 | '("testbarfoo" . #t)
42 | (test-re "foobarfoo" "foo" "test" 1))
43 | (test "replace all matches"
44 | '("testbartest" . #t)
45 | (test-re "foobarfoo" "foo" "test" 0))
46 | (test "replace second match only"
47 | '("foobartest" . #t)
48 | (test-re "foobarfoo" "foo" "test" 2)))
49 |
50 | (test-group "miscellaneous"
51 | (test "input string with multibyte character"
52 | '("foo|bar" . #t)
53 | (test-re "fooλbar" "λ" "|"))
54 | (test "replacement with multibyte character"
55 | '("fooλbar" . #t)
56 | (test-re "foo|bar" "|" "λ"))
57 | (test "replace with newline"
58 | '("foo\nbar" . #t)
59 | (test-re "foo|bar" "|" "\\\n"))
60 | (test "non-participating submatch"
61 | '("baz" . #t)
62 | (test-re "foo baz" "foo \\(..*\\)* \\(..*\\)" "\\2\\1"))
63 | (test "empty submatch"
64 | '("matched: " . #t)
65 | (test-re "foo <> baz"
66 | "foo <\\(.*\\)> baz"
67 | "matched: \\1")))
68 |
69 | (test-group "modified"
70 | (test "no match"
71 | '("foo" . #f)
72 | (test-re "foo" "bar" "test"))
73 |
74 | (test "replace second match"
75 | '(" foo foo bar " . #t)
76 | (test-re " foo foo foo " " foo " " bar " 2)))
77 |
--------------------------------------------------------------------------------
/tests/run.scm:
--------------------------------------------------------------------------------
1 | (import r7rs test (edward parse))
2 |
3 | (define (%test-parse parser input)
4 | (define (parse-with-error parser stream)
5 | (call-with-parse parser stream 0
6 | (lambda (r s i fk)
7 | (if (parse-stream-end? s i)
8 | r
9 | (fk s i "incomplete parse")))
10 | (lambda (s i reason) (error reason))))
11 |
12 | (let* ((stream (string->parse-stream input))
13 | (result (parse-with-error parser stream)))
14 | result))
15 |
16 | (define (test-parse expected parser input)
17 | (test expected (%test-parse parser input)))
18 |
19 | (define (test-parse-error desc expected parser input)
20 | (let ((r (call-with-current-continuation
21 | (lambda (k)
22 | (with-exception-handler
23 | (lambda (e) (k e))
24 | (lambda ( ) (k (%test-parse parser input))))))))
25 | (test desc expected
26 | (if (error-object? r)
27 | (error-object-message r))))) ;; (not (error-object? r)) → undefined
28 |
29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 |
31 | (include-relative "parse-addr.scm")
32 | (include-relative "parse-cmd.scm")
33 | (include-relative "replace.scm")
34 | (include-relative "buffer.scm")
35 | (include-relative "util.scm")
36 |
37 | ;; Exit with non-zero exit status if some test failed.
38 | (test-exit)
39 |
--------------------------------------------------------------------------------
/tests/util.scm:
--------------------------------------------------------------------------------
1 | (import (edward util))
2 |
3 | (test-group "ports->lines"
4 | (test "multiple"
5 | '(("foo" "bar" "baz") . 12)
6 | (let ((port (open-input-string "foo\nbar\nbaz\n")))
7 | (port->lines port)))
8 |
9 | (test "empty"
10 | '(() . 0)
11 | (let ((port (open-input-string "")))
12 | (port->lines port))))
13 |
14 | (test-group "count-bytes"
15 | (test "ascii string" 6 (count-bytes "foobar"))
16 | (test "multibyte string" 2 (count-bytes "λ")))
17 |
18 | (test-group "path-join"
19 | (test "empty" "" (path-join))
20 | (test "single" "foo" (path-join "foo"))
21 | (test "multiple" "foo/bar/baz" (path-join "foo" "bar" "baz")))
22 |
--------------------------------------------------------------------------------