~martanne/devel

vis: feat[lua] add function vis:file_exists() v1 APPLIED

Matěj Cepl: 6
 feat[lua] add function vis:file_exists()
 no longer depend on lua-busted
 no longer depend on lua-busted
 lua: remove forgotten require 'busted.runner'
 lua: add falsy and truthy asserts
 lua: add function vis:file_exists()

 27 files changed, 364 insertions(+), 81 deletions(-)
#1336506 alpine.yml success
#1336507 debian.yml success
#1336508 freebsd.yml success
#1336509 openbsd.yml success
Hi!

I think the first two commits are fine besides the comment inline
(though they should be squashed).

As for the file_exists I don't think its vis' job to provide a lua
standard library. I'm also against the notion of providing trivial
snippets of code as library functions (ala javascript "isEven").
If you really have a plugin where you are using this function in
tons of places include it in your there but otherwise this code
should just be inline where it is needed.
Matěj Cepl <mcepl@cepl.eu> wrote:
Next
--
https://rnpnr.xyz/
GPG Fingerprint: B8F0 CF4C B6E9 415C 1B27 A8C4 C8D2 F782 86DF 2DC5
Next
Matěj Cepl <mcepl@cepl.eu> wrote:
Next
Matěj Cepl <mcepl@cepl.eu> wrote:
Applied thanks!

Also this one which I can't seem to find in my inbox and don't
know why was rejected:
https://lists.sr.ht/~martanne/devel/patches/55191
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~martanne/devel/patches/55192/mbox | git am -3
Learn more about email & git

[RFC PATCH vis] feat[lua] add function vis:file_exists() Export this patch

---
It seems to me that I am copying the same file_exists() to every
other plugin I make. It should be part of our standard library.

What do you think?

 lua/vis.lua              | 21 +++++++++++++++++++++
 test/lua/file-exists.in  | 14 ++++++++++++++
 test/lua/file-exists.lua | 16 ++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 test/lua/file-exists.in
 create mode 100644 test/lua/file-exists.lua

diff --git a/lua/vis.lua b/lua/vis.lua
index d06bbafb..c3ef166d 100644
--- a/lua/vis.lua
+++ b/lua/vis.lua
@@ -113,6 +113,27 @@ vis.module_exist = function(_, name)
	return false
end

--- Check whether a file exists
--
-- Checks whether the file exists identified by anything which
-- can be opened with @{io.open}.
--
-- @tparam string path name of the file including path
-- @treturn bool whether the file exists
-- @usage
-- if vis:file_exists("/etc/passwd") then
-- 	-- do something
-- end
--
vis.file_exists = function(_, path)
	local f = io.open(path)
	local out = f ~= nil
	if out then
		io.close(f)
	end
	return out
end

vis.lexers = {}

if not vis:module_exist('lpeg') then
diff --git a/test/lua/file-exists.in b/test/lua/file-exists.in
new file mode 100644
index 00000000..892e5c0d
--- /dev/null
+++ b/test/lua/file-exists.in
@@ -0,0 +1,14 @@
Byl pozdní večer — první máj —
večerní máj — byl lásky čas.
Hrdliččin zval ku lásce hlas,
kde borový zaváněl háj.
O lásce šeptal tichý mech;
květoucí strom lhal lásky žel,
svou lásku slavík růži pěl,
růžinu jevil vonný vzdech.
Jezero hladké v křovích stinných
zvučelo temně tajný bol,
břeh je objímal kol a kol;
a slunce jasná světů jiných
bloudila blankytnými pásky,
planoucí tam co slzy lásky.
diff --git a/test/lua/file-exists.lua b/test/lua/file-exists.lua
new file mode 100644
index 00000000..c51b1ce0
--- /dev/null
+++ b/test/lua/file-exists.lua
@@ -0,0 +1,16 @@
require 'busted.runner'()

local file = vis.win.file

