mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #18706 execute Lua with "nvim -l"
This commit is contained in:
commit
08ebf8d3a8
6
.github/workflows/api-docs.yml
vendored
6
.github/workflows/api-docs.yml
vendored
@ -28,6 +28,10 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: rhysd/action-setup-vim@v1
|
||||
with:
|
||||
neovim: true
|
||||
version: nightly
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# Fetch depth 0 is required if called through workflow_call. In order
|
||||
@ -38,7 +42,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y doxygen python3 python3-msgpack luajit
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y doxygen python3 python3-msgpack
|
||||
|
||||
- name: Setup git config
|
||||
run: |
|
||||
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -205,6 +205,8 @@ jobs:
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
CI_OS_NAME: ${{ matrix.os }}
|
||||
# TEST_FILE: test/functional/core/startup_spec.lua
|
||||
# TEST_FILTER: foo
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@ -281,6 +283,8 @@ jobs:
|
||||
DEPS_BUILD_DIR: ${{ github.workspace }}/nvim-deps
|
||||
CACHE_NVIM_DEPS_DIR: ${{ github.workspace }}/nvim-deps
|
||||
DEPS_PREFIX: ${{ github.workspace }}/nvim-deps/usr
|
||||
# TEST_FILE: test/functional/core/startup_spec.lua
|
||||
# TEST_FILTER: foo
|
||||
name: windows (MSVC_64)
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -116,10 +116,7 @@ Each pull request must pass the automated builds on [Cirrus CI] and [GitHub Acti
|
||||
|
||||
- CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings
|
||||
will fail the build.
|
||||
- If any tests fail, the build will fail.
|
||||
See [test/README.md#running-tests][run-tests] to run tests locally.
|
||||
Passing locally doesn't guarantee passing the CI build, because of the
|
||||
different compilers and platforms tested against.
|
||||
- If any tests fail, the build will fail. See [test/README.md#running-tests][run-tests] to run tests locally.
|
||||
- CI runs [ASan] and other analyzers.
|
||||
- To run valgrind locally: `VALGRIND=1 make test`
|
||||
- To run Clang ASan/UBSan locally: `CC=clang make CMAKE_FLAGS="-DCLANG_ASAN_UBSAN=ON"`
|
||||
@ -127,6 +124,8 @@ Each pull request must pass the automated builds on [Cirrus CI] and [GitHub Acti
|
||||
neighbors_, to encourage incrementally updating the legacy style to meet our
|
||||
[style](#style). (See [#3174][3174] for background.)
|
||||
- CI for FreeBSD runs on [Cirrus CI].
|
||||
- To see CI results faster in your PR, you can temporarily set `TEST_FILE` in
|
||||
[ci.yml](https://github.com/neovim/neovim/blob/e35b9020b16985eee26e942f9a3f6b045bc3809b/.github/workflows/ci.yml#L205).
|
||||
|
||||
### Clang scan-build
|
||||
|
||||
|
@ -21,15 +21,19 @@ Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
|
||||
which can be used from Lua code (|lua-vimscript| |vim.api|). Together these
|
||||
"namespaces" form the Nvim programming interface.
|
||||
|
||||
See the |lua-guide| for an introduction to using Lua in Neovim.
|
||||
Lua plugins and user config are automatically discovered and loaded, just like
|
||||
Vimscript. See |lua-guide| for practical guidance.
|
||||
|
||||
You can also run Lua scripts from your shell using the |-l| argument: >
|
||||
nvim -l foo.lua [args...]
|
||||
<
|
||||
*lua-compat*
|
||||
Lua 5.1 is the permanent interface for Nvim Lua. Plugins need only consider
|
||||
Lua 5.1, not worry about forward-compatibility with future Lua versions. If
|
||||
Nvim ever ships with Lua 5.4+, a Lua 5.1 compatibility shim will be provided
|
||||
so that old plugins continue to work transparently.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
==============================================================================
|
||||
LUA CONCEPTS AND IDIOMS *lua-concepts*
|
||||
|
||||
Lua is very simple: this means that, while there are some quirks, once you
|
||||
@ -73,25 +77,24 @@ In Lua, any missing arguments are passed as `nil`. Example: >lua
|
||||
Furthermore it is not an error if extra parameters are passed, they are just
|
||||
discarded.
|
||||
|
||||
It is also allowed to omit the parentheses (only) if the function takes
|
||||
exactly one string (`"foo"`) or table literal (`{1,2,3}`). The latter is often
|
||||
used to approximate the "named parameters" feature of languages like Python
|
||||
("kwargs" or "keyword args"). Example: >lua
|
||||
*kwargs*
|
||||
When calling a function, you can omit the parentheses if the function takes
|
||||
exactly one string literal (`"foo"`) or table literal (`{1,2,3}`). The latter
|
||||
is often used to approximate "named parameters" ("kwargs" or "keyword args")
|
||||
as in languages like Python and C#. Example: >lua
|
||||
local func_with_opts = function(opts)
|
||||
local will_do_foo = opts.foo
|
||||
local filename = opts.filename
|
||||
|
||||
...
|
||||
end
|
||||
|
||||
func_with_opts { foo = true, filename = "hello.world" }
|
||||
<
|
||||
There is nothing special going on here except that parentheses are treated as
|
||||
There's nothing special going on here except that parentheses are treated as
|
||||
whitespace. But visually, this small bit of sugar gets reasonably close to
|
||||
a "keyword args" interface.
|
||||
|
||||
It is of course also valid to call the function with parentheses: >lua
|
||||
|
||||
func_with_opts({ foo = true, filename = "hello.world" })
|
||||
<
|
||||
Nvim tends to prefer the keyword args style.
|
||||
@ -100,25 +103,20 @@ Nvim tends to prefer the keyword args style.
|
||||
LUA PATTERNS *lua-patterns*
|
||||
|
||||
Lua intentionally does not support regular expressions, instead it has limited
|
||||
"patterns" which avoid the performance pitfalls of extended regex.
|
||||
|luaref-patterns|
|
||||
"patterns" |luaref-patterns| which avoid the performance pitfalls of extended
|
||||
regex. Lua scripts can also use Vim regex via |vim.regex()|.
|
||||
|
||||
Examples using |string.match()|: >lua
|
||||
These examples use |string.match()| to demonstrate Lua patterns: >lua
|
||||
|
||||
print(string.match("foo123bar123", "%d+"))
|
||||
-- 123
|
||||
|
||||
print(string.match("foo123bar123", "[^%d]+"))
|
||||
-- foo
|
||||
|
||||
print(string.match("foo123bar123", "[abc]+"))
|
||||
-- ba
|
||||
|
||||
print(string.match("foo.bar", "%.bar"))
|
||||
-- .bar
|
||||
|
||||
For more complex matching you can use Vim regex from Lua via |vim.regex()|.
|
||||
|
||||
==============================================================================
|
||||
IMPORTING LUA MODULES *require()* *lua-require*
|
||||
|
||||
@ -389,7 +387,7 @@ For example consider the following Lua omnifunc handler: >lua
|
||||
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc')
|
||||
|
||||
Note: The module ("mymod" in the above example) must either be a Lua global,
|
||||
or use the require syntax as specified above to access it from a package.
|
||||
or use require() as shown above to access it from a package.
|
||||
|
||||
Note: `v:lua` without a call is not allowed in a Vimscript expression:
|
||||
|Funcref|s cannot represent Lua functions. The following are errors: >vim
|
||||
|
@ -57,6 +57,11 @@ The following new APIs or features were added.
|
||||
<
|
||||
(or the Vimscript equivalent) to their |config| file.
|
||||
|
||||
• Run Lua scripts from your shell using |-l|. >
|
||||
nvim -l foo.lua --arg1 --arg2
|
||||
< Also works with stdin: >
|
||||
echo "print(42)" | nvim -l -
|
||||
|
||||
• Added a |vim.lsp.codelens.clear()| function to clear codelenses.
|
||||
|
||||
• |vim.inspect_pos()|, |vim.show_pos()| and |:Inspect| allow a user to get or show items
|
||||
|
@ -9,7 +9,7 @@ Starting Vim *starting*
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Nvim arguments *vim-arguments*
|
||||
Nvim arguments *cli-arguments*
|
||||
|
||||
Most often, Nvim is started to edit a single file with the command: >
|
||||
|
||||
@ -31,8 +31,8 @@ filename One or more file names. The first one will be the current
|
||||
To avoid a file name starting with a '-' being interpreted as
|
||||
an option, precede the arglist with "--", e.g.: >
|
||||
nvim -- -filename
|
||||
< All arguments after the "--" will be interpreted as file names,
|
||||
no other options or "+command" argument can follow.
|
||||
< All arguments after "--" are interpreted as file names, no
|
||||
other options or "+command" arguments can follow.
|
||||
|
||||
*--*
|
||||
`-` Alias for stdin (standard input).
|
||||
@ -143,15 +143,13 @@ argument.
|
||||
these commands, independently from "-c" commands.
|
||||
|
||||
*-S*
|
||||
-S {file} Vimscript or Lua (".lua") {file} will be |:source|d after the
|
||||
first file has been read. Equivalent to: >
|
||||
-S [file] Executes Vimscript or Lua (".lua") [file] after the first file
|
||||
has been read. See also |:source|. If [file] is not given,
|
||||
defaults to "Session.vim". Equivalent to: >
|
||||
-c "source {file}"
|
||||
< Can be repeated like "-c", subject to the same limit of 10
|
||||
"-c" arguments. {file} cannot start with a "-".
|
||||
|
||||
-S Works like "-S Session.vim". Only when used as the last
|
||||
argument or when another "-" option follows.
|
||||
|
||||
-L *-L* *-r*
|
||||
-r Recovery mode. Without a file name argument, a list of
|
||||
existing swap files is given. With a file name, a swap file
|
||||
@ -192,8 +190,9 @@ argument.
|
||||
-E reads stdin as text (into buffer 1).
|
||||
|
||||
-es *-es* *-Es* *-s-ex* *silent-mode*
|
||||
-Es Silent mode (no UI), for scripting. Unrelated to |-s|.
|
||||
Disables most prompts, messages, warnings and errors.
|
||||
-Es Script mode, aka "silent mode", aka "batch mode". No UI,
|
||||
disables most prompts and messages. Unrelated to |-s|.
|
||||
See also |-S| to run script files.
|
||||
|
||||
-es reads/executes stdin as Ex commands. >
|
||||
printf "put ='foo'\n%%print\n" | nvim -es
|
||||
@ -211,10 +210,37 @@ argument.
|
||||
nvim -es +":verbose echo 'foo'"
|
||||
nvim -V1 -es +foo
|
||||
|
||||
< User |config| is skipped (unless given with |-u|).
|
||||
< User |config| is skipped unless |-u| was given.
|
||||
Swap file is skipped (like |-n|).
|
||||
User |shada| is loaded (unless "-i NONE" is given).
|
||||
|
||||
*-l*
|
||||
-l {script} [args]
|
||||
Executes Lua {script} non-interactively (no UI) with optional
|
||||
[args] after processing any preceding Nvim |cli-arguments|,
|
||||
then exits. See |-S| to run multiple Lua scripts without args,
|
||||
or in an interactive session.
|
||||
*lua-args*
|
||||
All [args] are treated as {script} arguments and passed
|
||||
literally to Lua (in the conventional `_G.arg` global table),
|
||||
thus "-l" ends processing of Nvim arguments.
|
||||
|
||||
Exits with code 1 on Lua error.
|
||||
|
||||
Sets 'verbose' to 1 (like "-V1"), so Lua `print()` writes to
|
||||
output.
|
||||
|
||||
Arguments before "-l" are processed before executing {script}.
|
||||
This example quits before executing "foo.lua": >
|
||||
nvim +q -l foo.lua
|
||||
< This loads Lua module "bar" before executing "foo.lua": >
|
||||
nvim +"lua require('bar')" -l foo.lua
|
||||
<
|
||||
Skips user |config| unless |-u| was given.
|
||||
Disables plugins unless 'loadplugins' was set.
|
||||
Disables |shada| unless |-i| was given.
|
||||
Disables swapfile (like |-n|).
|
||||
|
||||
*-b*
|
||||
-b Binary mode. File I/O will only recognize <NL> to separate
|
||||
lines. The 'expandtab' option will be reset. The 'textwidth'
|
||||
@ -222,9 +248,6 @@ argument.
|
||||
is set. This is done after reading the |vimrc| but before
|
||||
reading any file in the arglist. See also |edit-binary|.
|
||||
|
||||
*-l*
|
||||
-l Lisp mode. Sets the 'lisp' and 'showmatch' options on.
|
||||
|
||||
*-A*
|
||||
-A Arabic mode. Sets the 'arabic' option on.
|
||||
|
||||
@ -239,10 +262,10 @@ argument.
|
||||
Example: >
|
||||
nvim -V8
|
||||
|
||||
-V[N]{filename}
|
||||
Like -V and set 'verbosefile' to {filename}. Messages are not
|
||||
displayed; instead they are written to the file {filename}.
|
||||
{filename} must not start with a digit.
|
||||
-V[N]{file}
|
||||
Like -V and sets 'verbosefile' to {file} (must not start with
|
||||
a digit). Messages are not displayed, instead they are
|
||||
written to {file}.
|
||||
Example: >
|
||||
nvim -V20vimlog
|
||||
<
|
||||
|
@ -55,11 +55,19 @@ if sys.version_info < MIN_PYTHON_VERSION:
|
||||
doxygen_version = tuple((int(i) for i in subprocess.check_output(["doxygen", "-v"],
|
||||
universal_newlines=True).split()[0].split('.')))
|
||||
|
||||
# Until 0.9 is released, need this hacky way to check that "nvim -l foo.lua" works.
|
||||
nvim_version = list(line for line in subprocess.check_output(['nvim', '-h'], universal_newlines=True).split('\n')
|
||||
if '-l ' in line)
|
||||
|
||||
if doxygen_version < MIN_DOXYGEN_VERSION:
|
||||
print("\nRequires doxygen {}.{}.{}+".format(*MIN_DOXYGEN_VERSION))
|
||||
print("Your doxygen version is {}.{}.{}\n".format(*doxygen_version))
|
||||
sys.exit(1)
|
||||
|
||||
if len(nvim_version) == 0:
|
||||
print("\nRequires 'nvim -l' feature, see https://github.com/neovim/neovim/pull/18706")
|
||||
sys.exit(1)
|
||||
|
||||
# DEBUG = ('DEBUG' in os.environ)
|
||||
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
|
||||
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
|
||||
@ -79,7 +87,7 @@ base_dir = os.path.dirname(os.path.dirname(script_path))
|
||||
out_dir = os.path.join(base_dir, 'tmp-{target}-doc')
|
||||
filter_cmd = '%s %s' % (sys.executable, script_path)
|
||||
msgs = [] # Messages to show on exit.
|
||||
lua2dox_filter = os.path.join(base_dir, 'scripts', 'lua2dox_filter')
|
||||
lua2dox = os.path.join(base_dir, 'scripts', 'lua2dox.lua')
|
||||
|
||||
CONFIG = {
|
||||
'api': {
|
||||
@ -993,7 +1001,7 @@ def delete_lines_below(filename, tokenstr):
|
||||
fp.writelines(lines[0:i])
|
||||
|
||||
|
||||
def main(config, args):
|
||||
def main(doxygen_config, args):
|
||||
"""Generates:
|
||||
|
||||
1. Vim :help docs
|
||||
@ -1021,7 +1029,7 @@ def main(config, args):
|
||||
# runtime/lua/vim/lsp.lua:209: warning: argument 'foo' not found
|
||||
stderr=(subprocess.STDOUT if debug else subprocess.DEVNULL))
|
||||
p.communicate(
|
||||
config.format(
|
||||
doxygen_config.format(
|
||||
input=' '.join(
|
||||
[f'"{file}"' for file in CONFIG[target]['files']]),
|
||||
output=output_dir,
|
||||
@ -1108,11 +1116,7 @@ def main(config, args):
|
||||
fn_map_full.update(fn_map)
|
||||
|
||||
if len(sections) == 0:
|
||||
if target == 'lua':
|
||||
fail(f'no sections for target: {target} (this usually means'
|
||||
+ ' "luajit" was not found by scripts/lua2dox_filter)')
|
||||
else:
|
||||
fail(f'no sections for target: {target}')
|
||||
fail(f'no sections for target: {target} (look for errors near "Preprocessing" log lines above)')
|
||||
if len(sections) > len(CONFIG[target]['section_order']):
|
||||
raise RuntimeError(
|
||||
'found new modules "{}"; update the "section_order" map'.format(
|
||||
@ -1159,7 +1163,7 @@ def main(config, args):
|
||||
def filter_source(filename):
|
||||
name, extension = os.path.splitext(filename)
|
||||
if extension == '.lua':
|
||||
p = subprocess.run([lua2dox_filter, filename], stdout=subprocess.PIPE)
|
||||
p = subprocess.run(['nvim', '-l', lua2dox, filename], stdout=subprocess.PIPE)
|
||||
op = ('?' if 0 != p.returncode else p.stdout.decode('utf-8'))
|
||||
print(op)
|
||||
else:
|
||||
|
@ -27,14 +27,13 @@ http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm
|
||||
Running
|
||||
-------
|
||||
|
||||
This file "lua2dox.lua" gets called by "lua2dox_filter" (bash).
|
||||
This script "lua2dox.lua" gets called by "gen_vimdoc.py".
|
||||
|
||||
Doxygen must be on your system. You can experiment like so:
|
||||
|
||||
- Run "doxygen -g" to create a default Doxyfile.
|
||||
- Then alter it to let it recognise lua. Add the two following lines:
|
||||
- Then alter it to let it recognise lua. Add the following line:
|
||||
FILE_PATTERNS = *.lua
|
||||
FILTER_PATTERNS = *.lua=lua2dox_filter
|
||||
- Then run "doxygen".
|
||||
|
||||
The core function reads the input file (filename or stdin) and outputs some pseudo C-ish language.
|
||||
@ -117,26 +116,6 @@ local function string_split(Str, Pattern)
|
||||
return splitStr
|
||||
end
|
||||
|
||||
--! \class TCore_Commandline
|
||||
--! \brief reads/parses commandline
|
||||
local TCore_Commandline = class()
|
||||
|
||||
--! \brief constructor
|
||||
function TCore_Commandline.init(this)
|
||||
this.argv = arg
|
||||
this.parsed = {}
|
||||
this.params = {}
|
||||
end
|
||||
|
||||
--! \brief get value
|
||||
function TCore_Commandline.getRaw(this, Key, Default)
|
||||
local val = this.argv[Key]
|
||||
if not val then
|
||||
val = Default
|
||||
end
|
||||
return val
|
||||
end
|
||||
|
||||
-------------------------------
|
||||
--! \brief file buffer
|
||||
--!
|
||||
@ -147,7 +126,7 @@ local TStream_Read = class()
|
||||
--!
|
||||
--! \param Filename name of file to read (or nil == stdin)
|
||||
function TStream_Read.getContents(this, Filename)
|
||||
assert(Filename)
|
||||
assert(Filename, ('invalid file: %s'):format(Filename))
|
||||
-- get lines from file
|
||||
-- syphon lines to our table
|
||||
local filecontents = {}
|
||||
@ -548,15 +527,14 @@ end
|
||||
local This_app = TApp()
|
||||
|
||||
--main
|
||||
local cl = TCore_Commandline()
|
||||
|
||||
local argv1 = cl:getRaw(2)
|
||||
local argv1 = arg[1]
|
||||
if argv1 == '--help' then
|
||||
TCore_IO_writeln(This_app:getVersion())
|
||||
TCore_IO_writeln(This_app:getCopyright())
|
||||
TCore_IO_writeln([[
|
||||
run as:
|
||||
lua2dox_filter <param>
|
||||
nvim -l scripts/lua2dox.lua <param>
|
||||
--------------
|
||||
Param:
|
||||
<filename> : interprets filename
|
||||
|
@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
###########################################################################
|
||||
# Copyright (C) 2012 by Simon Dales #
|
||||
# simon@purrsoft.co.uk #
|
||||
# #
|
||||
# This program is free software; you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation; either version 2 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program; if not, write to the #
|
||||
# Free Software Foundation, Inc., #
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
|
||||
###########################################################################
|
||||
LANG=""
|
||||
|
||||
##! \brief test executable to see if it exists
|
||||
test_executable() {
|
||||
P_EXE="$1"
|
||||
#########
|
||||
WHICH=$(which "$P_EXE")
|
||||
if test -z "${WHICH}"; then
|
||||
echo "not found \"${P_EXE}\""
|
||||
else
|
||||
EXE="${P_EXE}"
|
||||
fi
|
||||
}
|
||||
|
||||
##! \brief sets the lua interpreter
|
||||
set_lua() {
|
||||
if test -z "${EXE}"; then
|
||||
test_executable '.deps/usr/bin/luajit'
|
||||
fi
|
||||
|
||||
if test -z "${EXE}"; then
|
||||
test_executable 'luajit'
|
||||
fi
|
||||
|
||||
if test -z "${EXE}"; then
|
||||
test_executable 'lua'
|
||||
fi
|
||||
}
|
||||
|
||||
##! \brief makes canonical name of file
|
||||
##!
|
||||
##! Note that "readlink -f" doesn't work in MacOSX
|
||||
##!
|
||||
do_readlink() {
|
||||
pushd . > /dev/null
|
||||
TARGET_FILE=$1
|
||||
|
||||
cd "$(dirname $TARGET_FILE)"
|
||||
TARGET_FILE=$(basename "$TARGET_FILE")
|
||||
|
||||
# Iterate down a (possible) chain of symlinks
|
||||
while [ -L "$TARGET_FILE" ]; do
|
||||
TARGET_FILE=$(readlink "$TARGET_FILE")
|
||||
cd $(dirname "$TARGET_FILE")
|
||||
TARGET_FILE=$(basename "$TARGET_FILE")
|
||||
done
|
||||
|
||||
PHYS_DIR=$(pwd -P)
|
||||
RESULT=$PHYS_DIR
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
##main
|
||||
set_lua
|
||||
if test -z "${EXE}"; then
|
||||
echo "no lua interpreter found"
|
||||
exit 1
|
||||
else
|
||||
BASENAME=$(basename "$0")
|
||||
do_readlink "$0"
|
||||
DIRNAME="${RESULT}"
|
||||
|
||||
LUASCRIPT="${DIRNAME}/lua2dox.lua ${BASENAME}"
|
||||
#echo "lua[${LUASCRIPT}]"
|
||||
|
||||
${EXE} ${LUASCRIPT} $@
|
||||
fi
|
||||
|
||||
##eof
|
2566
src/Doxyfile
2566
src/Doxyfile
File diff suppressed because it is too large
Load Diff
@ -122,9 +122,6 @@ modifications.
|
||||
.It Fl b
|
||||
Binary mode.
|
||||
.Ic ":help edit-binary"
|
||||
.It Fl l
|
||||
Lisp mode.
|
||||
Sets the 'lisp' and 'showmatch' options.
|
||||
.It Fl A
|
||||
Arabic mode.
|
||||
Sets the 'arabic' option.
|
||||
@ -144,7 +141,7 @@ is specified, append messages to
|
||||
instead of printing them.
|
||||
.Ic ":help 'verbose'"
|
||||
.It Fl D
|
||||
Debug mode for VimL (Vim script).
|
||||
Vimscript debug mode.
|
||||
Started when executing the first command from a script.
|
||||
:help debug-mode
|
||||
.It Fl n
|
||||
@ -268,10 +265,26 @@ but execute
|
||||
before processing any vimrc.
|
||||
Up to 10 instances of these can be used independently from instances of
|
||||
.Fl c .
|
||||
.It Fl l Ar script Op Ar args
|
||||
Execute Lua
|
||||
.Ar script
|
||||
with optional
|
||||
.Op Ar args
|
||||
after processing any preceding Nvim startup arguments.
|
||||
All
|
||||
.Op Ar args
|
||||
are treated as script arguments and are passed literally to Lua, that is,
|
||||
.Fl l
|
||||
stops processing of Nvim arguments.
|
||||
.Ic ":help -l"
|
||||
.It Fl S Op Ar session
|
||||
Source
|
||||
Execute
|
||||
.Ar session
|
||||
after the first file argument has been read.
|
||||
after the first file argument has been read. If
|
||||
.Ar session
|
||||
filename ends with
|
||||
.Pa .lua
|
||||
it is executed as Lua instead of Vimscript.
|
||||
Equivalent to
|
||||
.Cm -c \(dqsource session\(dq .
|
||||
.Ar session
|
||||
|
@ -18,6 +18,12 @@ The source files use extensions to hint about their purpose.
|
||||
- `*.h.generated.h` - exported functions’ declarations.
|
||||
- `*.c.generated.h` - static functions’ declarations.
|
||||
|
||||
Common structures
|
||||
-----------------
|
||||
|
||||
- StringBuilder
|
||||
- kvec or garray.c for dynamic lists / vectors (use StringBuilder for strings)
|
||||
|
||||
Logs
|
||||
----
|
||||
|
||||
|
@ -515,7 +515,7 @@ EXTERN int allbuf_lock INIT(= 0);
|
||||
/// not allowed then.
|
||||
EXTERN int sandbox INIT(= 0);
|
||||
|
||||
/// Batch-mode: "-es" or "-Es" commandline argument was given.
|
||||
/// Batch-mode: "-es", "-Es", "-l" commandline argument was given.
|
||||
EXTERN int silent_mode INIT(= false);
|
||||
|
||||
/// Start position of active Visual selection.
|
||||
@ -1042,7 +1042,7 @@ EXTERN int vim_ignored;
|
||||
|
||||
// stdio is an RPC channel (--embed).
|
||||
EXTERN bool embedded_mode INIT(= false);
|
||||
// Do not start a UI nor read/write to stdio (unless embedding).
|
||||
// Do not start UI (--headless, -l) nor read/write to stdio (unless embedding).
|
||||
EXTERN bool headless_mode INIT(= false);
|
||||
|
||||
// uncrustify:on
|
||||
|
@ -323,6 +323,30 @@ static int nlua_thr_api_nvim__get_runtime(lua_State *lstate)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Copies args starting at `lua_arg0` into the Lua `arg` global.
|
||||
///
|
||||
/// Example (`lua_arg0` points to "--arg1"):
|
||||
/// nvim -l foo.lua --arg1 --arg2
|
||||
///
|
||||
/// @note Lua CLI sets arguments upto "-e" as _negative_ `_G.arg` indices, but we currently don't
|
||||
/// follow that convention.
|
||||
///
|
||||
/// @see https://www.lua.org/pil/1.4.html
|
||||
/// @see https://github.com/premake/premake-core/blob/1c1304637f4f5e50ba8c57aae8d1d80ec3b7aaf2/src/host/premake.c#L563-L594
|
||||
///
|
||||
/// @returns number of args
|
||||
static int nlua_init_argv(lua_State *const L, char **argv, int argc, int lua_arg0)
|
||||
{
|
||||
lua_newtable(L); // _G.arg
|
||||
int i = 0;
|
||||
for (; lua_arg0 >= 0 && i + lua_arg0 < argc; i++) {
|
||||
lua_pushstring(L, argv[i + lua_arg0]);
|
||||
lua_rawseti(L, -2, i + 1); // _G.arg[i+1] = "arg1"
|
||||
}
|
||||
lua_setglobal(L, "arg");
|
||||
return i;
|
||||
}
|
||||
|
||||
static void nlua_schedule_event(void **argv)
|
||||
{
|
||||
LuaRef cb = (LuaRef)(ptrdiff_t)argv[0];
|
||||
@ -765,10 +789,8 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Initialize global lua interpreter
|
||||
///
|
||||
/// Crashes Nvim if initialization fails.
|
||||
void nlua_init(void)
|
||||
/// Initializes global Lua interpreter, or exits Nvim on failure.
|
||||
void nlua_init(char **argv, int argc, int lua_arg0)
|
||||
{
|
||||
#ifdef NLUA_TRACK_REFS
|
||||
const char *env = os_getenv("NVIM_LUA_NOTRACK");
|
||||
@ -789,10 +811,9 @@ void nlua_init(void)
|
||||
}
|
||||
|
||||
luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem);
|
||||
|
||||
global_lstate = lstate;
|
||||
|
||||
main_thread = uv_thread_self();
|
||||
nlua_init_argv(lstate, argv, argc, lua_arg0);
|
||||
}
|
||||
|
||||
static lua_State *nlua_thread_acquire_vm(void)
|
||||
@ -1686,21 +1707,49 @@ void ex_luafile(exarg_T *const eap)
|
||||
nlua_exec_file((const char *)eap->arg);
|
||||
}
|
||||
|
||||
/// execute lua code from a file.
|
||||
/// Executes Lua code from a file or "-" (stdin).
|
||||
///
|
||||
/// Note: we call the lua global loadfile as opposed to calling luaL_loadfile
|
||||
/// in case loadfile has been overridden in the users environment.
|
||||
/// Calls the Lua `loadfile` global as opposed to `luaL_loadfile` in case `loadfile` was overridden
|
||||
/// in the user environment.
|
||||
///
|
||||
/// @param path path of the file
|
||||
/// @param path Path to the file, may be "-" (stdin) during startup.
|
||||
///
|
||||
/// @return true if everything ok, false if there was an error (echoed)
|
||||
/// @return true on success, false on error (echoed) or user canceled (CTRL-c) while reading "-"
|
||||
/// (stdin).
|
||||
bool nlua_exec_file(const char *path)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
lua_State *const lstate = global_lstate;
|
||||
if (!strequal(path, "-")) {
|
||||
lua_getglobal(lstate, "loadfile");
|
||||
lua_pushstring(lstate, path);
|
||||
} else {
|
||||
FileDescriptor *stdin_dup = file_open_stdin();
|
||||
|
||||
lua_getglobal(lstate, "loadfile");
|
||||
lua_pushstring(lstate, path);
|
||||
StringBuilder sb = KV_INITIAL_VALUE;
|
||||
kv_resize(sb, 64);
|
||||
ptrdiff_t read_size = -1;
|
||||
// Read all input from stdin, unless interrupted (ctrl-c).
|
||||
while (true) {
|
||||
if (got_int) { // User canceled.
|
||||
return false;
|
||||
}
|
||||
read_size = file_read(stdin_dup, IObuff, 64);
|
||||
if (read_size < 0) { // Error.
|
||||
return false;
|
||||
}
|
||||
kv_concat_len(sb, IObuff, (size_t)read_size);
|
||||
if (read_size < 64) { // EOF.
|
||||
break;
|
||||
}
|
||||
}
|
||||
kv_push(sb, NUL);
|
||||
file_free(stdin_dup, false);
|
||||
|
||||
lua_getglobal(lstate, "loadstring");
|
||||
lua_pushstring(lstate, sb.items);
|
||||
kv_destroy(sb);
|
||||
}
|
||||
|
||||
if (nlua_pcall(lstate, 1, 2)) {
|
||||
nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
|
||||
|
@ -279,8 +279,7 @@ int main(int argc, char **argv)
|
||||
// argument list "global_alist".
|
||||
command_line_scan(¶ms);
|
||||
|
||||
nlua_init();
|
||||
|
||||
nlua_init(argv, argc, params.lua_arg0);
|
||||
TIME_MSG("init lua interpreter");
|
||||
|
||||
if (embedded_mode) {
|
||||
@ -363,8 +362,7 @@ int main(int argc, char **argv)
|
||||
debug_break_level = params.use_debug_break_level;
|
||||
|
||||
// Read ex-commands if invoked with "-es".
|
||||
if (!params.input_isatty && !params.input_neverscript
|
||||
&& silent_mode && exmode_active) {
|
||||
if (!params.input_isatty && !params.input_istext && silent_mode && exmode_active) {
|
||||
input_start(STDIN_FILENO);
|
||||
}
|
||||
|
||||
@ -409,14 +407,12 @@ int main(int argc, char **argv)
|
||||
init_default_autocmds();
|
||||
TIME_MSG("init default autocommands");
|
||||
|
||||
bool vimrc_none = params.use_vimrc != NULL && strequal(params.use_vimrc, "NONE");
|
||||
bool vimrc_none = strequal(params.use_vimrc, "NONE");
|
||||
|
||||
// Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
|
||||
// Allows for setting 'loadplugins' there.
|
||||
if (vimrc_none) {
|
||||
// When using --clean we still want to load plugins
|
||||
p_lpl = params.clean;
|
||||
}
|
||||
// For --clean we still want to load plugins.
|
||||
p_lpl = vimrc_none ? params.clean : p_lpl;
|
||||
|
||||
// Execute --cmd arguments.
|
||||
exe_pre_commands(¶ms);
|
||||
@ -610,6 +606,12 @@ int main(int argc, char **argv)
|
||||
(void)eval_has_provider("clipboard");
|
||||
}
|
||||
|
||||
if (params.luaf != NULL) {
|
||||
bool lua_ok = nlua_exec_file(params.luaf);
|
||||
TIME_MSG("executing Lua -l script");
|
||||
getout(lua_ok ? 0 : 1);
|
||||
}
|
||||
|
||||
TIME_MSG("before starting main loop");
|
||||
ILOG("starting main loop");
|
||||
|
||||
@ -657,9 +659,8 @@ void getout(int exitval)
|
||||
{
|
||||
exiting = true;
|
||||
|
||||
// When running in Ex mode an error causes us to exit with a non-zero exit
|
||||
// code. POSIX requires this, although it's not 100% clear from the
|
||||
// standard.
|
||||
// On error during Ex mode, exit with a non-zero code.
|
||||
// POSIX requires this, although it's not 100% clear from the standard.
|
||||
if (exmode_active) {
|
||||
exitval += ex_exitval;
|
||||
}
|
||||
@ -750,6 +751,7 @@ void getout(int exitval)
|
||||
if (did_emsg) {
|
||||
// give the user a chance to read the (error) message
|
||||
no_wait_return = false;
|
||||
// TODO(justinmk): this may call getout(0), clobbering exitval...
|
||||
wait_return(false);
|
||||
}
|
||||
|
||||
@ -773,10 +775,9 @@ void getout(int exitval)
|
||||
os_exit(exitval);
|
||||
}
|
||||
|
||||
/// Preserve files and exit.
|
||||
/// @note IObuff must contain a message.
|
||||
/// @note This may be called from deadly_signal() in a signal handler, avoid
|
||||
/// unsafe functions, such as allocating memory.
|
||||
/// Preserve files, print contents of `IObuff`, and exit 1.
|
||||
///
|
||||
/// May be called from deadly_signal().
|
||||
void preserve_exit(void)
|
||||
FUNC_ATTR_NORETURN
|
||||
{
|
||||
@ -962,7 +963,7 @@ static bool edit_stdin(mparm_T *parmp)
|
||||
{
|
||||
bool implicit = !headless_mode
|
||||
&& !(embedded_mode && stdin_fd <= 0)
|
||||
&& (!exmode_active || parmp->input_neverscript)
|
||||
&& (!exmode_active || parmp->input_istext)
|
||||
&& !parmp->input_isatty
|
||||
&& parmp->scriptin == NULL; // `-s -` was not given.
|
||||
return parmp->had_stdin_file || implicit;
|
||||
@ -993,9 +994,9 @@ static void command_line_scan(mparm_T *parmp)
|
||||
} else {
|
||||
parmp->commands[parmp->n_commands++] = &(argv[0][1]);
|
||||
}
|
||||
|
||||
// Optional argument.
|
||||
} else if (argv[0][0] == '-' && !had_minmin) {
|
||||
// Optional argument.
|
||||
|
||||
want_argument = false;
|
||||
char c = argv[0][argv_idx++];
|
||||
switch (c) {
|
||||
@ -1005,9 +1006,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
silent_mode = true;
|
||||
parmp->no_swap_file = true;
|
||||
} else {
|
||||
if (parmp->edit_type != EDIT_NONE
|
||||
&& parmp->edit_type != EDIT_FILE
|
||||
&& parmp->edit_type != EDIT_STDIN) {
|
||||
if (parmp->edit_type > EDIT_STDIN) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
}
|
||||
parmp->had_stdin_file = true;
|
||||
@ -1015,7 +1014,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
}
|
||||
argv_idx = -1; // skip to next argument
|
||||
break;
|
||||
case '-': // "--" don't take any more option arguments
|
||||
case '-': // "--" No more option arguments.
|
||||
// "--help" give help message
|
||||
// "--version" give version message
|
||||
// "--noplugin[s]" skip plugins
|
||||
@ -1111,7 +1110,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
case 'E': // "-E" Ex mode
|
||||
exmode_active = true;
|
||||
parmp->input_neverscript = true;
|
||||
parmp->input_istext = true;
|
||||
break;
|
||||
case 'f': // "-f" GUI: run in foreground.
|
||||
break;
|
||||
@ -1123,10 +1122,6 @@ static void command_line_scan(mparm_T *parmp)
|
||||
p_hkmap = true;
|
||||
set_option_value_give_err("rl", 1L, NULL, 0);
|
||||
break;
|
||||
case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on.
|
||||
set_option_value_give_err("lisp", 1L, NULL, 0);
|
||||
p_sm = true;
|
||||
break;
|
||||
case 'M': // "-M" no changes or writing of files
|
||||
reset_modifiable();
|
||||
FALLTHROUGH;
|
||||
@ -1231,6 +1226,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
FALLTHROUGH;
|
||||
case 'S': // "-S {file}" execute Vim script
|
||||
case 'i': // "-i {shada}" use for ShaDa file
|
||||
case 'l': // "-l {file}" Lua mode
|
||||
case 'u': // "-u {vimrc}" vim inits file
|
||||
case 'U': // "-U {gvimrc}" gvim inits file
|
||||
case 'W': // "-W {scriptout}" overwrite
|
||||
@ -1311,6 +1307,23 @@ static void command_line_scan(mparm_T *parmp)
|
||||
set_option_value_give_err("shadafile", 0L, argv[0], 0);
|
||||
break;
|
||||
|
||||
case 'l': // "-l" Lua script: args after "-l".
|
||||
headless_mode = true;
|
||||
silent_mode = true;
|
||||
p_verbose = 1;
|
||||
parmp->no_swap_file = true;
|
||||
parmp->use_vimrc = parmp->use_vimrc ? parmp->use_vimrc : "NONE";
|
||||
if (p_shadafile == NULL || *p_shadafile == NUL) {
|
||||
set_option_value_give_err("shadafile", 0L, "NONE", 0);
|
||||
}
|
||||
parmp->luaf = argv[0];
|
||||
argc--;
|
||||
if (argc > 0) { // Lua args after "-l <file>".
|
||||
parmp->lua_arg0 = parmp->argc - argc;
|
||||
argc = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': // "-s {scriptin}" read from script file
|
||||
if (parmp->scriptin != NULL) {
|
||||
scripterror:
|
||||
@ -1354,9 +1367,7 @@ scripterror:
|
||||
argv_idx = -1; // skip to next argument
|
||||
|
||||
// Check for only one type of editing.
|
||||
if (parmp->edit_type != EDIT_NONE
|
||||
&& parmp->edit_type != EDIT_FILE
|
||||
&& parmp->edit_type != EDIT_STDIN) {
|
||||
if (parmp->edit_type > EDIT_STDIN) {
|
||||
mainerr(err_too_many_args, argv[0]);
|
||||
}
|
||||
parmp->edit_type = EDIT_FILE;
|
||||
@ -1392,8 +1403,8 @@ scripterror:
|
||||
}
|
||||
}
|
||||
|
||||
if (embedded_mode && silent_mode) {
|
||||
mainerr(_("--embed conflicts with -es/-Es"), NULL);
|
||||
if (embedded_mode && (silent_mode || parmp->luaf)) {
|
||||
mainerr(_("--embed conflicts with -es/-Es/-l"), NULL);
|
||||
}
|
||||
|
||||
// If there is a "+123" or "-c" command, set v:swapcommand to the first one.
|
||||
@ -1421,6 +1432,8 @@ static void init_params(mparm_T *paramp, int argc, char **argv)
|
||||
paramp->listen_addr = NULL;
|
||||
paramp->server_addr = NULL;
|
||||
paramp->remote = 0;
|
||||
paramp->luaf = NULL;
|
||||
paramp->lua_arg0 = -1;
|
||||
}
|
||||
|
||||
/// Initialize global startuptime file if "--startuptime" passed as an argument.
|
||||
@ -1554,19 +1567,7 @@ static void open_script_files(mparm_T *parmp)
|
||||
if (parmp->scriptin) {
|
||||
int error;
|
||||
if (strequal(parmp->scriptin, "-")) {
|
||||
int stdin_dup_fd;
|
||||
if (stdin_fd > 0) {
|
||||
stdin_dup_fd = stdin_fd;
|
||||
} else {
|
||||
stdin_dup_fd = os_dup(STDIN_FILENO);
|
||||
#ifdef MSWIN
|
||||
// Replace the original stdin with the console input handle.
|
||||
os_replace_stdin_to_conin();
|
||||
#endif
|
||||
}
|
||||
FileDescriptor *const stdin_dup = file_open_fd_new(&error, stdin_dup_fd,
|
||||
kFileReadOnly|kFileNonBlocking);
|
||||
assert(stdin_dup != NULL);
|
||||
FileDescriptor *stdin_dup = file_open_stdin();
|
||||
scriptin[0] = stdin_dup;
|
||||
} else {
|
||||
scriptin[0] = file_open_new(&error, parmp->scriptin,
|
||||
@ -2133,7 +2134,7 @@ static void mainerr(const char *errstr, const char *str)
|
||||
static void version(void)
|
||||
{
|
||||
// TODO(bfred): not like this?
|
||||
nlua_init();
|
||||
nlua_init(NULL, 0, -1);
|
||||
info_message = true; // use os_msg(), not os_errmsg()
|
||||
list_version();
|
||||
msg_putchar('\n');
|
||||
@ -2154,6 +2155,7 @@ static void usage(void)
|
||||
os_msg(_(" + Start at end of file\n"));
|
||||
os_msg(_(" --cmd <cmd> Execute <cmd> before any config\n"));
|
||||
os_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n"));
|
||||
os_msg(_(" -l <script> [args...] Execute Lua <script> (with optional args)\n"));
|
||||
os_msg("\n");
|
||||
os_msg(_(" -b Binary mode\n"));
|
||||
os_msg(_(" -d Diff mode\n"));
|
||||
|
@ -23,15 +23,18 @@ typedef struct {
|
||||
char cmds_tofree[MAX_ARG_CMDS]; // commands that need free()
|
||||
int n_pre_commands; // no. of commands from --cmd
|
||||
char *pre_commands[MAX_ARG_CMDS]; // commands from --cmd argument
|
||||
char *luaf; // Lua script filename from "-l"
|
||||
int lua_arg0; // Lua script args start index.
|
||||
|
||||
int edit_type; // type of editing to do
|
||||
char *tagname; // tag from -t argument
|
||||
char *use_ef; // 'errorfile' from -q argument
|
||||
|
||||
bool input_isatty; // stdin is a terminal
|
||||
bool input_istext; // stdin is text, not executable (-E/-Es)
|
||||
bool output_isatty; // stdout is a terminal
|
||||
bool err_isatty; // stderr is a terminal
|
||||
bool input_neverscript; // never treat stdin as script (-E/-Es)
|
||||
|
||||
int no_swap_file; // "-n" argument used
|
||||
int use_debug_break_level;
|
||||
int window_count; // number of windows to use
|
||||
|
@ -3003,31 +3003,36 @@ static int do_more_prompt(int typed_char)
|
||||
}
|
||||
|
||||
#if defined(MSWIN)
|
||||
void os_errmsg(char *str)
|
||||
/// Headless (no UI) error message handler.
|
||||
static void do_msg(char *str, bool errmsg)
|
||||
{
|
||||
static bool did_err = false;
|
||||
assert(str != NULL);
|
||||
wchar_t *utf16str;
|
||||
int r = utf8_to_utf16(str, -1, &utf16str);
|
||||
if (r != 0) {
|
||||
if (r != 0 && !did_err) {
|
||||
did_err = true;
|
||||
fprintf(stderr, "utf8_to_utf16 failed: %d", r);
|
||||
} else {
|
||||
fwprintf(stderr, L"%ls", utf16str);
|
||||
ELOG("utf8_to_utf16 failed: %d", r);
|
||||
} else if (r == 0) {
|
||||
if (errmsg) {
|
||||
fwprintf(stderr, L"%ls", utf16str);
|
||||
} else {
|
||||
wprintf(L"%ls", utf16str);
|
||||
}
|
||||
xfree(utf16str);
|
||||
}
|
||||
}
|
||||
|
||||
/// Give a message. To be used when the UI is not initialized yet.
|
||||
void os_errmsg(char *str)
|
||||
{
|
||||
do_msg(str, true);
|
||||
}
|
||||
|
||||
/// Headless (no UI) message handler.
|
||||
void os_msg(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
wchar_t *utf16str;
|
||||
int r = utf8_to_utf16(str, -1, &utf16str);
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "utf8_to_utf16 failed: %d", r);
|
||||
} else {
|
||||
wprintf(L"%ls", utf16str);
|
||||
xfree(utf16str);
|
||||
}
|
||||
do_msg(str, false);
|
||||
}
|
||||
#endif // MSWIN
|
||||
|
||||
|
@ -167,6 +167,30 @@ FileDescriptor *file_open_fd_new(int *const error, const int fd, const int flags
|
||||
return fp;
|
||||
}
|
||||
|
||||
/// Opens standard input as a FileDescriptor.
|
||||
FileDescriptor *file_open_stdin(void)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
int error;
|
||||
int stdin_dup_fd;
|
||||
if (stdin_fd > 0) {
|
||||
stdin_dup_fd = stdin_fd;
|
||||
} else {
|
||||
stdin_dup_fd = os_dup(STDIN_FILENO);
|
||||
#ifdef MSWIN
|
||||
// Replace the original stdin with the console input handle.
|
||||
os_replace_stdin_to_conin();
|
||||
#endif
|
||||
}
|
||||
FileDescriptor *const stdin_dup = file_open_fd_new(&error, stdin_dup_fd,
|
||||
kFileReadOnly|kFileNonBlocking);
|
||||
assert(stdin_dup != NULL);
|
||||
if (error != 0) {
|
||||
ELOG("failed to open stdin: %s", os_strerror(error));
|
||||
}
|
||||
return stdin_dup;
|
||||
}
|
||||
|
||||
/// Close file and free its buffer
|
||||
///
|
||||
/// @param[in,out] fp File to close.
|
||||
|
@ -962,6 +962,7 @@ endfunc
|
||||
|
||||
" Test for enabling the lisp mode on startup
|
||||
func Test_l_arg()
|
||||
throw 'Skipped: Nvim -l arg differs from Vim'
|
||||
let after =<< trim [CODE]
|
||||
let s = 'lisp=' .. &lisp .. ', showmatch=' .. &showmatch
|
||||
call writefile([s], 'Xtestout')
|
||||
|
@ -245,12 +245,10 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
|
||||
/// plus six following composing characters of three bytes each.
|
||||
#define MB_MAXBYTES 21
|
||||
|
||||
// This has to go after the include of proto.h, as proto/gui.pro declares
|
||||
// functions of these names. The declarations would break if the defines had
|
||||
// been seen at that stage. But it must be before globals.h, where error_ga
|
||||
// is declared.
|
||||
#ifndef MSWIN
|
||||
/// Headless (no UI) error message handler.
|
||||
# define os_errmsg(str) fprintf(stderr, "%s", (str))
|
||||
/// Headless (no UI) message handler.
|
||||
# define os_msg(str) printf("%s", (str))
|
||||
#endif
|
||||
|
||||
|
@ -26,6 +26,7 @@ local write_file = helpers.write_file
|
||||
local meths = helpers.meths
|
||||
local alter_slashes = helpers.alter_slashes
|
||||
local is_os = helpers.is_os
|
||||
local dedent = helpers.dedent
|
||||
|
||||
local testfile = 'Xtest_startuptime'
|
||||
after_each(function()
|
||||
@ -47,6 +48,34 @@ describe('startup', function()
|
||||
assert_log("require%('vim%._editor'%)", testfile, 100)
|
||||
end)
|
||||
end)
|
||||
|
||||
it('-D does not hang #12647', function()
|
||||
clear()
|
||||
local screen
|
||||
screen = Screen.new(60, 7)
|
||||
screen:attach()
|
||||
command([[let g:id = termopen('"]]..nvim_prog..
|
||||
[[" -u NONE -i NONE --cmd "set noruler" -D')]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
|
|
||||
Entering Debug mode. Type "cont" to continue. |
|
||||
nvim_exec() |
|
||||
cmd: aunmenu * |
|
||||
> |
|
||||
|
|
||||
]])
|
||||
command([[call chansend(g:id, "cont\n")]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
[No Name] |
|
||||
|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('startup', function()
|
||||
@ -58,6 +87,134 @@ describe('startup', function()
|
||||
os.remove('Xtest_startup_ttyout')
|
||||
end)
|
||||
|
||||
describe('-l Lua', function()
|
||||
local function assert_l_out(expected, nvim_args, lua_args, script, input)
|
||||
local args = { nvim_prog }
|
||||
vim.list_extend(args, nvim_args or {})
|
||||
vim.list_extend(args, { '-l', (script or 'test/functional/fixtures/startup.lua') })
|
||||
vim.list_extend(args, lua_args or {})
|
||||
local out = funcs.system(args, input):gsub('\r\n', '\n')
|
||||
return eq(dedent(expected), out)
|
||||
end
|
||||
|
||||
it('failure modes', function()
|
||||
-- nvim -l <empty>
|
||||
matches('nvim%.?e?x?e?: Argument missing after: "%-l"', funcs.system({ nvim_prog, '-l' }))
|
||||
eq(1, eval('v:shell_error'))
|
||||
end)
|
||||
|
||||
it('os.exit() sets Nvim exitcode', function()
|
||||
-- nvim -l foo.lua -arg1 -- a b c
|
||||
assert_l_out([[
|
||||
bufs:
|
||||
nvim args: 7
|
||||
lua args: { "-arg1", "--exitcode", "73", "--arg2" }]],
|
||||
{},
|
||||
{ '-arg1', "--exitcode", "73", '--arg2' }
|
||||
)
|
||||
eq(73, eval('v:shell_error'))
|
||||
end)
|
||||
|
||||
it('Lua-error sets Nvim exitcode', function()
|
||||
eq(0, eval('v:shell_error'))
|
||||
matches('E5113: .* my pearls!!',
|
||||
funcs.system({ nvim_prog, '-l', 'test/functional/fixtures/startup-fail.lua' }))
|
||||
eq(1, eval('v:shell_error'))
|
||||
matches('E5113: .* %[string "error%("whoa"%)"%]:1: whoa',
|
||||
funcs.system({ nvim_prog, '-l', '-' }, 'error("whoa")'))
|
||||
eq(1, eval('v:shell_error'))
|
||||
end)
|
||||
|
||||
it('executes stdin "-"', function()
|
||||
assert_l_out('args=2 whoa',
|
||||
nil,
|
||||
{ 'arg1', 'arg 2' },
|
||||
'-',
|
||||
"print(('args=%d %s'):format(#_G.arg, 'whoa'))")
|
||||
assert_l_out('biiig input: 1000042',
|
||||
nil,
|
||||
nil,
|
||||
'-',
|
||||
('print("biiig input: "..("%s"):len())'):format(string.rep('x', (1000 * 1000) + 42)))
|
||||
eq(0, eval('v:shell_error'))
|
||||
end)
|
||||
|
||||
it('sets _G.arg', function()
|
||||
-- nvim -l foo.lua -arg1 -- a b c
|
||||
assert_l_out([[
|
||||
bufs:
|
||||
nvim args: 6
|
||||
lua args: { "-arg1", "--arg2", "arg3" }]],
|
||||
{},
|
||||
{ '-arg1', '--arg2', 'arg3' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
|
||||
-- nvim -l foo.lua --
|
||||
assert_l_out([[
|
||||
bufs:
|
||||
nvim args: 4
|
||||
lua args: { "--" }]],
|
||||
{},
|
||||
{ '--' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
|
||||
-- nvim file1 file2 -l foo.lua -arg1 -- file3 file4
|
||||
assert_l_out([[
|
||||
bufs: file1 file2
|
||||
nvim args: 10
|
||||
lua args: { "-arg1", "arg 2", "--", "file3", "file4" }]],
|
||||
{ 'file1', 'file2', },
|
||||
{ '-arg1', 'arg 2', '--', 'file3', 'file4' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
|
||||
-- nvim file1 file2 -l foo.lua -arg1 --
|
||||
assert_l_out([[
|
||||
bufs: file1 file2
|
||||
nvim args: 7
|
||||
lua args: { "-arg1", "--" }]],
|
||||
{ 'file1', 'file2', },
|
||||
{ '-arg1', '--' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
|
||||
-- nvim -l foo.lua <vim args>
|
||||
assert_l_out([[
|
||||
bufs:
|
||||
nvim args: 5
|
||||
lua args: { "-c", "set wrap?" }]],
|
||||
{},
|
||||
{ '-c', 'set wrap?' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
|
||||
-- nvim <vim args> -l foo.lua <vim args>
|
||||
assert_l_out(
|
||||
-- luacheck: ignore 611 (Line contains only whitespaces)
|
||||
[[
|
||||
wrap
|
||||
|
||||
bufs:
|
||||
nvim args: 7
|
||||
lua args: { "-c", "set wrap?" }]],
|
||||
{ '-c', 'set wrap?' },
|
||||
{ '-c', 'set wrap?' }
|
||||
)
|
||||
eq(0, eval('v:shell_error'))
|
||||
end)
|
||||
|
||||
it('disables swapfile/shada/config/plugins', function()
|
||||
assert_l_out('updatecount=0 shadafile=NONE loadplugins=false scriptnames=1',
|
||||
nil,
|
||||
nil,
|
||||
'-',
|
||||
[[print(('updatecount=%d shadafile=%s loadplugins=%s scriptnames=%d'):format(
|
||||
vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.split(vim.fn.execute('scriptnames'),'\n'))))]])
|
||||
end)
|
||||
end)
|
||||
|
||||
it('pipe at both ends: has("ttyin")==0 has("ttyout")==0', function()
|
||||
-- system() puts a pipe at both ends.
|
||||
local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
|
||||
@ -66,6 +223,7 @@ describe('startup', function()
|
||||
'+q' })
|
||||
eq('0 0', out)
|
||||
end)
|
||||
|
||||
it('with --embed: has("ttyin")==0 has("ttyout")==0', function()
|
||||
local screen = Screen.new(25, 3)
|
||||
-- Remote UI connected by --embed.
|
||||
@ -77,6 +235,7 @@ describe('startup', function()
|
||||
0 0 |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
|
||||
local screen = Screen.new(25, 4)
|
||||
screen:attach()
|
||||
@ -95,6 +254,7 @@ describe('startup', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
|
||||
if is_os('win') then
|
||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||
@ -111,6 +271,7 @@ describe('startup', function()
|
||||
read_file('Xtest_startup_ttyout'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
|
||||
if is_os('win') then
|
||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||
@ -128,6 +289,7 @@ describe('startup', function()
|
||||
read_file('Xtest_startup_ttyout'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('input from pipe (implicit) #7679', function()
|
||||
local screen = Screen.new(25, 4)
|
||||
screen:attach()
|
||||
@ -147,6 +309,7 @@ describe('startup', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('input from pipe + file args #7679', function()
|
||||
eq('ohyeah\r\n0 0 bufs=3',
|
||||
funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '--headless',
|
||||
@ -238,11 +401,11 @@ describe('startup', function()
|
||||
it('-es/-Es disables swapfile, user config #8540', function()
|
||||
for _,arg in ipairs({'-es', '-Es'}) do
|
||||
local out = funcs.system({nvim_prog, arg,
|
||||
'+set swapfile? updatecount? shada?',
|
||||
'+set swapfile? updatecount? shadafile?',
|
||||
"+put =execute('scriptnames')", '+%print'})
|
||||
local line1 = string.match(out, '^.-\n')
|
||||
-- updatecount=0 means swapfile was disabled.
|
||||
eq(" swapfile updatecount=0 shada=!,'100,<50,s10,h\n", line1)
|
||||
eq(" swapfile updatecount=0 shadafile=\n", line1)
|
||||
-- Standard plugins were loaded, but not user config.
|
||||
eq('health.vim', string.match(out, 'health.vim'))
|
||||
eq(nil, string.match(out, 'init.vim'))
|
||||
@ -266,11 +429,13 @@ describe('startup', function()
|
||||
{ 'put =mode(1)', 'print', '' }))
|
||||
end)
|
||||
|
||||
it('fails on --embed with -es/-Es', function()
|
||||
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es',
|
||||
it('fails on --embed with -es/-Es/-l', function()
|
||||
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
|
||||
funcs.system({nvim_prog, '--embed', '-es' }))
|
||||
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es',
|
||||
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
|
||||
funcs.system({nvim_prog, '--embed', '-Es' }))
|
||||
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
|
||||
funcs.system({nvim_prog, '--embed', '-l', 'foo.lua' }))
|
||||
end)
|
||||
|
||||
it('does not crash if --embed is given twice', function()
|
||||
@ -532,32 +697,6 @@ describe('sysinit', function()
|
||||
eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))'))
|
||||
end)
|
||||
|
||||
it('fixed hang issue with -D (#12647)', function()
|
||||
local screen
|
||||
screen = Screen.new(60, 7)
|
||||
screen:attach()
|
||||
command([[let g:id = termopen('"]]..nvim_prog..
|
||||
[[" -u NONE -i NONE --cmd "set noruler" -D')]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
Entering Debug mode. Type "cont" to continue. |
|
||||
nvim_exec() |
|
||||
cmd: aunmenu * |
|
||||
> |
|
||||
<" -u NONE -i NONE --cmd "set noruler" -D 1,0-1 All|
|
||||
|
|
||||
]])
|
||||
command([[call chansend(g:id, "cont\n")]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
[No Name] |
|
||||
|
|
||||
<" -u NONE -i NONE --cmd "set noruler" -D 1,0-1 All|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('user config init', function()
|
||||
|
7
test/functional/fixtures/startup-fail.lua
Normal file
7
test/functional/fixtures/startup-fail.lua
Normal file
@ -0,0 +1,7 @@
|
||||
-- Test "nvim -l foo.lua …" with a Lua error.
|
||||
|
||||
local function main()
|
||||
error('my pearls!!')
|
||||
end
|
||||
|
||||
main()
|
35
test/functional/fixtures/startup.lua
Normal file
35
test/functional/fixtures/startup.lua
Normal file
@ -0,0 +1,35 @@
|
||||
-- Test "nvim -l foo.lua …"
|
||||
|
||||
local function printbufs()
|
||||
local bufs = ''
|
||||
for _, v in ipairs(vim.api.nvim_list_bufs()) do
|
||||
local b = vim.fn.bufname(v)
|
||||
if b:len() > 0 then
|
||||
bufs = ('%s %s'):format(bufs, b)
|
||||
end
|
||||
end
|
||||
print(('bufs:%s'):format(bufs))
|
||||
end
|
||||
|
||||
local function parseargs(args)
|
||||
local exitcode = nil
|
||||
for i = 1, #args do
|
||||
if args[i] == '--exitcode' then
|
||||
exitcode = tonumber(args[i + 1])
|
||||
end
|
||||
end
|
||||
return exitcode
|
||||
end
|
||||
|
||||
local function main()
|
||||
printbufs()
|
||||
print('nvim args:', #vim.v.argv)
|
||||
print('lua args:', vim.inspect(_G.arg))
|
||||
|
||||
local exitcode = parseargs(_G.arg)
|
||||
if type(exitcode) == 'number' then
|
||||
os.exit(exitcode)
|
||||
end
|
||||
end
|
||||
|
||||
main()
|
@ -1,3 +1,5 @@
|
||||
-- Tests for system() and :! shell.
|
||||
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local assert_alive = helpers.assert_alive
|
||||
|
Loading…
Reference in New Issue
Block a user