diff --git a/Makefile.in b/Makefile.in index ccd908330..8d18ce1d7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,7 +57,6 @@ CXXFLAGS = @CXXFLAGS@ $(MACROS) $(EXTRA_CXXFLAGS) LDFLAGS = @LDFLAGS@ LDFLAGS_FISH = ${LDFLAGS} @LIBS_FISH@ @LDFLAGS_FISH@ LDFLAGS_FISH_INDENT = ${LDFLAGS} @LIBS_FISH_INDENT@ -LDFLAGS_FISH_PAGER = ${LDFLAGS} @LIBS_FISH_PAGER@ LDFLAGS_FISHD = ${LDFLAGS} @LIBS_FISHD@ LDFLAGS_MIMEDB = ${LDFLAGS} @LIBS_MIMEDB@ @@ -106,15 +105,6 @@ BUILTIN_FILES := builtin_set.cpp builtin_commandline.cpp \ builtin_set_color.cpp builtin_printf.cpp -# -# All objects that the system needs to build fish_pager -# - -FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \ - input_common.o env_universal.o env_universal_common.o common.o \ - print_help.o iothread.o color.o - - # # All objects that the system needs to build fish_tests # @@ -192,7 +182,7 @@ FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish) # Programs to install # -PROGRAMS := fish mimedb fish_pager fishd fish_indent +PROGRAMS := fish mimedb fishd fish_indent # # Manual pages to install @@ -239,7 +229,7 @@ FISH-BUILD-VERSION-FILE: FORCE -include FISH-BUILD-VERSION-FILE CPPFLAGS += -DFISH_BUILD_VERSION=\"$(FISH_BUILD_VERSION)\" .PHONY: FORCE -env.o fish.o fish_indent.o fish_pager.o fishd.o mimedb.o: FISH-BUILD-VERSION-FILE +env.o fish.o fish_indent.o fishd.o mimedb.o: FISH-BUILD-VERSION-FILE # @@ -699,14 +689,6 @@ fish: $(FISH_OBJS) fish.o $(CXX) $(CXXFLAGS) $(FISH_OBJS) fish.o $(LDFLAGS_FISH) -o $@ -# -# Build the fish_pager program. -# - -fish_pager: $(FISH_PAGER_OBJS) - $(CXX) $(CXXFLAGS) $(FISH_PAGER_OBJS) $(LDFLAGS_FISH_PAGER) -o $@ - - # # Build the fishd program. # @@ -863,9 +845,6 @@ fish.o: expand.h intern.h exec.h output.h screen.h history.h path.h input.h fish.o: input_common.h fish_indent.o: config.h fallback.h signal.h util.h common.h wutil.h fish_indent.o: tokenizer.h print_help.h parser_keywords.h -fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h -fish_pager.o: output.h screen.h highlight.h env.h color.h input_common.h -fish_pager.o: env_universal.h env_universal_common.h print_help.h fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h fish_tests.o: parse_tree.h tokenizer.h parse_constants.h reader.h complete.h fish_tests.o: highlight.h env.h color.h builtin.h function.h event.h diff --git a/complete.h b/complete.h index be10d17bf..10f351fed 100644 --- a/complete.h +++ b/complete.h @@ -55,13 +55,6 @@ */ #define COMPLETE_SEP_STR L"\004" -/** - * Separator between completion items in fish_pager. This is used for - * completion grouping, e.g. when putting completions with the same - * descriptions on the same line. - */ -#define COMPLETE_ITEM_SEP L'\uf500' - /** * Character that separates the completion and description on * programmable completions diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index d2e9d2bcd..deb3a107d 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ dependencies = ( D07D265715E33B86009E43F6 /* PBXTargetDependency */, D07D265915E33B86009E43F6 /* PBXTargetDependency */, - D07D265B15E33B86009E43F6 /* PBXTargetDependency */, D07D265D15E33B86009E43F6 /* PBXTargetDependency */, D0A56500168D257900AF6161 /* PBXTargetDependency */, ); @@ -49,7 +48,6 @@ dependencies = ( D0F01A1315AA36280034B3B1 /* PBXTargetDependency */, D0F01A1515AA362E0034B3B1 /* PBXTargetDependency */, - D0F01A1915AA36310034B3B1 /* PBXTargetDependency */, D0F01A1715AA36300034B3B1 /* PBXTargetDependency */, D0A564EF168D09C000AF6161 /* PBXTargetDependency */, ); @@ -172,24 +170,11 @@ D0D02ADB159864C2008E62BD /* tokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855D13B3ACEE0099B651 /* tokenizer.cpp */; }; D0D02ADC159864D5008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; }; D0D02ADD159864D7008E62BD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; }; - D0D02AEA15986549008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; }; - D0D02AEB1598654C008E62BD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; }; - D0D1CD6C15B7451900F03988 /* fish_pager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854013B3ACEE0099B651 /* fish_pager.cpp */; }; - D0D1CD6D15B7452100F03988 /* output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855113B3ACEE0099B651 /* output.cpp */; }; - D0D1CD6E15B7452600F03988 /* wutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0856113B3ACEE0099B651 /* wutil.cpp */; }; - D0D1CD6F15B7452D00F03988 /* input_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854913B3ACEE0099B651 /* input_common.cpp */; }; - D0D1CD7015B7453300F03988 /* env_universal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853913B3ACEE0099B651 /* env_universal.cpp */; }; - D0D1CD7115B7453700F03988 /* env_universal_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */; }; - D0D1CD7215B7454A00F03988 /* print_help.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855613B3ACEE0099B651 /* print_help.cpp */; }; - D0D1CD7315B7455200F03988 /* color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0B6B0FE14E88BA400AD6C10 /* color.cpp */; }; - D0D1CD7415B7456000F03988 /* iothread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854D13B3ACEE0099B651 /* iothread.cpp */; }; - D0D1CD7515B7458B00F03988 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853613B3ACEE0099B651 /* common.cpp */; }; D0D2694915983772005D9B9C /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854413B3ACEE0099B651 /* function.cpp */; }; D0D2694A15983779005D9B9C /* builtin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853513B3ACEE0099B651 /* builtin.cpp */; }; D0F019F115A977140034B3B1 /* fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D2693C159835CA005D9B9C /* fish */; }; D0F019F215A977270034B3B1 /* fishd in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02ABC15985EF9008E62BD /* fishd */; }; D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02AD01598642A008E62BD /* fish_indent */; }; - D0F019F415A9772C0034B3B1 /* fish_pager in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02AE415986537008E62BD /* fish_pager */; }; D0F019F815A977AB0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD580159EE48F0024809C /* config.fish */; }; D0F019FD15A977CA0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0C4FD9415A7D7EE00212EF1 /* config.fish */; }; D0F01A0315A978910034B3B1 /* osx_fish_launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = D0D02AFA159871B2008E62BD /* osx_fish_launcher.m */; }; @@ -219,13 +204,6 @@ remoteGlobalIDString = D0D02ABB15985EF9008E62BD; remoteInfo = fishd; }; - D07D265C15E33B86009E43F6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D0A084F213B3AC130099B651 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0D02AE315986537008E62BD; - remoteInfo = fish_pager; - }; D07D265E15E33B86009E43F6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D0A084F213B3AC130099B651 /* Project object */; @@ -268,13 +246,6 @@ remoteGlobalIDString = D0D02ACF1598642A008E62BD; remoteInfo = fish_indent; }; - D0F01A1815AA36310034B3B1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D0A084F213B3AC130099B651 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0D02AE315986537008E62BD; - remoteInfo = fish_pager; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -355,7 +326,6 @@ D0F019F115A977140034B3B1 /* fish in CopyFiles */, D0F019F215A977270034B3B1 /* fishd in CopyFiles */, D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */, - D0F019F415A9772C0034B3B1 /* fish_pager in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -458,7 +428,6 @@ D0A0853D13B3ACEE0099B651 /* expand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = expand.cpp; sourceTree = ""; }; D0A0853E13B3ACEE0099B651 /* fallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fallback.cpp; sourceTree = ""; }; D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_indent.cpp; sourceTree = ""; }; - D0A0854013B3ACEE0099B651 /* fish_pager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_pager.cpp; sourceTree = ""; }; D0A0854113B3ACEE0099B651 /* fish_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_tests.cpp; sourceTree = ""; }; D0A0854213B3ACEE0099B651 /* fish.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish.cpp; sourceTree = ""; }; D0A0854313B3ACEE0099B651 /* fishd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fishd.cpp; sourceTree = ""; }; @@ -516,7 +485,6 @@ D0D02AA915985C0C008E62BD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = osx/Info.plist; sourceTree = ""; }; D0D02ABC15985EF9008E62BD /* fishd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fishd; sourceTree = BUILT_PRODUCTS_DIR; }; D0D02AD01598642A008E62BD /* fish_indent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish_indent; sourceTree = BUILT_PRODUCTS_DIR; }; - D0D02AE415986537008E62BD /* fish_pager */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish_pager; sourceTree = BUILT_PRODUCTS_DIR; }; D0D02AFA159871B2008E62BD /* osx_fish_launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = osx_fish_launcher.m; path = osx/osx_fish_launcher.m; sourceTree = ""; }; D0D2693C159835CA005D9B9C /* fish */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish; sourceTree = BUILT_PRODUCTS_DIR; }; D0D9B2B318555D92001AE279 /* parse_constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parse_constants.h; sourceTree = ""; }; @@ -554,15 +522,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D0D02AE115986537008E62BD /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D0D02AEA15986549008E62BD /* libncurses.dylib in Frameworks */, - D0D02AEB1598654C008E62BD /* libiconv.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; D0D26939159835CA005D9B9C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -676,7 +635,6 @@ D0A0850E13B3ACEE0099B651 /* function.h */, D0A0854413B3ACEE0099B651 /* function.cpp */, D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */, - D0A0854013B3ACEE0099B651 /* fish_pager.cpp */, D0A0854113B3ACEE0099B651 /* fish_tests.cpp */, D0A0854213B3ACEE0099B651 /* fish.cpp */, D0A0854313B3ACEE0099B651 /* fishd.cpp */, @@ -789,7 +747,6 @@ D0D02A9A15985A75008E62BD /* fish.app */, D0D02ABC15985EF9008E62BD /* fishd */, D0D02AD01598642A008E62BD /* fish_indent */, - D0D02AE415986537008E62BD /* fish_pager */, D08A328D17B4455100F3A533 /* fish_tests */, ); name = Products; @@ -890,22 +847,6 @@ productReference = D0D02AD01598642A008E62BD /* fish_indent */; productType = "com.apple.product-type.tool"; }; - D0D02AE315986537008E62BD /* fish_pager */ = { - isa = PBXNativeTarget; - buildConfigurationList = D0D02AE715986537008E62BD /* Build configuration list for PBXNativeTarget "fish_pager" */; - buildPhases = ( - D0D02AE015986537008E62BD /* Sources */, - D0D02AE115986537008E62BD /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = fish_pager; - productName = fish_pager; - productReference = D0D02AE415986537008E62BD /* fish_pager */; - productType = "com.apple.product-type.tool"; - }; D0D2693B159835CA005D9B9C /* fish_shell */ = { isa = PBXNativeTarget; buildConfigurationList = D0D26943159835CA005D9B9C /* Build configuration list for PBXNativeTarget "fish_shell" */; @@ -948,7 +889,6 @@ D0D2693B159835CA005D9B9C /* fish_shell */, D0D02ABB15985EF9008E62BD /* fishd */, D0D02ACF1598642A008E62BD /* fish_indent */, - D0D02AE315986537008E62BD /* fish_pager */, D08A328C17B4455100F3A533 /* fish_tests */, D0A564E6168CFDD800AF6161 /* man_pages */, D0A084F713B3AC130099B651 /* Makefile */, @@ -1201,23 +1141,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D0D02AE015986537008E62BD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D0D1CD6C15B7451900F03988 /* fish_pager.cpp in Sources */, - D0D1CD6D15B7452100F03988 /* output.cpp in Sources */, - D0D1CD6E15B7452600F03988 /* wutil.cpp in Sources */, - D0D1CD6F15B7452D00F03988 /* input_common.cpp in Sources */, - D0D1CD7015B7453300F03988 /* env_universal.cpp in Sources */, - D0D1CD7115B7453700F03988 /* env_universal_common.cpp in Sources */, - D0D1CD7315B7455200F03988 /* color.cpp in Sources */, - D0D1CD7515B7458B00F03988 /* common.cpp in Sources */, - D0D1CD7215B7454A00F03988 /* print_help.cpp in Sources */, - D0D1CD7415B7456000F03988 /* iothread.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; D0D26938159835CA005D9B9C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1292,11 +1215,6 @@ target = D0D02ABB15985EF9008E62BD /* fishd */; targetProxy = D07D265A15E33B86009E43F6 /* PBXContainerItemProxy */; }; - D07D265B15E33B86009E43F6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0D02AE315986537008E62BD /* fish_pager */; - targetProxy = D07D265C15E33B86009E43F6 /* PBXContainerItemProxy */; - }; D07D265D15E33B86009E43F6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D0D02ACF1598642A008E62BD /* fish_indent */; @@ -1327,11 +1245,6 @@ target = D0D02ACF1598642A008E62BD /* fish_indent */; targetProxy = D0F01A1615AA36300034B3B1 /* PBXContainerItemProxy */; }; - D0F01A1915AA36310034B3B1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0D02AE315986537008E62BD /* fish_pager */; - targetProxy = D0F01A1815AA36310034B3B1 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -1435,18 +1348,6 @@ }; name = "Release_C++11"; }; - D007FDE117136EAA00A52BE6 /* Release_C++11 */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = "Release_C++11"; - }; D007FDE217136EAA00A52BE6 /* Release_C++11 */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1743,34 +1644,6 @@ }; name = Release; }; - D0D02AE815986537008E62BD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - D0D02AE915986537008E62BD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; D0D26944159835CA005D9B9C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1898,16 +1771,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D0D02AE715986537008E62BD /* Build configuration list for PBXNativeTarget "fish_pager" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D0D02AE815986537008E62BD /* Debug */, - D0D02AE915986537008E62BD /* Release */, - D007FDE117136EAA00A52BE6 /* Release_C++11 */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; D0D26943159835CA005D9B9C /* Build configuration list for PBXNativeTarget "fish_shell" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/fish_pager.cpp b/fish_pager.cpp deleted file mode 100644 index f640e9959..000000000 --- a/fish_pager.cpp +++ /dev/null @@ -1,1427 +0,0 @@ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#include -#include -#include -#include - -#include - -#if HAVE_NCURSES_H -#include -#else -#include -#endif - -#if HAVE_TERM_H -#include -#elif HAVE_NCURSES_TERM_H -#include -#endif - -#include - -#ifdef HAVE_GETOPT_H -#include -#endif - -#include -#include - -#include "fallback.h" -#include "util.h" - -#include "wutil.h" -#include "common.h" -#include "complete.h" -#include "output.h" -#include "input_common.h" -#include "env_universal.h" -#include "print_help.h" - -enum -{ - LINE_UP = R_NULL+1, - LINE_DOWN, - PAGE_UP, - PAGE_DOWN -} -; - - -enum -{ - HIGHLIGHT_PAGER_PREFIX, - HIGHLIGHT_PAGER_COMPLETION, - HIGHLIGHT_PAGER_DESCRIPTION, - HIGHLIGHT_PAGER_PROGRESS, - HIGHLIGHT_PAGER_SECONDARY -} -; - -enum -{ - /* - Returnd by the pager if no more displaying is needed - */ - PAGER_DONE, - /* - Returned by the pager if the completions would not fit in the specified number of columns - */ - PAGER_RETRY, - /* - Returned by the pager if the terminal changes size - */ - PAGER_RESIZE -} -; - -/** - The minimum width (in characters) the terminal may have for fish_pager to not refuse showing the completions -*/ -#define PAGER_MIN_WIDTH 16 - -/** - The maximum number of columns of completion to attempt to fit onto the screen -*/ -#define PAGER_MAX_COLS 6 - -/** - The string describing the single-character options accepted by fish_pager -*/ -#define GETOPT_STRING "c:hr:qvp:" - -/** - Error to use when given an invalid file descriptor for reading completions or writing output -*/ -#define ERR_NOT_FD _( L"%ls: Argument '%s' is not a valid file descriptor\n" ) - -/** - This struct should be continually updated by signals as the term - resizes, and as such always contain the correct current size. -*/ -static struct winsize termsize; - -/** - The termios modes the terminal had when the program started. These - should be restored on exit -*/ -static struct termios saved_modes; - -/** - This flag is set to 1 of we have sent the enter_ca_mode terminfo - sequence to save the previous terminal contents. -*/ -static int is_ca_mode = 0; - -/** - This buffer is used to buffer the output of the pager to improve - screen redraw performance bu cutting down the number of write() - calls to only one. -*/ -static std::vector pager_buffer; - -/** - The environment variables used to specify the color of different - tokens. -*/ -static const wchar_t *hightlight_var[] = -{ - L"fish_pager_color_prefix", - L"fish_pager_color_completion", - L"fish_pager_color_description", - L"fish_pager_color_progress", - L"fish_pager_color_secondary" -} -; - -/** - This string contains the text that should be sent back to the calling program -*/ -static wcstring out_buff; -/** - This is the file to which the output text should be sent. It is really a pipe. -*/ -static FILE *out_file; - -/** - Data structure describing one or a group of related completions -*/ -struct comp_t -{ - /** - The list of all completin strings this entry applies to - */ - wcstring_list_t comp; - /** - The description - */ - wcstring desc; - /** - On-screen width of the completion string - */ - int comp_width; - /** - On-screen width of the description information - */ - int desc_width; - /** - Preffered total width - */ - int pref_width; - /** - Minimum acceptable width - */ - int min_width; -}; - -/** - This function translates from a highlight code to a specific color - by check invironement variables -*/ -static rgb_color_t get_color(int highlight) -{ - const wchar_t *val; - - if (highlight < 0) - return rgb_color_t::normal(); - if (highlight >= (5)) - return rgb_color_t::normal(); - - val = wgetenv(hightlight_var[highlight]); - - if (!val) - { - val = env_universal_get(hightlight_var[highlight]); - } - - if (!val) - { - return rgb_color_t::normal(); - } - - return parse_color(val, false); -} - -/** - This function calculates the minimum width for each completion - entry in the specified array_list. This width depends on the - terminal size, so this function should be called when the terminal - changes size. -*/ -static void recalc_width(std::vector &lst, const wchar_t *prefix) -{ - for (size_t i=0; imin_width = mini(c->desc_width, maxi(0,termsize.ws_col/3 - 2)) + - mini(c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4; - } - -} - -/** - Test if the specified character sequence has been entered on the - keyboard -*/ -static int try_sequence(const char *seq) -{ - int j, k; - wint_t c=0; - - for (j=0; - seq[j] != '\0' && seq[j] == (c=input_common_readch(j>0)); - j++) - ; - - if (seq[j] == '\0') - { - return 1; - } - else - { - input_common_unreadch(c); - for (k=j-1; k>=0; k--) - input_common_unreadch(seq[k]); - } - return 0; -} - -/** - Read a character from keyboard -*/ -static wint_t readch() -{ - struct mapping - { - const char *seq; - wint_t bnd; - } - ; - - struct mapping m[]= - { - { - "\x1b[A", LINE_UP - } - , - { - key_up, LINE_UP - } - , - { - "\x1b[B", LINE_DOWN - } - , - { - key_down, LINE_DOWN - } - , - { - key_ppage, PAGE_UP - } - , - { - key_npage, PAGE_DOWN - } - , - { - " ", PAGE_DOWN - } - , - { - "\t", PAGE_DOWN - } - , - { - 0, 0 - } - - } - ; - int i; - - for (i=0; m[i].bnd; i++) - { - if (!m[i].seq) - { - continue; - } - - if (try_sequence(m[i].seq)) - return m[i].bnd; - } - return input_common_readch(0); -} - -/** - Write specified character to the output buffer \c pager_buffer -*/ -static int pager_buffered_writer(char c) -{ - pager_buffer.push_back(c); - return 0; -} - -/** - Flush \c pager_buffer to stdout -*/ -static void pager_flush() -{ - if (! pager_buffer.empty()) - { - write_loop(1, & pager_buffer.at(0), pager_buffer.size() * sizeof(char)); - pager_buffer.clear(); - } -} - -/** - Print the specified string, but use at most the specified amount of - space. If the whole string can't be fitted, ellipsize it. - - \param str the string to print - \param max the maximum space that may be used for printing - \param has_more if this flag is true, this is not the entire string, and the string should be ellisiszed even if the string fits but takes up the whole space. -*/ -static int print_max(const wchar_t *str, int max, int has_more) -{ - int i; - int written = 0; - for (i=0; str[i]; i++) - { - - if (written + wcwidth(str[i]) > max) - break; - if ((written + wcwidth(str[i]) == max) && (has_more || str[i+1])) - { - writech(ellipsis_char); - written += wcwidth(ellipsis_char); - break; - } - - writech(str[i]); - written+= wcwidth(str[i]); - } - return written; -} - -/** - Print the specified item using at the specified amount of space -*/ -static void completion_print_item(const wchar_t *prefix, comp_t *c, int width, bool secondary) -{ - int comp_width=0, desc_width=0; - int written=0; - - if (c->pref_width <= width) - { - /* - The entry fits, we give it as much space as it wants - */ - comp_width = c->comp_width; - desc_width = c->desc_width; - } - else - { - /* - The completion and description won't fit on the - allocated space. Give a maximum of 2/3 of the - space to the completion, and whatever is left to - the description. - */ - int desc_all = c->desc_width?c->desc_width+4:0; - - comp_width = maxi(mini(c->comp_width, - 2*(width-4)/3), - width - desc_all); - if (c->desc_width) - desc_width = width-comp_width-4; - else - c->desc_width=0; - - } - - rgb_color_t bg = secondary ? get_color(HIGHLIGHT_PAGER_SECONDARY) : rgb_color_t::normal(); - for (size_t i=0; icomp.size(); i++) - { - const wcstring &comp = c->comp.at(i); - if (i != 0) - written += print_max(L" ", comp_width - written, 2); - set_color(get_color(HIGHLIGHT_PAGER_PREFIX), bg); - written += print_max(prefix, comp_width - written, comp.empty()?0:1); - set_color(get_color(HIGHLIGHT_PAGER_COMPLETION), bg); - written += print_max(comp.c_str(), comp_width - written, i!=(c->comp.size()-1)); - } - - - if (desc_width) - { - while (written < (width-desc_width-2)) - { - written++; - writech(L' '); - } - set_color(get_color(HIGHLIGHT_PAGER_DESCRIPTION), bg); - written += print_max(L"(", 1, 0); - written += print_max(c->desc.c_str(), desc_width, 0); - written += print_max(L")", 1, 0); - } - else - { - while (written < width) - { - written++; - writech(L' '); - } - } - if (secondary) - set_color(rgb_color_t::normal(), rgb_color_t::normal()); -} - -/** - Print the specified part of the completion list, using the - specified column offsets and quoting style. - - \param l The list of completions to print - \param cols number of columns to print in - \param width An array specifying the width of each column - \param row_start The first row to print - \param row_stop the row after the last row to print - \param prefix The string to print before each completion - \param is_quoted Whether to print the completions are in a quoted environment -*/ - -static void completion_print(int cols, - int *width, - int row_start, - int row_stop, - const wchar_t *prefix, - int is_quoted, - const std::vector &lst) -{ - - size_t rows = (lst.size()-1)/cols+1; - size_t i, j; - - for (i = row_start; i &lst) -{ - /* - The calculated preferred width of each column - */ - int pref_width[PAGER_MAX_COLS]; - /* - The calculated minimum width of each column - */ - int min_width[PAGER_MAX_COLS]; - /* - If the list can be printed with this width, width will contain the width of each column - */ - int *width=pref_width; - /* - Set to one if the list should be printed at this width - */ - int print=0; - - long i, j; - - int rows = (int)((lst.size()-1)/cols+1); - - int pref_tot_width=0; - int min_tot_width = 0; - int res=PAGER_RETRY; - /* - Skip completions on tiny terminals - */ - - if (termsize.ws_col < PAGER_MIN_WIDTH) - return PAGER_DONE; - - memset(pref_width, 0, sizeof(pref_width)); - memset(min_width, 0, sizeof(min_width)); - - /* Calculate how wide the list would be */ - for (j = 0; j < cols; j++) - { - for (i = 0; ipref_width; - min = c->min_width; - - if (j != cols-1) - { - pref += 2; - min += 2; - } - min_width[j] = maxi(min_width[j], - min); - pref_width[j] = maxi(pref_width[j], - pref); - } - min_tot_width += min_width[j]; - pref_tot_width += pref_width[j]; - } - /* - Force fit if one column - */ - if (cols == 1) - { - if (pref_tot_width > termsize.ws_col) - { - pref_width[0] = termsize.ws_col; - } - width = pref_width; - print=1; - } - else if (pref_tot_width <= termsize.ws_col) - { - /* Terminal is wide enough. Print the list! */ - width = pref_width; - print=1; - } - else - { - long next_rows = (lst.size()-1)/(cols-1)+1; - /* fwprintf( stderr, - L"cols %d, min_tot %d, term %d, rows=%d, nextrows %d, termrows %d, diff %d\n", - cols, - min_tot_width, termsize.ws_col, - rows, next_rows, termsize.ws_row, - pref_tot_width-termsize.ws_col ); - */ - if (min_tot_width < termsize.ws_col && - (((rows < termsize.ws_row) && (next_rows >= termsize.ws_row)) || - (pref_tot_width-termsize.ws_col< 4 && cols < 3))) - { - /* - Terminal almost wide enough, or squeezing makes the - whole list fit on-screen. - - This part of the code is really important. People hate - having to scroll through the completion list. In cases - where there are a huge number of completions, it can't - be helped, but it is not uncommon for the completions to - _almost_ fit on one screen. In those cases, it is almost - always desirable to 'squeeze' the completions into a - single page. - - If we are using N columns and can get everything to - fit using squeezing, but everything would also fit - using N-1 columns, don't try. - */ - - int tot_width = min_tot_width; - width = min_width; - - while (tot_width < termsize.ws_col) - { - for (i=0; (i 0) - { - pos--; - writembs(tparm(cursor_address, 0, 0)); - writembs(scroll_reverse); - completion_print(cols, - width, - pos, - pos+1, - prefix, - is_quoted, - lst); - writembs(tparm(cursor_address, - termsize.ws_row-1, 0)); - writembs(clr_eol); - - } - - break; - } - - case LINE_DOWN: - { - if (pos <= (rows - termsize.ws_row)) - { - pos++; - completion_print(cols, - width, - pos+termsize.ws_row-2, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst); - } - break; - } - - case PAGE_DOWN: - { - - npos = mini((int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1)); - if (npos != pos) - { - pos = npos; - completion_print(cols, - width, - pos, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst); - } - else - { - if (flash_screen) - writembs(flash_screen); - } - - break; - } - - case PAGE_UP: - { - npos = maxi(0, - pos - termsize.ws_row+1); - - if (npos != pos) - { - pos = npos; - completion_print(cols, - width, - pos, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst); - } - else - { - if (flash_screen) - writembs(flash_screen); - } - break; - } - - case R_NULL: - { - do_loop=0; - res=PAGER_RESIZE; - break; - - } - - default: - { - out_buff.push_back(c); - do_loop = 0; - break; - } - } - } - writembs(clr_eol); - } - } - return res; -} - -/** - Substitute any series of whitespace with a single space character - inside completion descriptions. Remove all whitespace from - beginning/end of completion descriptions. -*/ -static void mangle_descriptions(wcstring_list_t &lst) -{ - int skip; - for (size_t i=0; i desc_table; - - for (size_t i=0; isize(); i++) - { - const wchar_t *item = lst->at(i).c_str(); - const wchar_t *desc = wcschr(item, COMPLETE_SEP); - long prev_idx; - - if (!desc) - continue; - desc++; - prev_idx = desc_table[desc] - 1; - if (prev_idx == -1) - { - desc_table[desc] = (long)(i+1); - } - else - { - const wchar_t *old = lst->at(prev_idx).c_str(); - const wchar_t *old_end = wcschr(old, COMPLETE_SEP); - - if (old_end) - { - - wcstring foo; - foo.append(old, old_end - old); - foo.push_back(COMPLETE_ITEM_SEP); - foo.append(item); - - lst->at(prev_idx) = foo; - lst->at(i).clear(); - } - - } - - } - - /* Remove empty strings */ - lst->erase(remove(lst->begin(), lst->end(), wcstring()), lst->end()); -} - -/** - Replace completion strings with a comp_t structure -*/ -static std::vector mangle_completions(wcstring_list_t &lst, const wchar_t *prefix) -{ - std::vector result; - for (size_t i=0; icomp_width += my_wcswidth(str.c_str()); - comp->comp.push_back(str); - start = end+1; - } - - if (c == COMPLETE_SEP) - { - comp->desc = next.c_str() + start; - break; - } - - if (!c) - break; - - } - - comp->comp_width += (int)(my_wcswidth(prefix)*comp->comp.size() + 2*(comp->comp.size()-1)); - comp->desc_width = comp->desc.empty()?0:my_wcswidth(comp->desc.c_str()); - - comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0); - - result.push_back(comp); - } - - recalc_width(result, prefix); - return result; -} - - - -/** - Respond to a winch signal by checking the terminal size -*/ -static void handle_winch(int sig) -{ - if (ioctl(1,TIOCGWINSZ,&termsize)!=0) - { - return; - } -} - -/** - The callback function that the keyboard reading function calls when - an interrupt occurs. This makes sure that R_NULL is returned at - once when an interrupt has occured. -*/ -static int interrupt_handler() -{ - return R_NULL; -} - -/** - Initialize various subsystems. This also closes stdin and replaces - it with a copy of stderr, so the reading of completion strings must - be done before init is called. -*/ -static void init(int mangle_descriptors, int out) -{ - struct sigaction act; - - static struct termios pager_modes; - char *term; - - if (mangle_descriptors) - { - - /* - Make fd 1 output to screen, and use some other fd for writing - the resulting output back to the caller - */ - int in; - out = dup(1); - close(1); - close(0); - - /* OK to not use CLO_EXEC here because fish_pager is single threaded */ - if ((in = open(ttyname(2), O_RDWR)) != -1) - { - if (dup2(2, 1) == -1) - { - debug(0, _(L"Could not set up output file descriptors for pager")); - exit(1); - } - - if (dup2(in, 0) == -1) - { - debug(0, _(L"Could not set up input file descriptors for pager")); - exit(1); - } - } - else - { - debug(0, _(L"Could not open tty for pager")); - exit(1); - } - } - - if (!(out_file = fdopen(out, "w"))) - { - debug(0, _(L"Could not initialize result pipe")); - exit(1); - } - - - env_universal_init(0, 0, 0, 0); - input_common_init(&interrupt_handler); - output_set_writer(&pager_buffered_writer); - - sigemptyset(& act.sa_mask); - act.sa_flags=0; - act.sa_handler=SIG_DFL; - act.sa_flags = 0; - act.sa_handler= &handle_winch; - if (sigaction(SIGWINCH, &act, 0)) - { - wperror(L"sigaction"); - exit(1); - } - - handle_winch(0); /* Set handler for window change events */ - - tcgetattr(0,&pager_modes); /* get the current terminal modes */ - memcpy(&saved_modes, - &pager_modes, - sizeof(saved_modes)); /* save a copy so we can reset the terminal later */ - - pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */ - pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */ - pager_modes.c_cc[VMIN]=1; - pager_modes.c_cc[VTIME]=0; - - /* - - */ - if (tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ - { - wperror(L"tcsetattr"); - exit(1); - } - - int errret; - if (setupterm(0, STDOUT_FILENO, &errret) == ERR) - { - debug(0, _(L"Could not set up terminal")); - exit(1); - } - - term = getenv("TERM"); - if (term) - { - wcstring wterm = str2wcstring(term); - output_set_term(wterm); - } - - /* Infer term256 support */ - char *fish_term256 = getenv("fish_term256"); - bool support_term256; - if (fish_term256) - { - support_term256 = from_string(fish_term256); - } - else - { - support_term256 = term && strstr(term, "256color"); - } - output_set_supports_term256(support_term256); -} - -/** - Free memory used by various subsystems. -*/ -static void destroy() -{ - env_universal_destroy(); - input_common_destroy(); - wutil_destroy(); - if (fish_del_curterm(cur_term) == ERR) - { - debug(0, _(L"Error while closing terminfo")); - } - - fclose(out_file); -} - -/** - Read lines of input from the specified file, unescape them and - insert them into the specified list. -*/ -static void read_array(FILE* file, wcstring_list_t &comp) -{ - std::vector buffer; - int c; - - while (!feof(file)) - { - buffer.clear(); - - while (1) - { - c = getc(file); - if (c == EOF) - { - break; - } - - if (c == '\n') - { - break; - } - - buffer.push_back(static_cast(c)); - } - - if (! buffer.empty()) - { - buffer.push_back(0); - wcstring wcs = str2wcstring(&buffer.at(0)); - if (unescape_string_in_place(&wcs, false)) - { - comp.push_back(wcs); - } - } - } - -} - -static int get_fd(const char *str) -{ - char *end; - long fd; - - errno = 0; - fd = strtol(str, &end, 10); - if (fd < 0 || *end || errno) - { - debug(0, ERR_NOT_FD, program_name, optarg); - exit(1); - } - return (int)fd; -} - - -int main(int argc, char **argv) -{ - int i; - int is_quoted=0; - wcstring_list_t comp; - wcstring prefix; - - int mangle_descriptors = 0; - int result_fd = -1; - set_main_thread(); - setup_fork_guards(); - - /* - This initialization is made early, so that the other init code - can use global_context for memory managment - */ - program_name = L"fish_pager"; - - - wsetlocale(LC_ALL, L""); - - /* - The call signature for fish_pager is a mess. Because we want - to be able to upgrade fish without breaking running - instances, we need to support all previous - modes. Unfortunatly, the two previous ones are a mess. The - third one is designed to be extensible, so hopefully it will - be the last. - */ - - if (argc > 1 && argv[1][0] == '-') - { - /* - Third mode - */ - - int completion_fd = -1; - FILE *completion_file; - - while (1) - { - static struct option - long_options[] = - { - { - "result-fd", required_argument, 0, 'r' - } - , - { - "completion-fd", required_argument, 0, 'c' - } - , - { - "prefix", required_argument, 0, 'p' - } - , - { - "is-quoted", no_argument, 0, 'q' - } - , - { - "help", no_argument, 0, 'h' - } - , - { - "version", no_argument, 0, 'v' - } - , - { - 0, 0, 0, 0 - } - } - ; - - int opt_index = 0; - - int opt = getopt_long(argc, - argv, - GETOPT_STRING, - long_options, - &opt_index); - - if (opt == -1) - break; - - switch (opt) - { - case 0: - { - break; - } - - case 'r': - { - result_fd = get_fd(optarg); - break; - } - - case 'c': - { - completion_fd = get_fd(optarg); - break; - } - - case 'p': - { - prefix = str2wcstring(optarg); - break; - } - - case 'h': - { - print_help(argv[0], 1); - exit(0); - } - - case 'v': - { - debug(0, L"%ls, version %s\n", program_name, FISH_BUILD_VERSION); - exit(0); - } - - case 'q': - { - is_quoted = 1; - } - - } - } - - if (completion_fd == -1 || result_fd == -1) - { - debug(0, _(L"Unspecified file descriptors")); - exit(1); - } - - - if ((completion_file = fdopen(completion_fd, "r"))) - { - read_array(completion_file, comp); - fclose(completion_file); - } - else - { - debug(0, _(L"Could not read completions")); - wperror(L"fdopen"); - exit(1); - } - - } - else - { - /* - Second or first mode. These suck, but we need to support - them for backwards compatibility. At least for some - time. - - Third mode was implemented in January 2007, and previous - modes should be considered deprecated from that point - forward. A reasonable time frame for removal of the code - below has yet to be determined. - */ - - if (argc < 3) - { - print_help(argv[0], 1); - exit(0); - } - else - { - mangle_descriptors = 1; - - prefix = str2wcstring(argv[2]); - is_quoted = strcmp("1", argv[1])==0; - - if (argc > 3) - { - /* - First mode - */ - for (i=3; i completions = mangle_completions(comp, prefix.c_str()); - - /** - Try to print the completions. Start by trying to print the - list in PAGER_MAX_COLS columns, if the completions won't - fit, reduce the number of columns by one. Printing a single - column never fails. - */ - for (i = PAGER_MAX_COLS; i>0; i--) - { - switch (completion_try_print(i, prefix.c_str(), is_quoted, completions)) - { - - case PAGER_RETRY: - break; - - case PAGER_DONE: - i=0; - break; - - case PAGER_RESIZE: - /* - This means we got a resize event, so we start - over from the beginning. Since it the screen got - bigger, we might be able to fit all completions - on-screen. - */ - i=PAGER_MAX_COLS+1; - break; - - } - } - - fwprintf(out_file, L"%ls", out_buff.c_str()); - if (is_ca_mode) - { - writembs(exit_ca_mode); - pager_flush(); - } - destroy(); - -} - diff --git a/reader.cpp b/reader.cpp index 3899e4d47..6a81f3805 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1347,144 +1347,6 @@ static void completion_insert(const wchar_t *val, complete_flags_t flags) data->suppress_autosuggestion = true; } -/* Return an escaped path to fish_pager */ -static wcstring escaped_fish_pager_path(void) -{ - wcstring result; - const env_var_t bin_dir = env_get_string(L"__fish_bin_dir"); - if (bin_dir.missing_or_empty()) - { - /* This isn't good, hope our normal command stuff can find it */ - result = L"fish_pager"; - } - else - { - result = escape_string(bin_dir + L"/fish_pager", ESCAPE_ALL); - } - return result; -} - -/** - Run the fish_pager command to display the completion list. If the - fish_pager outputs any text, it is inserted into the input - backbuffer. - - \param prefix the string to display before every completion. - \param is_quoted should be set if the argument is quoted. This will change the display style. - \param comp the list of completions to display -*/ -static void run_pager(const wcstring &prefix, int is_quoted, const std::vector &comp) -{ - wcstring msg; - wcstring prefix_esc; - char *foo; - - shared_ptr in_buff(io_buffer_t::create(true, 3)); - shared_ptr out_buff(io_buffer_t::create(false, 4)); - - // The above may fail e.g. if we have too many open fds - if (in_buff.get() == NULL || out_buff.get() == NULL) - return; - - wchar_t *escaped_separator; - - if (prefix.empty()) - { - prefix_esc = L"\"\""; - } - else - { - prefix_esc = escape_string(prefix, 1); - } - - - const wcstring pager_path = escaped_fish_pager_path(); - const wcstring cmd = format_string(L"%ls -c 3 -r 4 %ls -p %ls", - // L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./%ls %d %ls", - pager_path.c_str(), - is_quoted?L"-q":L"", - prefix_esc.c_str()); - - escaped_separator = escape(COMPLETE_SEP_STR, 1); - - editable_line_t *el = &data->command_line; - - for (size_t i=0; i< comp.size(); i++) - { - long base_len=-1; - const completion_t &cmpl = comp.at(i); - - wcstring completion_text; - wcstring description_text; - - // Note that an empty completion is perfectly sensible here, e.g. tab-completing 'foo' with a file called 'foo' and another called 'foobar' - if ((cmpl.flags & COMPLETE_REPLACES_TOKEN) && match_type_shares_prefix(cmpl.match.type)) - { - // Compute base_len if we have not yet - if (base_len == -1) - { - const wchar_t *begin, *buff = el->text.c_str(); - - parse_util_token_extent(buff, el->position, &begin, 0, 0, 0); - base_len = el->position - (begin-buff); - } - - completion_text = escape_string(cmpl.completion.c_str() + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED); - } - else - { - completion_text = escape_string(cmpl.completion, ESCAPE_ALL | ESCAPE_NO_QUOTED); - } - - - if (! cmpl.description.empty()) - { - description_text = escape_string(cmpl.description, true); - } - - /* It's possible (even common) to have an empty completion with no description. An example would be completing 'foo' with extant files 'foo' and 'foobar'. But fish_pager ignores blank lines. So if our completion text is empty, always include a description, even if it's empty. - */ - msg.reserve(msg.size() + completion_text.size() + description_text.size() + 2); - msg.append(completion_text); - if (! description_text.empty() || completion_text.empty()) - { - msg.append(escaped_separator); - msg.append(description_text); - } - msg.push_back(L'\n'); - } - - free(escaped_separator); - - foo = wcs2str(msg.c_str()); - in_buff->out_buffer_append(foo, strlen(foo)); - free(foo); - - term_donate(); - parser_t &parser = parser_t::principal_parser(); - io_chain_t io_chain; - io_chain.push_back(out_buff); - io_chain.push_back(in_buff); - parser.eval(cmd, io_chain, TOP); - term_steal(); - - out_buff->read(); - - const char zero = 0; - out_buff->out_buffer_append(&zero, 1); - - const char *out_data = out_buff->out_buffer_ptr(); - if (out_data) - { - const wcstring str = str2wcstring(out_data); - size_t idx = str.size(); - while (idx--) - { - input_unreadch(str.at(idx)); - } - } -} - struct autosuggestion_context_t { wcstring search_string;