describe("file exists", function()

	it("has name", function()
		assert.is_true(file.name:len() > 0)
	end)

	it("exists", function()
		assert.is_true(vis:file_exists(file.path))
	end)

end)

-- 
2.46.1
vis/patches: SUCCESS in 1m17s

[feat[lua] add function vis:file_exists()][0] from [Matěj Cepl][1]

[0]: https://lists.sr.ht/~martanne/devel/patches/55192
[1]: mailto:mcepl@cepl.eu

✓ #1336507 SUCCESS vis/patches/debian.yml  https://builds.sr.ht/~martanne/job/1336507
✓ #1336506 SUCCESS vis/patches/alpine.yml  https://builds.sr.ht/~martanne/job/1336506
✓ #1336508 SUCCESS vis/patches/freebsd.yml https://builds.sr.ht/~martanne/job/1336508
✓ #1336509 SUCCESS vis/patches/openbsd.yml https://builds.sr.ht/~martanne/job/1336509

[PATCH vis v2 1/4] no longer depend on lua-busted Export this patch

From: Jeremy Bobbin <jer@jer.cx>

---
 test/.gitignore         |   1 -
 test/lua/Makefile       |   2 +-
 test/lua/README.md      |   2 +-
 test/lua/cursor.lua     |   1 -
 test/lua/file-empty.lua |   1 -
 test/lua/lines.lua      |   1 -
 test/lua/map-basic.lua  |   1 -
 test/lua/test.sh        |   9 +--
 test/lua/visrc.lua      | 128 ++++++++++++++++++++++++++++++++++------
 9 files changed, 115 insertions(+), 31 deletions(-)

diff --git a/test/.gitignore b/test/.gitignore
index b62c022f..4b76c8e4 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,4 +1,3 @@
*.out
*.err
*.status
*.busted
diff --git a/test/lua/Makefile b/test/lua/Makefile
index a7afc801..84a1eedc 100644
--- a/test/lua/Makefile
+++ b/test/lua/Makefile
@@ -5,7 +5,7 @@ all: clean ../../vis test
	@$(MAKE) -C ../..

clean:
	@rm -f *.out *.err *.busted
	@rm -f *.out *.err

test:
	@./test.sh
diff --git a/test/lua/README.md b/test/lua/README.md
index 5b9a1e6f..a6bffb3d 100644
--- a/test/lua/README.md
+++ b/test/lua/README.md
@@ -1,7 +1,7 @@
Unit Test for Vis' Lua API
--------------------------

