mirror of
https://github.com/neovim/neovim.git
synced 2025-12-07 15:14:04 +00:00
build(windows): restore tee.exe on Windows #36363
Problem:
Neovim no longer ships with a tee binary on Windows, which breaks
functionality for the :grep and :make commands.
nvim --clean
:grep foo or :make
"tee is not recognized as an internal or external command"
Solution:
Include a simple, no-dependency tee.c source file in the src/ directory.
Update CMakeLists.txt to build a tee executable alongside neovim during
the build process, and ensure the tee.exe program appears alongside the
neovim executable in the bin/ directory so that it is accessible for
:grep and :make.
tee.c was obtained from the vim codebase:
https://github.com/vim/vim/blob/master/src/tee/tee.c
And we modified it to fix performance issues.
Testing:
nvim --clean
:grep foo or :make, after setting a file to the makeprg option.
Verify that :grep results and error output from a compiler appear in the message pane.
ref https://github.com/neovim/neovim/issues/32431
fix https://github.com/neovim/neovim/issues/32504
Other tee options:
- [tee-win32](https://github.com/dEajL3kA/tee-win32): MIT. However,
I couldn't get it to build on my machine even after updating its
makefile to call my install of MSVC. It's also super optimized and
uses some processor intrinsics for multithreading.
- [gnu coreutils tee](https://gnuwin32.sourceforge.net/packages/coreutils.htm):
(Windows coreutils contains a tee.c. Last updated 2005. Did not build
immediately on my machine; we'd have to determine which definitions
from elsewhere in coreutils tee.c needs and incorporate them somehow.
- [WinTee](https://github.com/mpderbec/WinTee): Has no license. Last
updated 11 years ago. Relies on Visual Studio to build.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
@@ -312,6 +312,7 @@ add_custom_target(nvim ALL)
|
|||||||
add_dependencies(nvim nvim_bin nvim_runtime_deps nvim_runtime)
|
add_dependencies(nvim nvim_bin nvim_runtime_deps nvim_runtime)
|
||||||
|
|
||||||
add_subdirectory(src/nvim)
|
add_subdirectory(src/nvim)
|
||||||
|
add_subdirectory(src/tee)
|
||||||
add_subdirectory(cmake.config)
|
add_subdirectory(cmake.config)
|
||||||
add_subdirectory(runtime)
|
add_subdirectory(runtime)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|||||||
@@ -423,6 +423,7 @@ list(SORT NVIM_SOURCES)
|
|||||||
list(SORT NVIM_HEADERS)
|
list(SORT NVIM_HEADERS)
|
||||||
|
|
||||||
list(APPEND UNCRUSTIFY_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
list(APPEND UNCRUSTIFY_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||||
|
list(APPEND UNCRUSTIFY_NVIM_SOURCES ${PROJECT_SOURCE_DIR}/src/tee/tee.c)
|
||||||
|
|
||||||
foreach(sfile ${NVIM_SOURCES})
|
foreach(sfile ${NVIM_SOURCES})
|
||||||
get_filename_component(f ${sfile} NAME)
|
get_filename_component(f ${sfile} NAME)
|
||||||
@@ -454,6 +455,7 @@ foreach(hfile ${NVIM_HEADERS})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||||
|
list(APPEND LINT_NVIM_SOURCES ${PROJECT_SOURCE_DIR}/src/tee/tee.c)
|
||||||
|
|
||||||
# Log level (NVIM_LOG_DEBUG in log.h)
|
# Log level (NVIM_LOG_DEBUG in log.h)
|
||||||
if(CI_BUILD)
|
if(CI_BUILD)
|
||||||
|
|||||||
10
src/tee/CMakeLists.txt
Normal file
10
src/tee/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
add_executable(tee tee.c)
|
||||||
|
|
||||||
|
# tee has to be in the same directory as the nvim executable
|
||||||
|
set_target_properties(tee PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS tee
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
|
)
|
||||||
130
src/tee/tee.c
Normal file
130
src/tee/tee.c
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// tee.c - pipe fitting
|
||||||
|
//
|
||||||
|
// Copyright (c) 1996, Paul Slootman
|
||||||
|
//
|
||||||
|
// Author: Paul Slootman
|
||||||
|
// (paul@wurtel.hobby.nl, paul@murphy.nl, paulS@toecompst.nl)
|
||||||
|
// Modifications for MSVC: Yasuhiro Matsumoto
|
||||||
|
// Modifications for Neovim: https://github.com/neovim/neovim/pull/36363
|
||||||
|
//
|
||||||
|
// This source code is released into the public domain. It is provided on an
|
||||||
|
// as-is basis and no responsibility is accepted for its failure to perform
|
||||||
|
// as expected. It is worth at least as much as you paid for it!
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// tee reads stdin, and writes what it reads to each of the specified
|
||||||
|
// files. The primary reason of existence for this version is a quick
|
||||||
|
// and dirty implementation to distribute with Vim, to make one of the
|
||||||
|
// most useful features of Vim possible on OS/2: quickfix.
|
||||||
|
//
|
||||||
|
// Of course, not using tee but instead redirecting make's output directly
|
||||||
|
// into a temp file and then processing that is possible, but if we have a
|
||||||
|
// system capable of correctly piping (unlike DOS, for example), why not
|
||||||
|
// use it as well as possible? This tee should also work on other systems,
|
||||||
|
// but it's not been tested there, only on OS/2.
|
||||||
|
//
|
||||||
|
// tee is also available in the GNU shellutils package, which is available
|
||||||
|
// precompiled for OS/2. That one probably works better.
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define sysconf(x) - 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Neotee: a web-scale fork of tee\n"
|
||||||
|
"Usage:\n"
|
||||||
|
"\ttee [-a] file ... file_n\n"
|
||||||
|
"\n"
|
||||||
|
"\t-a\tappend to files instead of truncating\n"
|
||||||
|
"\n"
|
||||||
|
"Tee reads its input, and writes to each of the specified files,\n"
|
||||||
|
"as well as to the standard output.\n"
|
||||||
|
"\n"
|
||||||
|
"Shipped with Nvim 0.12+ for use with :make, :grep, :!, etc.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int append = 0;
|
||||||
|
size_t numfiles;
|
||||||
|
int maxfiles;
|
||||||
|
FILE **filepointers;
|
||||||
|
int i;
|
||||||
|
char buf[65536];
|
||||||
|
int n;
|
||||||
|
int optnr = 1;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (argv[i][0] != '-') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[i], "-a")) {
|
||||||
|
append++;
|
||||||
|
} else {
|
||||||
|
usage();
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
optnr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
numfiles = argc - optnr;
|
||||||
|
|
||||||
|
if (numfiles == 0) {
|
||||||
|
usage();
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
maxfiles = sysconf(_SC_OPEN_MAX); // or fill in 10 or so
|
||||||
|
if (maxfiles < 0) {
|
||||||
|
maxfiles = 10;
|
||||||
|
}
|
||||||
|
if (numfiles + 3 > maxfiles) { // +3 accounts for stdin, out, err
|
||||||
|
fprintf(stderr, "There is a limit of max %d files.\n", maxfiles - 3);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
filepointers = calloc(numfiles, sizeof(FILE *)); // NOLINT
|
||||||
|
if (filepointers == NULL) {
|
||||||
|
fprintf(stderr, "Error allocating memory for %ld files\n", (long)numfiles);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i = 0; i < numfiles; i++) {
|
||||||
|
filepointers[i] = fopen(argv[i + optnr], append ? "ab" : "wb");
|
||||||
|
if (filepointers[i] == NULL) {
|
||||||
|
fprintf(stderr, "Can't open \"%s\"\n", argv[i + optnr]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
setmode(fileno(stdin), O_BINARY);
|
||||||
|
fflush(stdout); // needed for _fsetmode(stdout)
|
||||||
|
setmode(fileno(stdout), O_BINARY);
|
||||||
|
setvbuf(stdout, NULL, _IONBF, 0); // unbuffered for immediate output
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while ((n = fread(buf, 1, sizeof(buf), stdin)) > 0) {
|
||||||
|
fwrite(buf, 1, n, stdout);
|
||||||
|
for (i = 0; i < numfiles; i++) {
|
||||||
|
if (filepointers[i]) {
|
||||||
|
fwrite(buf, 1, n, filepointers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
for (i = 0; i < numfiles; i++) {
|
||||||
|
if (filepointers[i]) {
|
||||||
|
fclose(filepointers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user