The tests use the [busted unit testing framework](https://olivinelabs.com/busted/).
The test-suite is based on the [busted unit testing framework](https://olivinelabs.com/busted/).

Each `*.lua` file is sourced from a new `vis` instance which loads the
correspending `*.in` file.
diff --git a/test/lua/cursor.lua b/test/lua/cursor.lua
index 8ea34040..34d7ca09 100644
--- a/test/lua/cursor.lua
+++ b/test/lua/cursor.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local win = vis.win

diff --git a/test/lua/file-empty.lua b/test/lua/file-empty.lua
index 69ec17d5..c94e5232 100644
--- a/test/lua/file-empty.lua
+++ b/test/lua/file-empty.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

diff --git a/test/lua/lines.lua b/test/lua/lines.lua
index 745e8b05..76b2741d 100644
--- a/test/lua/lines.lua
+++ b/test/lua/lines.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

diff --git a/test/lua/map-basic.lua b/test/lua/map-basic.lua
index b0ce941d..7e0dba15 100644
--- a/test/lua/map-basic.lua
+++ b/test/lua/map-basic.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

vis:map(vis.modes.NORMAL, "K", function()
	vis:feedkeys("iNormal Mode<Escape>")
diff --git a/test/lua/test.sh b/test/lua/test.sh
index 4d885de3..db7fb1e7 100755
--- a/test/lua/test.sh
+++ b/test/lua/test.sh
@@ -9,11 +9,6 @@ if ! $VIS -v | grep '+lua' >/dev/null 2>&1; then
	exit 0
fi

type busted >/dev/null 2>&1 || {
	echo "busted(1) not found, skipping tests"
	exit 0
}

TESTS_OK=0
TESTS_RUN=0

@@ -28,11 +23,11 @@ for t in $test_files; do
	t=${t%.lua}
	t=${t#./}
	printf "%-30s" "$t"
	$VIS "$t.in" < /dev/null 2> /dev/null > "$t.busted"
	$VIS "$t.in" < /dev/null 2> /dev/null > "$t.out"

	if [ $? -ne 0 ]; then
		printf "FAIL\n"
		cat "$t.busted"
		cat "$t.out"
	else
		TESTS_OK=$((TESTS_OK + 1))
		printf "OK\n"
diff --git a/test/lua/visrc.lua b/test/lua/visrc.lua
index 16aa8b99..31656745 100644
--- a/test/lua/visrc.lua
+++ b/test/lua/visrc.lua
@@ -1,28 +1,122 @@
package.path = '../../lua/?.lua;'..package.path

dofile("../../lua/vis.lua")

--- redirect output to stdout, stderr is used by the vis UI
io.stderr = io.stdout
local function str(e)
	if type(e) == "string" then
		if e == "" then
			return "an empty string"
		else
			return '"'..e..'"'
		end
	else
		return tostring(e)
	end
end


local function same(a, b)
	if type(a) ~= type(b) then
		return string.format("expected %s - got %s", type(a), type(b))
	end

	if type(a) ~= 'table' then
		if a == b then
			return nil
		else
			return string.format("expected %s - got %s", str(a), str(b))
		end
	end

	if #a ~= #b then
		return string.format("expected table of size %d got %d", #a, #b)
	end

	for k, v in pairs(a) do
		if b[k] == nil then
			return string.format("expected %s got nil", str(k))
		end
		r = same(v, b[k])
		if r ~= nil then
			return r
		end
	end
	return nil
end

--- make sure we gracefully terminate, cleanup terminal state etc.
os.exit = function(status)
	vis:exit(status)

local msg = ""
function describe(s, fn)
	group = {
		before_each = function()
		end,
		tests = {},
		after_each = function()
		end,

	}
	function before_each(fn) group.before_each = fn end
	function after_each(fn) group.after_each = fn end
	function it(s, fn)
		table.insert(group.tests, {
			s = s,
			fn = fn,
			assertions = {},
		})
	end
	fn()
	for j, t in pairs(group.tests) do
		group.before_each()
		assert = {
			has_error = function(fn)
				local status, err = pcall(fn)
				if err == nil then
					msg = msg..string.format("%s %s: expected error\n", s, t.s)
				end
			end,
			are = {
				equal = function(a, b)
					if a ~= b then
						msg = msg..string.format("%s %s: expected %s - got %s\n", s, t.s, str(a), str(b))
					end
				end,
				equals = function(a, b)
					if a ~= b then
						msg = msg..string.format("%s %s: expected %s - got %s\n", s, t.s, str(a), str(b))
					end
				end,
				same = function(a, b)
					r = same(a, b) -- same returns a string which is a reason why a & b are not equal
					if r ~= nil then
						msg = msg..string.format("%s %s: %s\n", s, t.s, r)
					end
				end,
			},
		}
		t.fn()
		group.after_each()
	end
end


vis.events.subscribe(vis.events.WIN_OPEN, function(win)
	-- test.in file passed to vis
	local in_file = win.file.name
	if in_file then
		-- use the corresponding test.lua file
		lua_file = string.gsub(in_file, '%.in$', '.lua')
		local ok, msg = pcall(dofile, lua_file)
		if not ok then
			if type(msg) == 'string' then
				print(msg)
			end
			vis:exit(1)
			return
		end
	if not in_file then
		return
	end

	-- use the corresponding test.lua file
	lua_file = string.gsub(in_file, '%.in$', '.lua')

	local ok, err = pcall(dofile, lua_file)
	if not ok then
		print(tostring(err))
		vis:exit(2) -- ERROR
	elseif msg ~= "" then
		io.write(msg) -- no newline
		vis:exit(1) -- FAIL
	else
		vis:exit(0) -- SUCCESS
	end
	vis:exit(0)
end)
-- 
2.46.1
Hi!

I think the first two commits are fine besides the comment inline
(though they should be squashed).

As for the file_exists I don't think its vis' job to provide a lua
standard library. I'm also against the notion of providing trivial
snippets of code as library functions (ala javascript "isEven").
If you really have a plugin where you are using this function in
tons of places include it in your there but otherwise this code
should just be inline where it is needed.

Matěj Cepl <mcepl@cepl.eu> wrote:
--
https://rnpnr.xyz/
GPG Fingerprint: B8F0 CF4C B6E9 415C 1B27 A8C4 C8D2 F782 86DF 2DC5

[PATCH vis v2] no longer depend on lua-busted Export this patch

From: Jeremy Bobbin <jer@jer.cx>

---
- remove assert.are.equals

 test/.gitignore         |   1 -
 test/lua/Makefile       |   2 +-
 test/lua/README.md      |   2 +-
 test/lua/cursor.lua     |   1 -
 test/lua/file-empty.lua |   1 -
 test/lua/lines.lua      |  31 +++++-----
 test/lua/map-basic.lua  |   1 -
 test/lua/pipe.lua       |   2 -
 test/lua/test.sh        |   9 +--
 test/lua/visrc.lua      | 133 +++++++++++++++++++++++++++++++++++-----
 10 files changed, 135 insertions(+), 48 deletions(-)

diff --git a/test/.gitignore b/test/.gitignore
index b62c022f..4b76c8e4 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,4 +1,3 @@
*.out
*.err
*.status
*.busted
diff --git a/test/lua/Makefile b/test/lua/Makefile
index a7afc801..84a1eedc 100644
--- a/test/lua/Makefile
+++ b/test/lua/Makefile
@@ -5,7 +5,7 @@ all: clean ../../vis test
	@$(MAKE) -C ../..

clean:
	@rm -f *.out *.err *.busted
	@rm -f *.out *.err

test:
	@./test.sh
diff --git a/test/lua/README.md b/test/lua/README.md
index 5b9a1e6f..a6bffb3d 100644
--- a/test/lua/README.md
+++ b/test/lua/README.md
@@ -1,7 +1,7 @@
Unit Test for Vis' Lua API
--------------------------

The tests use the [busted unit testing framework](https://olivinelabs.com/busted/).
The test-suite is based on the [busted unit testing framework](https://olivinelabs.com/busted/).

Each `*.lua` file is sourced from a new `vis` instance which loads the
correspending `*.in` file.
diff --git a/test/lua/cursor.lua b/test/lua/cursor.lua
index 8ea34040..34d7ca09 100644
--- a/test/lua/cursor.lua
+++ b/test/lua/cursor.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local win = vis.win

diff --git a/test/lua/file-empty.lua b/test/lua/file-empty.lua
index 69ec17d5..c94e5232 100644
--- a/test/lua/file-empty.lua
+++ b/test/lua/file-empty.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

diff --git a/test/lua/lines.lua b/test/lua/lines.lua
index 745e8b05..296ba772 100644
--- a/test/lua/lines.lua
+++ b/test/lua/lines.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

@@ -22,33 +21,33 @@ end)
describe("get file.lines[]", function()

	it("#lines", function()
		assert.are.equals(5, #file.lines)
		assert.are.equal(5, #file.lines)
	end)

	it("get lines[0]", function()
		-- is that what we want?
		assert.are.equals(file.lines[0], file.lines[1])
		assert.are.equal(file.lines[0], file.lines[1])
	end)

	it("get lines[1]", function()
		assert.are.equals("1", file.lines[1])
		assert.are.equal("1", file.lines[1])
	end)

	it("get empty \n line", function()
		assert.are.equals("", file.lines[2])
		assert.are.equal("", file.lines[2])
	end)

	it("get empty \r\n line", function()
		assert.are.equals("\r", file.lines[4])
		assert.are.equal("\r", file.lines[4])
	end)

	it("get lines[#lines]", function()
		assert.are.equals("5", file.lines[#file.lines])
		assert.are.equal("5", file.lines[#file.lines])
	end)

	it("get lines[#lines+1]", function()
		-- is that what we want?
		assert.are.equals("5", file.lines[#file.lines])
		assert.are.equal("5", file.lines[#file.lines])
	end)

end)
@@ -58,14 +57,14 @@ describe("set file.lines[]", function()
	it("replace empty \n line", function()
		local new = "line 2"
		file.lines[2] = new
		assert.are.equals(new, file.lines[2])
		assert.are.equal(new, file.lines[2])
	end)

--[[
	it("replace empty \r\n line", function()
		local new = "line 4"
		file.lines[4] = new
		assert.are.equals(new, file.lines[4])
		assert.are.equal(new, file.lines[4])
	end)
--]]

@@ -74,9 +73,9 @@ describe("set file.lines[]", function()
		local new_first = "new first line"
		local old_first = file.lines[1]
		file.lines[0] = new_first
		assert.are.equals(lines+1, #file.lines)
		assert.are.equals(new_first, file.lines[1])
		assert.are.equals(old_first, file.lines[2])
		assert.are.equal(lines+1, #file.lines)
		assert.are.equal(new_first, file.lines[1])
		assert.are.equal(old_first, file.lines[2])
	end)

	it("set lines[#lines+1], add new line at end", function()
@@ -84,9 +83,9 @@ describe("set file.lines[]", function()
		local new_last = "new last line"
		local old_last = file.lines[#file.lines]
		file.lines[#file.lines+1] = new_last
		assert.are.equals(lines+1, #file.lines)
		assert.are.equals(new_last, file.lines[#file.lines])
		assert.are.equals(old_last, file.lines[lines])
		assert.are.equal(lines+1, #file.lines)
		assert.are.equal(new_last, file.lines[#file.lines])
		assert.are.equal(old_last, file.lines[lines])
	end)

end)
diff --git a/test/lua/map-basic.lua b/test/lua/map-basic.lua
index b0ce941d..7e0dba15 100644
--- a/test/lua/map-basic.lua
+++ b/test/lua/map-basic.lua
@@ -1,4 +1,3 @@
require 'busted.runner'()

vis:map(vis.modes.NORMAL, "K", function()
	vis:feedkeys("iNormal Mode<Escape>")
diff --git a/test/lua/pipe.lua b/test/lua/pipe.lua
index 9dfb670b..1edd073b 100644
--- a/test/lua/pipe.lua
+++ b/test/lua/pipe.lua
@@ -1,5 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

describe("vis.pipe", function()
diff --git a/test/lua/test.sh b/test/lua/test.sh
index 4d885de3..db7fb1e7 100755
--- a/test/lua/test.sh
+++ b/test/lua/test.sh
@@ -9,11 +9,6 @@ if ! $VIS -v | grep '+lua' >/dev/null 2>&1; then
	exit 0
fi

type busted >/dev/null 2>&1 || {
	echo "busted(1) not found, skipping tests"
	exit 0
}

TESTS_OK=0
TESTS_RUN=0

@@ -28,11 +23,11 @@ for t in $test_files; do
	t=${t%.lua}
	t=${t#./}
	printf "%-30s" "$t"
	$VIS "$t.in" < /dev/null 2> /dev/null > "$t.busted"
	$VIS "$t.in" < /dev/null 2> /dev/null > "$t.out"

	if [ $? -ne 0 ]; then
		printf "FAIL\n"
		cat "$t.busted"
		cat "$t.out"
	else
		TESTS_OK=$((TESTS_OK + 1))
		printf "OK\n"
diff --git a/test/lua/visrc.lua b/test/lua/visrc.lua
index 16aa8b99..a19916f3 100644
--- a/test/lua/visrc.lua
+++ b/test/lua/visrc.lua
@@ -1,28 +1,127 @@
package.path = '../../lua/?.lua;'..package.path

dofile("../../lua/vis.lua")

--- redirect output to stdout, stderr is used by the vis UI
io.stderr = io.stdout
local function str(e)
	if type(e) == "string" then
		if e == "" then
			return "an empty string"
		else
			return '"'..e..'"'
		end
	else
		return tostring(e)
	end
end


local function same(a, b)
	if type(a) ~= type(b) then
		return string.format("expected %s - got %s", type(a), type(b))
	end

	if type(a) ~= 'table' then
		if a == b then
			return nil
		else
			return string.format("expected %s - got %s", str(a), str(b))
		end
	end

	if #a ~= #b then
		return string.format("expected table of size %d got %d", #a, #b)
	end

	for k, v in pairs(a) do
		if b[k] == nil then
			return string.format("expected %s got nil", str(k))
		end
		r = same(v, b[k])
		if r ~= nil then
			return r
		end
	end
	return nil
end

--- make sure we gracefully terminate, cleanup terminal state etc.
os.exit = function(status)
	vis:exit(status)

local msg = ""
function describe(s, fn)
	group = {
		before_each = function()
		end,
		tests = {},
		after_each = function()
		end,

	}
	function before_each(fn) group.before_each = fn end
	function after_each(fn) group.after_each = fn end
	function it(s, fn)
		table.insert(group.tests, {
			s = s,
			fn = fn,
			assertions = {},
		})
	end
	fn()
	for j, t in pairs(group.tests) do
		group.before_each()
		assert = {
			has_error = function(fn)
				local status, err = pcall(fn)
				if err == nil then
					msg = msg..string.format("%s %s: expected error\n", s, t.s)
				end
			end,
			truthy = function(stat)
				if not (stat) then
					msg = msg..string.format("%s %s: expected to be truthy: %s\n", s, t.s, str(stat))
				end
			end,
			falsy = function(stat)
				if (stat) then
					msg = msg..string.format("%s %s: expected to be falsy: %s\n", s, t.s, str(stat))
				end
			end,
			are = {
				equal = function(a, b)
					if a ~= b then
						msg = msg..string.format("%s %s: expected %s - got %s\n", s, t.s, str(a), str(b))
					end
				end,
				same = function(a, b)
					r = same(a, b) -- same returns a string which is a reason why a & b are not equal
					if r ~= nil then
						msg = msg..string.format("%s %s: %s\n", s, t.s, r)
					end
				end,
			},
		}
		t.fn()
		group.after_each()
	end
end


vis.events.subscribe(vis.events.WIN_OPEN, function(win)
	-- test.in file passed to vis
	local in_file = win.file.name
	if in_file then
		-- use the corresponding test.lua file
		lua_file = string.gsub(in_file, '%.in$', '.lua')
		local ok, msg = pcall(dofile, lua_file)
		if not ok then
			if type(msg) == 'string' then
				print(msg)
			end
			vis:exit(1)
			return
		end
	if not in_file then
		return
	end

	-- use the corresponding test.lua file
	lua_file = string.gsub(in_file, '%.in$', '.lua')

	local ok, err = pcall(dofile, lua_file)
	if not ok then
		print(tostring(err))
		vis:exit(2) -- ERROR
	elseif msg ~= "" then
		io.write(msg) -- no newline
		vis:exit(1) -- FAIL
	else
		vis:exit(0) -- SUCCESS
	end
	vis:exit(0)
end)
-- 
2.47.1
Matěj Cepl <mcepl@cepl.eu> wrote:
Applied thanks!

Also this one which I can't seem to find in my inbox and don't
know why was rejected:
https://lists.sr.ht/~martanne/devel/patches/55191

[PATCH vis v2 2/4] lua: remove forgotten require 'busted.runner' Export this patch

---
 test/lua/pipe.lua | 2 --
 1 file changed, 2 deletions(-)

diff --git a/test/lua/pipe.lua b/test/lua/pipe.lua
index 9dfb670b..1edd073b 100644
--- a/test/lua/pipe.lua
+++ b/test/lua/pipe.lua
@@ -1,5 +1,3 @@
require 'busted.runner'()

local file = vis.win.file

describe("vis.pipe", function()
-- 
2.46.1

[PATCH vis v2 3/4] lua: add falsy and truthy asserts Export this patch

---
 test/lua/visrc.lua | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/lua/visrc.lua b/test/lua/visrc.lua
index 31656745..984b81d3 100644
--- a/test/lua/visrc.lua
+++ b/test/lua/visrc.lua
@@ -74,6 +74,16 @@ function describe(s, fn)
					msg = msg..string.format("%s %s: expected error\n", s, t.s)
				end
			end,
			truthy = function(stat)
				if not (stat) then
					msg = msg..string.format("%s %s: expected to be truthy: %s\n", s, t.s, str(stat))
				end
			end,
			falsy = function(stat)
				if (stat) then
					msg = msg..string.format("%s %s: expected to be falsy: %s\n", s, t.s, str(stat))
				end
			end,
			are = {
				equal = function(a, b)
					if a ~= b then
-- 
2.46.1

[PATCH vis v2 4/4] lua: add function vis:file_exists() Export this patch

---
 lua/vis.lua              | 21 +++++++++++++++++++++
 test/lua/file-exists.in  | 14 ++++++++++++++
 test/lua/file-exists.lua | 18 ++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 test/lua/file-exists.in
 create mode 100644 test/lua/file-exists.lua

diff --git a/lua/vis.lua b/lua/vis.lua
index d06bbafb..c3ef166d 100644
--- a/lua/vis.lua
+++ b/lua/vis.lua
@@ -113,6 +113,27 @@ vis.module_exist = function(_, name)
	return false
end

--- Check whether a file exists
--
-- Checks whether the file exists identified by anything which
-- can be opened with @{io.open}.
--
-- @tparam string path name of the file including path
-- @treturn bool whether the file exists
-- @usage
-- if vis:file_exists("/etc/passwd") then
-- 	-- do something
-- end
--
vis.file_exists = function(_, path)
	local f = io.open(path)
	local out = f ~= nil
	if out then
		io.close(f)
	end
	return out
end

vis.lexers = {}

if not vis:module_exist('lpeg') then
diff --git a/test/lua/file-exists.in b/test/lua/file-exists.in
new file mode 100644
index 00000000..892e5c0d
--- /dev/null
+++ b/test/lua/file-exists.in
@@ -0,0 +1,14 @@
Byl pozdní večer — první máj —
večerní máj — byl lásky čas.
Hrdliččin zval ku lásce hlas,
kde borový zaváněl háj.
O lásce šeptal tichý mech;
květoucí strom lhal lásky žel,
svou lásku slavík růži pěl,
růžinu jevil vonný vzdech.
Jezero hladké v křovích stinných
zvučelo temně tajný bol,
břeh je objímal kol a kol;
a slunce jasná světů jiných
bloudila blankytnými pásky,
planoucí tam co slzy lásky.
diff --git a/test/lua/file-exists.lua b/test/lua/file-exists.lua
new file mode 100644
index 00000000..8d4c3898
--- /dev/null
+++ b/test/lua/file-exists.lua
@@ -0,0 +1,18 @@
local file = vis.win.file

describe("file exists", function()

	it("has name", function()
		assert.truthy(file.name:len() > 0)
	end)

	it("exists", function()
		assert.truthy(vis:file_exists(file.path))
	end)

	it("and this doesn't exist", function()
		assert.falsy(vis:file_exists("/doesnt-exist"))
	end)

end)

-- 
2.46.1