From ac7a461070fa6d810ff9cebd40d968bd262d96d9 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 25 Nov 2013 15:56:08 +0100 Subject: [PATCH 01/30] Cast size_t to unsigned long. printf expects unsigned long (%lu) argument, however, size_t doesn't have to be declared as such. As %zu is C99 (but not C++), it shouldn't be used directly. Instead, I have to cast value to the correct type. --- exec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exec.cpp b/exec.cpp index 6317b653c..b894ce690 100644 --- a/exec.cpp +++ b/exec.cpp @@ -188,7 +188,7 @@ void print_open_fds(void) { if (open_fds.at(i)) { - fprintf(stderr, "fd %lu\n", i); + fprintf(stderr, "fd %lu\n", (unsigned long) i); } } } From fcb3f3606502e559fd95908b5b0c1d36b0e0a060 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 25 Nov 2013 16:07:17 +0100 Subject: [PATCH 02/30] Ensure the loop in offset_of_next_item_fish_2_0 is executed. This ensures that timestamp will be initialized. --- history.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/history.cpp b/history.cpp index ff0a0865e..f8183f5d8 100644 --- a/history.cpp +++ b/history.cpp @@ -413,6 +413,13 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length bool has_timestamp = false; time_t timestamp; const char *interior_line; + + /* + * Ensure the loop is processed at least once. Otherwise, + * timestamp is unitialized. + */ + bool processed_once = false; + for (interior_line = next_line(line_start, end - line_start); interior_line != NULL && ! has_timestamp; interior_line = next_line(interior_line, end - interior_line)) @@ -427,8 +434,12 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length /* Try parsing a timestamp from this line. If we succeed, the loop will break. */ has_timestamp = parse_timestamp(interior_line, ×tamp); + + processed_once = true; } + assert(processed_once); + /* Skip this item if the timestamp is past our cutoff. */ if (has_timestamp && timestamp > cutoff_timestamp) { From 3eac5f9ab7f2ef5f86390a714f0eee48c6f2778b Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 25 Nov 2013 16:10:14 +0100 Subject: [PATCH 03/30] Fix io_buffer_t::print to take unsigned long argument. --- io.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io.cpp b/io.cpp index 1ee36e72d..3395942c2 100644 --- a/io.cpp +++ b/io.cpp @@ -71,7 +71,7 @@ void io_pipe_t::print() const void io_buffer_t::print() const { fprintf(stderr, "buffer %p (input: %s, size %lu)\n", out_buffer_ptr(), - is_input ? "yes" : "no", out_buffer_size()); + is_input ? "yes" : "no", (unsigned long) out_buffer_size()); } void io_buffer_t::read() From 312977d5a663a3153b019d571c6d9150e5a60a86 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 25 Nov 2013 16:15:36 +0100 Subject: [PATCH 04/30] Fix %lu for size_t in fish_tests.cpp --- fish_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fish_tests.cpp b/fish_tests.cpp index c75e9ea8f..321d109be 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -417,7 +417,7 @@ static void test_fork(void) size_t i, max = 100; for (i=0; i < 100; i++) { - printf("%lu / %lu\n", i+1, max); + printf("%lu / %lu\n", (unsigned long)(i+1), (unsigned long) max); /* Do something horrible to try to trigger an error */ #define THREAD_COUNT 8 #define FORK_COUNT 10 From cb86b8f8fcf64308b6f4599281c6197c547fa32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 22 Nov 2013 14:12:09 +0100 Subject: [PATCH 05/30] cd completion: handle not accessible directories --- share/functions/__fish_complete_cd.fish | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/share/functions/__fish_complete_cd.fish b/share/functions/__fish_complete_cd.fish index f54b5aaa7..64436a21a 100644 --- a/share/functions/__fish_complete_cd.fish +++ b/share/functions/__fish_complete_cd.fish @@ -30,9 +30,13 @@ function __fish_complete_cd -d "Completions for the cd command" for i in $mycdpath # Move to the initial directory first, # in case the CDPATH directory is relative + builtin cd $wd ^/dev/null + builtin cd $i ^/dev/null - builtin cd $wd - builtin cd $i + if test $status -ne 0 + # directory does not exists or missing permission + continue + end # What we would really like to do is skip descriptions if all # valid paths are in the same directory, but we don't know how to @@ -45,5 +49,5 @@ function __fish_complete_cd -d "Completions for the cd command" end end - builtin cd $wd + builtin cd $wd ^/dev/null end From 63a15e232bd598cbba6bfe2c1a5b16ba0d923235 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 00:07:18 -0800 Subject: [PATCH 06/30] Fix indentation in __fish_complete_cd --- share/functions/__fish_complete_cd.fish | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/share/functions/__fish_complete_cd.fish b/share/functions/__fish_complete_cd.fish index 64436a21a..1975eab20 100644 --- a/share/functions/__fish_complete_cd.fish +++ b/share/functions/__fish_complete_cd.fish @@ -30,13 +30,13 @@ function __fish_complete_cd -d "Completions for the cd command" for i in $mycdpath # Move to the initial directory first, # in case the CDPATH directory is relative - builtin cd $wd ^/dev/null - builtin cd $i ^/dev/null - - if test $status -ne 0 - # directory does not exists or missing permission - continue - end + builtin cd $wd ^/dev/null + builtin cd $i ^/dev/null + + if test $status -ne 0 + # directory does not exists or missing permission + continue + end # What we would really like to do is skip descriptions if all # valid paths are in the same directory, but we don't know how to @@ -49,5 +49,5 @@ function __fish_complete_cd -d "Completions for the cd command" end end - builtin cd $wd ^/dev/null + builtin cd $wd ^/dev/null end From 168d25e7806a147027a38c4e3135594c52bb7c2b Mon Sep 17 00:00:00 2001 From: d10n Date: Tue, 19 Nov 2013 14:42:05 -0500 Subject: [PATCH 07/30] Do not open CLI browsers when using fish_config. From the Python webbrowser documentation: "If text-mode browsers are used, the calling process will block until the user exits the browser." Running fish_config on an ssh server with no GUI browser will open a CLI browser which blocks and stops the server from handling requests. Using multiprocess to run the server in the background lets CLI browsers access the page, but the page is unusable. For now, disable CLI browsers and recommend opening the page in a graphical browser. In the future, maybe write a CLI utility to change prompts and delete history items. --- share/tools/web_config/webconfig.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/share/tools/web_config/webconfig.py b/share/tools/web_config/webconfig.py index f735a0268..88c1e042b 100755 --- a/share/tools/web_config/webconfig.py +++ b/share/tools/web_config/webconfig.py @@ -15,9 +15,15 @@ else: import http.server as SimpleHTTPServer import socketserver as SocketServer from urllib.parse import parse_qs + +# Disable CLI web browsers +term = os.environ.pop('TERM', None) import webbrowser +if term: + os.environ['TERM'] = term + import subprocess -import re, socket, os, sys, cgi, select, time, glob +import re, socket, cgi, select, time, glob try: import json except ImportError: From 0a54558ee24f2375266bf6c3c33a12602b344e5b Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sat, 2 Nov 2013 02:36:58 -0700 Subject: [PATCH 08/30] Update brew completion with new options --- share/completions/brew.fish | 73 +++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/share/completions/brew.fish b/share/completions/brew.fish index fe1ee764a..803d81f04 100644 --- a/share/completions/brew.fish +++ b/share/completions/brew.fish @@ -30,6 +30,14 @@ function __fish_brew_outdated_formulas brew outdated end +function __fish_brew_pinned_formulas + brew list --pinned +end + +function __fish_brew_taps + brew tap +end + ############ # commands # @@ -39,6 +47,15 @@ end complete -f -c brew -n '__fish_brew_needs_command' -a audit -d 'Check formula' complete -f -c brew -n '__fish_brew_using_command audit' -a '(__fish_brew_formulae)' +# bottle + +complete -f -c brew -n '__fish_brew_needs_command' -a bottle -d 'Create a binary package' +complete -f -c brew -n '__fish_brew_using_command bottle' -l 'homebrew-developer' -d 'Output developer debug information' +complete -f -c brew -n '__fish_brew_using_command bottle' -l 'no-revision' -d 'Do not bump the bottle revision number' +complete -f -c brew -n '__fish_brew_using_command bottle' -l 'rb' -d 'Write bottle block to a Ruby source file' +complete -f -c brew -n '__fish_brew_using_command bottle' -l 'write' -d 'Write bottle block to formula file' +complete -f -c brew -n '__fish_brew_using_command bottle' -l 'merge' -d 'Merge multiple bottle outputs' + # cat complete -f -c brew -n '__fish_brew_needs_command' -a cat -d 'Display formula' complete -f -c brew -n '__fish_brew_using_command cat' -a '(__fish_brew_formulae)' @@ -46,8 +63,9 @@ complete -f -c brew -n '__fish_brew_using_command cat' -a '(__fish_brew_formulae # cleanup complete -f -c brew -n '__fish_brew_needs_command' -a cleanup -d 'Remove old installed versions' complete -f -c brew -n '__fish_brew_using_command cleanup' -l force -d 'Remove out-of-date keg-only brews as well' -complete -f -c brew -n '__fish_brew_using_command cleanup' -s n -d 'Dry run' -complete -f -c brew -n '__fish_brew_using_command cleanup' -s s -d 'Scrubs the cache' +complete -f -c brew -n '__fish_brew_using_command cleanup' -l dry-run -d 'Show what files would be removed' +complete -f -c brew -n '__fish_brew_using_command cleanup' -s n -d 'Show what files would be removed' +complete -f -c brew -n '__fish_brew_using_command cleanup' -s s -d 'Scrub the cache' complete -f -c brew -n '__fish_brew_using_command cleanup' -a '(__fish_brew_installed_formulas)' # create @@ -55,6 +73,8 @@ complete -f -c brew -n '__fish_brew_needs_command' -a create -d 'Create new form complete -f -c brew -n '__fish_brew_using_command create' -l cmake -d 'Use template for CMake-style build' complete -f -c brew -n '__fish_brew_using_command create' -l autotools -d 'Use template for Autotools-style build' complete -f -c brew -n '__fish_brew_using_command create' -l no-fetch -d 'Don\'t download URL' +complete -f -c brew -n '__fish_brew_using_command create' -l set-name -d 'Override name autodetection' +complete -f -c brew -n '__fish_brew_using_command create' -l set-version -d 'Override version autodetection' # deps complete -f -c brew -n '__fish_brew_needs_command' -a deps -d 'Show a formula\'s dependencies' @@ -62,6 +82,7 @@ complete -f -c brew -n '__fish_brew_using_command deps' -l 1 -d 'Show only 1 lev complete -f -c brew -n '__fish_brew_using_command deps' -s n -d 'Show in topological order' complete -f -c brew -n '__fish_brew_using_command deps' -l tree -d 'Show dependencies as tree' complete -f -c brew -n '__fish_brew_using_command deps' -l all -d 'Show dependencies for all formulae' +complete -f -c brew -n '__fish_brew_using_command deps' -l installed -d 'Show dependencies for installed formulae' complete -f -c brew -n '__fish_brew_using_command deps' -a '(__fish_brew_formulae)' # diy @@ -70,7 +91,10 @@ complete -f -c brew -n '__fish_brew_using_command diy' -l set-name -d 'Set name complete -f -c brew -n '__fish_brew_using_command diy' -l set-version -d 'Set version of package' complete -f -c brew -n '__fish_brew_needs_command' -a 'doctor' -d 'Check your system for problems' + +# edit complete -f -c brew -n '__fish_brew_needs_command' -a 'edit' -d 'Open brew/formula for editing' +complete -f -c brew -n '__fish_brew_using_command edit' -a '(__fish_brew_formulae)' # fetch complete -f -c brew -n '__fish_brew_needs_command' -a fetch -d 'Download source for formula' @@ -78,6 +102,7 @@ complete -f -c brew -n '__fish_brew_using_command fetch' -l force -d 'Remove a p complete -f -c brew -n '__fish_brew_using_command fetch' -l HEAD -d 'Download the HEAD version from a VCS' complete -f -c brew -n '__fish_brew_using_command fetch' -l deps -d 'Also download dependencies' complete -f -c brew -n '__fish_brew_using_command fetch' -s v -d 'Make HEAD checkout verbose' +complete -f -c brew -n '__fish_brew_using_command fetch' -l build-from-source -d 'Fetch source package instead of bottle' complete -f -c brew -n '__fish_brew_using_command fetch' -a '(__fish_brew_formulae)' complete -f -c brew -n '__fish_brew_needs_command' -a 'help' -d 'Display help' @@ -101,25 +126,42 @@ complete -f -c brew -n '__fish_brew_using_command install' -l fresh -d 'Don\'t r complete -f -c brew -n '__fish_brew_using_command install' -l use-clang -d 'Attempt to compile using clang' complete -f -c brew -n '__fish_brew_using_command install' -l use-gcc -d 'Attempt to compile using GCC' complete -f -c brew -n '__fish_brew_using_command install' -l use-llvm -d 'Attempt to compile using the LLVM' +complete -f -c brew -n '__fish_brew_using_command install' -l cc -a "clang gcc-4.0 gcc-4.2 gcc-4.3 gcc-4.4 gcc-4.5 gcc-4.6 gcc-4.7 gcc-4.8 gcc-4.9 llvm-gcc" -d 'Attempt to compile using the specified compiler' complete -f -c brew -n '__fish_brew_using_command install' -l build-from-source -d 'Compile from source even if a bottle is provided' complete -f -c brew -n '__fish_brew_using_command install' -l devel -d 'Install the development version of formula' complete -f -c brew -n '__fish_brew_using_command install' -l HEAD -d 'Install the HEAD version from VCS' complete -f -c brew -n '__fish_brew_using_command install' -l interactive -d 'Download and patch formula, then open a shell' +complete -f -c brew -n '__fish_brew_using_command install' -l env -a "std super" -d 'Force the specified build environment' +complete -f -c brew -n '__fish_brew_using_command install' -l build-bottle -d 'Optimize for a generic CPU architecture' +complete -f -c brew -n '__fish_brew_using_command install' -l bottle-arch -a 'core core2 penryn g3 g4 g4e g5' -d 'Optimize for the specified CPU architecture' complete -c brew -n '__fish_brew_using_command install' -a '(__fish_brew_formulae)' # link complete -f -c brew -n '__fish_brew_needs_command' -a 'link ln' -d 'Symlink installed formula' +complete -f -c brew -n '__fish_brew_using_command link' -l overwrite -d 'Overwrite existing files' +complete -f -c brew -n '__fish_brew_using_command ln' -l overwrite -d 'Overwrite existing files' +complete -f -c brew -n '__fish_brew_using_command link' -l dry-run -d 'Show what files would be linked or overwritten' +complete -f -c brew -n '__fish_brew_using_command ln' -l dry-run -d 'Show what files would be linked or overwritten' +complete -f -c brew -n '__fish_brew_using_command link' -l force -d 'Allow keg-only formulae to be linked' +complete -f -c brew -n '__fish_brew_using_command ln' -l force -d 'Allow keg-only formulae to be linked' complete -f -c brew -n '__fish_brew_using_command link' -a '(__fish_brew_installed_formulas)' complete -f -c brew -n '__fish_brew_using_command ln' -a '(__fish_brew_installed_formulas)' +# linkapps +complete -f -c brew -n '__fish_brew_needs_command' -a linkapps -d 'Symlink .app bundles into /Applications' +complete -f -c brew -n '__fish_brew_using_command linkapps' -l local -d 'Link .app bundles into ~/Applications instead' + # list complete -f -c brew -n '__fish_brew_needs_command' -a 'list ls' -d 'List all installed formula' complete -f -c brew -n '__fish_brew_using_command list' -l unbrewed -d 'List all files in the Homebrew prefix not installed by brew' complete -f -c brew -n '__fish_brew_using_command list' -l versions -d 'Show the version number' +complete -f -c brew -n '__fish_brew_using_command list' -l pinned -d 'Show the versions of pinned formulae' complete -c brew -n '__fish_brew_using_command list' -a '(__fish_brew_formulae)' + #ls complete -f -c brew -n '__fish_brew_using_command ls' -l unbrewed -d 'List all files in the Homebrew prefix not installed by brew' complete -f -c brew -n '__fish_brew_using_command ls' -l versions -d 'Show the version number' +complete -f -c brew -n '__fish_brew_using_command ls' -l pinned -d 'Show the versions of pinned formulae' complete -c brew -n '__fish_brew_using_command ls' -a '(__fish_brew_formulae)' # log @@ -132,12 +174,19 @@ complete -c brew -n '__fish_brew_using_command missing' -a '(__fish_brew_formula # options complete -f -c brew -n '__fish_brew_needs_command' -a options -d 'Display install options for formula' +complete -f -c brew -n '__fish_brew_using_command options' -l compact -d 'Show all options as a space-delimited list' +complete -f -c brew -n '__fish_brew_using_command options' -l all -d 'Show options for all formulae' +complete -f -c brew -n '__fish_brew_using_command options' -l installed -d 'Show options for all installed formulae' complete -c brew -n '__fish_brew_using_command options' -a '(__fish_brew_formulae)' -d 'formula' # outdated complete -f -c brew -n '__fish_brew_needs_command' -a outdated -d 'Show formula that have updated versions' complete -f -c brew -n '__fish_brew_using_command outdated' -l quiet -d 'Display only names' +# pin +complete -f -c brew -n '__fish_brew_needs_command' -a pin -d 'Pin the specified formulae to their current versions' +complete -f -c brew -n '__fish_brew_using_command pin' -a '(__fish_brew_installed_formulas)' -d 'formula' + # prune complete -f -c brew -n '__fish_brew_needs_command' -a prune -d 'Remove dead symlinks' @@ -148,12 +197,17 @@ complete -f -c brew -n '__fish_brew_using_command search' -l fink -d 'Search on complete -f -c brew -n '__fish_brew_using_command -S' -l macports -d 'Search on MacPorts' complete -f -c brew -n '__fish_brew_using_command -S' -l fink -d 'Search on Fink' +# sh +complete -f -c brew -n '__fish_brew_needs_command' -a sh -d 'Instantiate a Homebrew build enviornment' +complete -f -c brew -n '__fish_brew_using_command sh' -l env=std -d 'Use stdenv instead of superenv' + # tap complete -f -c brew -n '__fish_brew_needs_command' -a tap -d 'Tap a new formula repository on GitHub' +complete -f -c brew -n '__fish_brew_using_command tap' -l repair -d 'Create and prune tap symlinks as appropriate' # test complete -f -c brew -n '__fish_brew_needs_command' -a test -d 'Run tests for formula' -complete -c brew -n '__fish_brew_using_command test' -a '(__fish_brew_formulae)' -d 'formula' +complete -f -c brew -n '__fish_brew_using_command test' -a '(__fish_brew_installed_formulas)' -d 'formula' # uninstall complete -f -c brew -n '__fish_brew_needs_command' -a 'uninstall remove rm' -d 'Uninstall formula' @@ -166,10 +220,19 @@ complete -f -c brew -n '__fish_brew_using_command rm' -l force -d 'Delete all in # unlink complete -f -c brew -n '__fish_brew_needs_command' -a unlink -d 'Unlink formula' -complete -c brew -n '__fish_brew_using_command unlink' -a '(__fish_brew_installed_formulas)' +complete -f -c brew -n '__fish_brew_using_command unlink' -a '(__fish_brew_installed_formulas)' + +# unlinkapps +complete -f -c brew -n '__fish_brew_needs_command' -a unlinkapps -d 'Remove links created by brew linkapps' +complete -f -c brew -n '__fish_brew_using_command unlinkapps' -l local -d 'Remove links from ~/Applications created by brew linkapps' + +# unpin +complete -f -c brew -n '__fish_brew_needs_command' -a unpin -d 'Unpin specified formulae' +complete -f -c brew -n '__fish_brew_using_command unpin' -a '(__fish_brew_pinned_formulas)' # untap complete -f -c brew -n '__fish_brew_needs_command' -a untap -d 'Remove a tapped repository' +complete -f -c brew -n '__fish_brew_using_command untap' -a '(__fish_brew_taps)' # update complete -f -c brew -n '__fish_brew_needs_command' -a update -d 'Fetch newest version of Homebrew and formulas' @@ -182,6 +245,7 @@ complete -f -c brew -n '__fish_brew_using_command upgrade' -a '(__fish_brew_outd # uses complete -f -c brew -n '__fish_brew_needs_command' -a uses -d 'Show formulas that depend on specified formula' complete -f -c brew -n '__fish_brew_using_command uses' -l installed -d 'List only installed formulae' +complete -f -c brew -n '__fish_brew_using_command uses' -l recursive -d 'Resolve more than one level of dependencies' complete -c brew -n '__fish_brew_using_command uses' -a '(__fish_brew_formulae)' # versions @@ -194,6 +258,7 @@ complete -c brew -n '__fish_brew_using_command versions' -a '(__fish_brew_formul # switches # ############ complete -f -c brew -n '__fish_brew_needs_command' -a '-v --version' -d 'Print version number of brew' +complete -f -c brew -n '__fish_brew_needs_command' -l env -x -d 'Show Homebrew a summary of the build environment' complete -f -c brew -n '__fish_brew_needs_command' -l repository -x -d 'Display where Homebrew\'s .git directory is located' complete -f -c brew -n '__fish_brew_needs_command' -l config -x -d 'Show Homebrew and system configuration' From 2813dcc6cc756f20548b4cfadfa2facd6c126f22 Mon Sep 17 00:00:00 2001 From: d10n Date: Sun, 17 Nov 2013 07:49:48 -0500 Subject: [PATCH 09/30] On short prompts, commands wider than the terminal do not reposition to start on their own lines. --- screen.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/screen.cpp b/screen.cpp index d02fc438a..fdf462e2b 100644 --- a/screen.cpp +++ b/screen.cpp @@ -1215,7 +1215,14 @@ static screen_layout_t compute_layout(screen_t *s, result.left_prompt_space = left_prompt_width; // See remark about for why we can't use the right prompt here //result.right_prompt = right_prompt; - result.prompts_get_own_line = true; + + // If the command wraps, and the prompt is not short, place the command on its own line. + // A short prompt is 33% or less of the terminal's width. + const size_t prompt_percent_width = (100 * left_prompt_width) / screen_width; + if (left_prompt_width + first_command_line_width + 1 > screen_width && prompt_percent_width > 33) { + result.prompts_get_own_line = true; + } + done = true; } From ded64758d5972aca8c599278cd13d98b4b02906e Mon Sep 17 00:00:00 2001 From: d10n Date: Sun, 17 Nov 2013 07:56:47 -0500 Subject: [PATCH 10/30] Fix wide character wrapping. The intention of the block removed appears to be to indent wrapped lines to the column the line started at. What actually happens is that all wrapped lines wrap to column 0. After adding the sticky short prompt feature, the block removed caused a bug with wrapping wide characters in addition to not appearing to change anything else. Wide characters would change between wrapping to column 0 and the column the command started at, depending on what column the wide character was at before wrapping. I am keeping the existing behavior rather than restoring the block's original intention. If the original intention should be restored, it should be on a different branch. --- screen.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/screen.cpp b/screen.cpp index fdf462e2b..711aebabd 100644 --- a/screen.cpp +++ b/screen.cpp @@ -537,10 +537,6 @@ static void s_desired_append_char(screen_t *s, s->desired.add_line(); s->desired.cursor.y++; s->desired.cursor.x=0; - for (size_t i=0; i < prompt_width; i++) - { - s_desired_append_char(s, L' ', 0, indent, prompt_width); - } } line_t &line = s->desired.line(line_no); From 5b3397359f7f9bde9170246893c2bffd742b4f06 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 01:39:16 -0800 Subject: [PATCH 11/30] Fix support for backslash-newline in double quotes in unescape functions. Makes tests pass again. --- common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common.cpp b/common.cpp index f221b3ca2..3fce76d66 100644 --- a/common.cpp +++ b/common.cpp @@ -1594,6 +1594,7 @@ static bool unescape_string_internal(const wchar_t * const input, const size_t i { /* Swallow newline */ to_append = NOT_A_WCHAR; + input_position += 1; /* Skip over the backslash */ break; } From 8d1667e9e8a7ad941419b017e9118d3f2c3f5af7 Mon Sep 17 00:00:00 2001 From: David Adam Date: Mon, 25 Nov 2013 00:10:41 +0800 Subject: [PATCH 12/30] more detailed debugging when terminal type cannot be found Ref: #1060 --- input.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/input.cpp b/input.cpp index b587fcbac..7b63db1de 100644 --- a/input.cpp +++ b/input.cpp @@ -346,13 +346,18 @@ int input_init() input_common_init(&interrupt_handler); + const env_var_t term = env_get_string(L"TERM"); int errret; if (setupterm(0, STDOUT_FILENO, &errret) == ERR) { debug(0, _(L"Could not set up terminal")); + if (errret == 0) + { + debug(0, _(L"Check that your terminal type, '%ls', is supported on this system"), + term.c_str()); + } exit_without_destructors(1); } - const env_var_t term = env_get_string(L"TERM"); assert(! term.missing()); output_set_term(term); From 2c39d5b6c00f6f73af1342eb8f76866aae4de1a3 Mon Sep 17 00:00:00 2001 From: David Adam Date: Tue, 26 Nov 2013 11:39:54 +0800 Subject: [PATCH 13/30] fall back to ANSI terminal type if setupterm fails Closes: https://github.com/fish-shell/fish-shell/issues/1060 'ansi' should always be present (tested on Solaris, Linux, FreeBSD, Darwin). Also overrides TERM so that other programs behave consistently e.g. fish_pager. The error message makes no specific mention of terminfo or termcap as these vary across operating systems. (r+ @ridiculousfish with thanks) --- input.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/input.cpp b/input.cpp index 7b63db1de..12f7580d6 100644 --- a/input.cpp +++ b/input.cpp @@ -60,6 +60,8 @@ #include "intern.h" #include +#define DEFAULT_TERM L"ansi" + /** Struct representing a keybinding. Returned by input_get_mappings. */ @@ -355,8 +357,19 @@ int input_init() { debug(0, _(L"Check that your terminal type, '%ls', is supported on this system"), term.c_str()); + debug(0, _(L"Attempting to use '%ls' instead"), DEFAULT_TERM); + env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT); + const std::string default_term = wcs2string(DEFAULT_TERM); + if (setupterm(default_term.c_str(), STDOUT_FILENO, &errret) == ERR) + { + debug(0, _(L"Could not set up terminal")); + exit_without_destructors(1); + } + } + else + { + exit_without_destructors(1); } - exit_without_destructors(1); } assert(! term.missing()); output_set_term(term); From 51214177256be1127d793cbc1b40aec04d6856d8 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 10:52:03 -0800 Subject: [PATCH 14/30] Fix for annoying error message when converting out of range escape https://github.com/fish-shell/fish-shell/issues/1107 --- common.cpp | 2 +- fish_tests.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/common.cpp b/common.cpp index 3fce76d66..b7cdedc87 100644 --- a/common.cpp +++ b/common.cpp @@ -1197,7 +1197,7 @@ static size_t read_unquoted_escape(const wchar_t *input, wcstring *result, bool case L'U': { chars=8; - max_val = WCHAR_MAX; + max_val = mini(WCHAR_MAX, 0x10FFFF); // Largest Unicode code point - see #1107 break; } diff --git a/fish_tests.cpp b/fish_tests.cpp index 321d109be..b226d3079 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -144,6 +144,22 @@ static void test_unescape_sane() err(L"In unescaping '%ls', expected '%ls' but got '%ls'\n", tests[i].input, tests[i].expected, output.c_str()); } } + + // test for overflow + if (unescape_string(L"echo \\UFFFFFF", &output, UNESCAPE_DEFAULT)) + { + err(L"Should not have been able to unescape \\UFFFFFF\n"); + } + if (unescape_string(L"echo \\U110000", &output, UNESCAPE_DEFAULT)) + { + err(L"Should not have been able to unescape \\U110000\n"); + } + if (! unescape_string(L"echo \\U10FFFF", &output, UNESCAPE_DEFAULT)) + { + err(L"Should have been able to unescape \\U10FFFF\n"); + } + + } /** From b04fc5a39e59a0889b4fffd3e0456582ae923003 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 10:56:43 -0800 Subject: [PATCH 15/30] Add missing const cast for setup_term https://github.com/fish-shell/fish-shell/issues/1142 --- input.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.cpp b/input.cpp index 12f7580d6..51f658afc 100644 --- a/input.cpp +++ b/input.cpp @@ -360,7 +360,7 @@ int input_init() debug(0, _(L"Attempting to use '%ls' instead"), DEFAULT_TERM); env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT); const std::string default_term = wcs2string(DEFAULT_TERM); - if (setupterm(default_term.c_str(), STDOUT_FILENO, &errret) == ERR) + if (setupterm(const_cast(default_term.c_str()), STDOUT_FILENO, &errret) == ERR) { debug(0, _(L"Could not set up terminal")); exit_without_destructors(1); From 9f5547327e3710303d3cb40b4bc55e74653a70ee Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 23:18:12 -0800 Subject: [PATCH 16/30] Fix for compile error identified in https://github.com/fish-shell/fish-shell/issues/1142 --- common.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common.cpp b/common.cpp index b7cdedc87..9608e31eb 100644 --- a/common.cpp +++ b/common.cpp @@ -1197,7 +1197,12 @@ static size_t read_unquoted_escape(const wchar_t *input, wcstring *result, bool case L'U': { chars=8; - max_val = mini(WCHAR_MAX, 0x10FFFF); // Largest Unicode code point - see #1107 + max_val = WCHAR_MAX; + + // Don't exceed the largest Unicode code point - see #1107 + if (0x10FFFF < max_val) + max_val = (wchar_t)0x10FFFF; + break; } From 84483b4aac7cfd5d59b5a1050f5d11a5f052af50 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 26 Nov 2013 23:56:47 -0800 Subject: [PATCH 17/30] Fix for process expansion off the main thread in syntax highlighting (#1143) --- highlight.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/highlight.cpp b/highlight.cpp index 8d46feb33..2e1543877 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -710,7 +710,7 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command { /* Command. First check that the command actually exists. */ wcstring local_cmd = tok_last(&tok); - bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES); + bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS); if (! expanded || has_expand_reserved(cmd.c_str())) { /* We can't expand this cmd, ignore it */ @@ -873,7 +873,7 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio { /* We can possibly handle this specially */ wcstring dir = parsed_arguments.back(); - if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) + if (expand_one(dir, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) { handled = true; bool is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); @@ -997,7 +997,7 @@ static void tokenize(const wchar_t * const buff, std::vector &color, const if (cmd == L"cd") { wcstring dir = tok_last(&tok); - if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) + if (expand_one(dir, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) { int is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); if (!is_help && ! is_potential_cd_path(dir, working_directory, PATH_EXPAND_TILDE, NULL)) @@ -1182,7 +1182,7 @@ static void tokenize(const wchar_t * const buff, std::vector &color, const case TOK_STRING: { target_str = tok_last(&tok); - if (expand_one(target_str, EXPAND_SKIP_CMDSUBST)) + if (expand_one(target_str, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) { target = target_str.c_str(); } From 0c4dab54f1544dff96c0e2d01f4c661e07f7fa49 Mon Sep 17 00:00:00 2001 From: David Adam Date: Wed, 27 Nov 2013 17:58:43 +0800 Subject: [PATCH 18/30] __fish_complete_man: Use awk to parse output of apropos Closes #960. Uses pattern matching rather than OS detection. Works with BSD awk, GNU awk and Solaris' nawk. --- share/functions/__fish_complete_man.fish | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/share/functions/__fish_complete_man.fish b/share/functions/__fish_complete_man.fish index a5e4fa40f..59c8c24eb 100644 --- a/share/functions/__fish_complete_man.fish +++ b/share/functions/__fish_complete_man.fish @@ -21,7 +21,33 @@ function __fish_complete_man set section $section"[^)]*" # Do the actual search - apropos (commandline -ct) ^/dev/null | sgrep \^(commandline -ct) | sed -n -e 's/\([^ ]*\).*(\('$section'\)) *- */\1'\t'\2: /p' + apropos (commandline -ct) ^/dev/null | awk ' + BEGIN { FS="[\t ]- "; OFS="\t"; } + # BSD/Darwin + /^[^( \t]+\('$section'\)/ { + split($1, pages, ", "); + for (i in pages) { + page = pages[i]; + sub(/[ \t]+/, "", page); + paren = index(page, "("); + name = substr(page, 1, paren - 1); + sect = substr(page, paren + 1, length(page) - paren - 1); + print name, sect ": " $2; + } + } + # Linux + /^[^( \t]+ \('$section'\)/ { + split($1, t, " "); + sect = substr(t[2], 2, length(t[2]) - 2); + print t[1], sect ": " $2; + } + # Solaris + /^[^( \t]+\t+[^\(\t]/ { + split($1, t, " "); + sect = substr(t[3], 2, length(t[3]) - 2); + print t[2], sect ": " $2; + } + ' end end From 9862eb930d941a6fb93471bbb8e125076e95103a Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 27 Nov 2013 11:34:00 +0100 Subject: [PATCH 19/30] Use sed instead of sh for Informative Git Prompt. Informative Git Prompt assumes that sh is bash compatible, but that's not the case for FreeBSD. Fixes #1140. --- share/functions/__fish_git_prompt.fish | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/share/functions/__fish_git_prompt.fish b/share/functions/__fish_git_prompt.fish index e66472846..3012f8ef4 100644 --- a/share/functions/__fish_git_prompt.fish +++ b/share/functions/__fish_git_prompt.fish @@ -205,7 +205,7 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi set upstream svn+git # default upstream is SVN if available, else git # Save the config key (without .url) for later use - set -l remote_prefix (/bin/sh -c 'echo "${1%.url}"' -- $key) + set -l remote_prefix (echo $key | sed 's/\.url$//') set svn_prefix $svn_prefix $remote_prefix end end @@ -242,11 +242,11 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi set -l svn_upstream (git log --first-parent -1 --grep="^git-svn-id: \($svn_url_pattern\)" ^/dev/null) if test (count $svn_upstream) -ne 0 echo $svn_upstream[-1] | read -l _ svn_upstream _ - set svn_upstream (/bin/sh -c 'echo "${1%@*}"' -- $svn_upstream) + set svn_upstream (echo $svn_upstream | sed 's/@.*//') set -l cur_prefix for i in (seq (count $svn_remote)) set -l remote $svn_remote[$i] - set -l mod_upstream (/bin/sh -c 'echo "${1#$2}"' -- $svn_upstream $remote) + set -l mod_upstream (echo $svn_upstream | sed "s/$remote//") if test "$svn_upstream" != "$mod_upstream" # we found a valid remote set svn_upstream $mod_upstream @@ -263,14 +263,14 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi set upstream git-svn end else - set upstream (/bin/sh -c 'val=${1#/branches}; echo "${val#/}"' -- $svn_upstream) + set upstream (echo $svn_upstream | sed 's|/branches||; s|/||g') # Use fetch config to fix upstream set -l fetch_val (command git config "$cur_prefix".fetch) if test -n "$fetch_val" set -l IFS : echo "$fetch_val" | read -l trunk pattern - set upstream (/bin/sh -c 'echo "${1%/$2}"' -- $pattern $trunk)/$upstream + set upstream (echo $pattern | sed -e "s|/$trunk\$||") /$upstream end end else if test $upstream = svn+git @@ -426,7 +426,7 @@ function __fish_git_prompt --description "Prompt function for Git" if test -n "$u" set u "$___fish_git_prompt_color_untrackedfiles$u$___fish_git_prompt_color_untrackedfiles_done" end - set b (/bin/sh -c 'echo "${1#refs/heads/}"' -- $b) + set b (echo $b | sed 's|refs/heads/||') if test -n "$b" set b "$branch_color$b$branch_done" end From 44d13869ad21132796f3cf55e4b8ed3fd32cac97 Mon Sep 17 00:00:00 2001 From: Jelte Fennema Date: Tue, 19 Nov 2013 19:45:21 +0100 Subject: [PATCH 20/30] Add eselect, rc-update and rc-service completions. (These are utilities used by Gentoo Linux) Disable php completion for the 4th part of the command, since php-eselect is differently designed and causes errors Closes #1131. --- share/completions/eselect.fish | 74 +++++++++++++++++++ share/completions/rc-service.fish | 20 +++++ share/completions/rc-update.fish | 33 +++++++++ share/completions/service.fish | 10 +-- .../__fish_complete_service_actions.fish | 7 ++ .../__fish_number_of_cmd_args_wo_opts.fish | 4 + share/functions/__fish_print_cmd_args.fish | 3 + ...__fish_print_cmd_args_without_options.fish | 3 + .../functions/__fish_print_service_names.fish | 10 +++ 9 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 share/completions/eselect.fish create mode 100644 share/completions/rc-service.fish create mode 100644 share/completions/rc-update.fish create mode 100644 share/functions/__fish_complete_service_actions.fish create mode 100644 share/functions/__fish_number_of_cmd_args_wo_opts.fish create mode 100644 share/functions/__fish_print_cmd_args.fish create mode 100644 share/functions/__fish_print_cmd_args_without_options.fish create mode 100644 share/functions/__fish_print_service_names.fish diff --git a/share/completions/eselect.fish b/share/completions/eselect.fish new file mode 100644 index 000000000..5ecdcd6f5 --- /dev/null +++ b/share/completions/eselect.fish @@ -0,0 +1,74 @@ +function __fish_eselect_cmd + eselect --brief --colour=no $argv +end + +function __fish_complete_eselect_modules + set -l sedregexp 's/^ ([a-zA-Z0-9_-]*)[ ]*/\1\t/g' + __fish_eselect_cmd modules list | sgrep '^ ' | sed -r $sedregexp +end + +function __fish_complete_eselect_actions + set -l sedregexp 's/^ ([a-zA-Z0-9_-]*)[ ]*/\1\t/g' + set -l cmdl (commandline -poc) + __fish_eselect_cmd $cmdl[2..-1] usage | sgrep '^ [^ -]' | sed -r $sedregexp +end + +function __fish_complete_eselect_action_options + set -l parseregexp 's/^ ([a-zA-Z0-9_-]*)[ ]*/\1\t/g' + set -l cmdl (commandline -poc) + + # Disable further php completion + if [ (__fish_print_cmd_args_without_options)[2] = 'php' ] + return + end + + switch $cmdl[-1] + case -'*' + return + end + + set -l findregexp '/^ '$cmdl[-1]'/,/^ [^ ]/p' + + set cmdl[-1] usage + __fish_eselect_cmd $cmdl[2..-1] | sed -n -re $findregexp | sgrep '^ --' | sed -re $parseregexp +end + +function __fish_complete_eselect_targets + set -l sedregexp 's/^ \[([0-9]+)\][ ]*/\1\t/g' + set -l cmdl (commandline -poc) + + # Disable further php completion + # https://github.com/fish-shell/fish-shell/pull/1131 + if [ (__fish_print_cmd_args_without_options)[2] = 'php' ] + return + end + + switch $cmdl[-1] + case -'*' + set cmdl[-2] list + case '*' + set cmdl[-1] list + end + + eselect --colour=no $cmdl[2..-1] | sgrep '^ [^ -]' | sed -r $sedregexp +end + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 1" \ + -xa '(__fish_complete_eselect_modules)' + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 1" \ + -l brief -d 'Make output shorter' + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 1" \ + -l colour \ + -d "= Enable or disable colour output (default 'auto')" + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 2" \ + -xa '(__fish_complete_eselect_actions)' + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 3" \ + -xa '(__fish_complete_eselect_targets)' + +complete -c eselect -n "test (__fish_number_of_cmd_args_wo_opts) = 3" \ + -xa '(__fish_complete_eselect_action_options)' + diff --git a/share/completions/rc-service.fish b/share/completions/rc-service.fish new file mode 100644 index 000000000..a88856860 --- /dev/null +++ b/share/completions/rc-service.fish @@ -0,0 +1,20 @@ +# First argument is the names of the service, i.e. a file in /etc/init.d +complete -c rc-service -n "test (__fish_number_of_cmd_args_wo_opts) = 1" \ + -xa "(__fish_print_service_names)" --description "Service name" + +# The second argument is what action to take with the service +complete -c rc-service -n "test (__fish_number_of_cmd_args_wo_opts) -gt 1" \ + -xa "(__fish_complete_service_actions)" + +# Complete rc-service the options +complete -c rc-service -s e -l exists -d 'Tests if the service exists or not' +complete -c rc-service -s i -l ifexists \ + -d 'If the service exists, then run the command' +complete -c rc-service -s l -l list -d 'List all available services' +complete -c rc-service -s r -l resolve \ + -d 'Resolve the service name to an init script' +complete -c rc-service -s h -l help -d 'Display the help output' +complete -c rc-service -s C -l nocolor -d 'Disable color output' +complete -c rc-service -s V -l version -d 'Display software version' +complete -c rc-service -s v -l verbose -d 'Run verbosely' +complete -c rc-service -s q -l quiet -d 'Run quietly (Does not affect errors)' diff --git a/share/completions/rc-update.fish b/share/completions/rc-update.fish new file mode 100644 index 000000000..f2339699d --- /dev/null +++ b/share/completions/rc-update.fish @@ -0,0 +1,33 @@ +function __fish_complete_rc-update_actions + set -l actions add \ + 'Add the service to the runlevel or the current one if non given' + set -l actions $actions del \ + 'Delete the service from the runlevel or the current one if non given' + set -l actions $actions show \ + 'Show all enabled services and the runlevels they belong to' + printf "%s\t%s\n" $actions +end + +function __fish_complete_rc-update_runlevels + set -l levels sysinit \ + 'First startup runlevel' \ + boot \ + 'Second startup runlevel' \ + default \ + 'Last startup runlevel' \ + shutdown \ + 'Runlevel for stutting down' + printf "%s\t%s\n" $levels +end + +# The first argument is what action to take with the service +complete -c rc-update -n "test (__fish_number_of_cmd_args_wo_opts) = 1" \ + -xa "(__fish_complete_rc-update_actions)" + +# The second argument is the names of the service, i.e. a file in /etc/init.d +complete -c rc-update -n "test (__fish_number_of_cmd_args_wo_opts) = 2" \ + -xa "(__fish_print_service_names)" --description "Service name" + +# The third argument is the names of the service, i.e. a file in /etc/init.d +complete -c rc-update -n "test (__fish_number_of_cmd_args_wo_opts) = 3" \ + -xa "(__fish_complete_rc-update_runlevels)" diff --git a/share/completions/service.fish b/share/completions/service.fish index 2f3614370..4914f97b1 100644 --- a/share/completions/service.fish +++ b/share/completions/service.fish @@ -1,13 +1,5 @@ -function __fish_service_print_names - if type -f systemctl >/dev/null - command systemctl list-units -t service | cut -d ' ' -f 1 | grep '\.service$' | sed -e 's/\.service$//' - end - - command ls /etc/init.d -end - # Fist argument is the names of the service, i.e. a file in /etc/init.d -complete -c service -n "test (count (commandline -poc)) = 1" -xa "(__fish_service_print_names)" --description "Service name" +complete -c service -n "test (count (commandline -poc)) = 1" -xa "(__fish_print_service_names)" --description "Service name" #The second argument is what action to take with the service complete -c service -n "test (count (commandline -poc)) -gt 1" -xa '$__fish_service_commands' diff --git a/share/functions/__fish_complete_service_actions.fish b/share/functions/__fish_complete_service_actions.fish new file mode 100644 index 000000000..ab91f7860 --- /dev/null +++ b/share/functions/__fish_complete_service_actions.fish @@ -0,0 +1,7 @@ +function __fish_complete_service_actions -d "Print a list of all basic service \ + actions" + set -l actions start 'Start the service' + set -l actions $actions stop 'Stop the service' + set -l actions $actions restart 'Restart the service' + printf "%s\t%s\n" $actions +end diff --git a/share/functions/__fish_number_of_cmd_args_wo_opts.fish b/share/functions/__fish_number_of_cmd_args_wo_opts.fish new file mode 100644 index 000000000..83e3d2fa2 --- /dev/null +++ b/share/functions/__fish_number_of_cmd_args_wo_opts.fish @@ -0,0 +1,4 @@ +function __fish_number_of_cmd_args_wo_opts + count (__fish_print_cmd_args_without_options) +end + diff --git a/share/functions/__fish_print_cmd_args.fish b/share/functions/__fish_print_cmd_args.fish new file mode 100644 index 000000000..eaafe65a3 --- /dev/null +++ b/share/functions/__fish_print_cmd_args.fish @@ -0,0 +1,3 @@ +function __fish_print_cmd_args + commandline -poc +end diff --git a/share/functions/__fish_print_cmd_args_without_options.fish b/share/functions/__fish_print_cmd_args_without_options.fish new file mode 100644 index 000000000..dadabc2a8 --- /dev/null +++ b/share/functions/__fish_print_cmd_args_without_options.fish @@ -0,0 +1,3 @@ +function __fish_print_cmd_args_without_options + __fish_print_cmd_args | grep '^[^-]' +end diff --git a/share/functions/__fish_print_service_names.fish b/share/functions/__fish_print_service_names.fish new file mode 100644 index 000000000..3eeb00155 --- /dev/null +++ b/share/functions/__fish_print_service_names.fish @@ -0,0 +1,10 @@ +function __fish_print_service_names -d 'All services known to the system' + if type -f systemctl >/dev/null + command systemctl list-units -t service | cut -d ' ' -f 1 | grep '\.service$' | sed -e 's/\.service$//' + else if type -f rc-service + command rc-service -l + else + command ls /etc/init.d + end +end + From 591abd340b9085b923b9f7ffdd76ae3c2088d10e Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 27 Nov 2013 11:40:28 +0100 Subject: [PATCH 21/30] Fix bold in informative git prompt. Currently this fix is useless, as web config cannot apply variables, but in future, it could be more useful. --- share/tools/web_config/sample_prompts/informative_git.fish | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/tools/web_config/sample_prompts/informative_git.fish b/share/tools/web_config/sample_prompts/informative_git.fish index 466b40515..5ac277672 100644 --- a/share/tools/web_config/sample_prompts/informative_git.fish +++ b/share/tools/web_config/sample_prompts/informative_git.fish @@ -4,7 +4,7 @@ set -g __fish_git_prompt_show_informative_status 1 set -g __fish_git_prompt_hide_untrackedfiles 1 -set -g __fish_git_prompt_color_branch magenta bold +set -g __fish_git_prompt_color_branch magenta --bold set -g __fish_git_prompt_showupstream "informative" set -g __fish_git_prompt_char_upstream_ahead "↑" set -g __fish_git_prompt_char_upstream_behind "↓" @@ -20,7 +20,7 @@ set -g __fish_git_prompt_color_dirtystate blue set -g __fish_git_prompt_color_stagedstate yellow set -g __fish_git_prompt_color_invalidstate red set -g __fish_git_prompt_color_untrackedfiles $fish_color_normal -set -g __fish_git_prompt_color_cleanstate green bold +set -g __fish_git_prompt_color_cleanstate green --bold function fish_prompt --description 'Write out the prompt' From 0e7790df8c77d8dc5ee0936ef4efa476ddbc6659 Mon Sep 17 00:00:00 2001 From: Shane Xu Date: Wed, 27 Nov 2013 23:39:52 +0800 Subject: [PATCH 22/30] add port information --- share/completions/scp.fish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/completions/scp.fish b/share/completions/scp.fish index f7e131f50..f791b8af5 100644 --- a/share/completions/scp.fish +++ b/share/completions/scp.fish @@ -31,7 +31,7 @@ complete -c scp -d "Remote Path" -n "commandline -ct|sgrep -o '.*:'" -a " commandline -ct|sgrep -o '.*:' )( #Get the list of remote files from the specified ssh server - ssh -o \"BatchMode yes\" (commandline -ct|sed -ne 's/\(.*\):.*/\1/p') ls\ -dp\ (commandline -ct|sed -ne 's/.*://p')\* 2> /dev/null + ssh (commandline -c|sgrep -o '\-P [0-9]*'|tr P p) -o \"BatchMode yes\" (commandline -ct|sed -ne 's/\(.*\):.*/\1/p') ls\ -dp\ (commandline -ct|sed -ne 's/.*://p')\* 2> /dev/null ) " From 1eb09f3eb26fda104ba645169562fa25263c15ab Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 27 Nov 2013 21:10:28 +0100 Subject: [PATCH 23/30] Fix compilation failures under Intel C compiler. It appears that Intel C compiler doesn't recognize unsigned wchar_t, however it doesn't appear to be important (the conversion function is unused, and in other cases it doesn't appear to be needed). --- builtin_printf.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/builtin_printf.cpp b/builtin_printf.cpp index b7df7fa82..7e7daee23 100644 --- a/builtin_printf.cpp +++ b/builtin_printf.cpp @@ -195,11 +195,6 @@ double C_STRTOD(wchar_t const *nptr, wchar_t **endptr) return r; } -static inline unsigned wchar_t to_uwchar_t(wchar_t ch) -{ - return ch; -} - void builtin_printf_state_t::fatal_error(const wchar_t *fmt, ...) { // Don't error twice @@ -292,7 +287,7 @@ static T string_to_scalar_type(const wchar_t *s, builtin_printf_state_t *state) T val; if (*s == L'\"' || *s == L'\'') { - unsigned wchar_t ch = *++s; + wchar_t ch = *++s; val = ch; } else @@ -736,7 +731,7 @@ no_more_flag_characters: ++f; { - unsigned wchar_t conversion = *f; + wchar_t conversion = *f; if (! ok[conversion]) { this->fatal_error(_(L"%.*ls: invalid conversion specification"), (int)(f + 1 - direc_start), direc_start); From e0b78f7f2a0274e834b3d5bd73f89184fc47fe87 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 27 Nov 2013 21:16:34 +0100 Subject: [PATCH 24/30] Disallow Unicode conversion specifications. This stops fish from accessing the `bool ok[UCHAR_MAX + 1]` table beyond allocated space potentially accessing memory that doesn't belong to fish, and crashing. --- builtin_printf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin_printf.cpp b/builtin_printf.cpp index 7e7daee23..1a1ab3350 100644 --- a/builtin_printf.cpp +++ b/builtin_printf.cpp @@ -732,7 +732,7 @@ no_more_flag_characters: { wchar_t conversion = *f; - if (! ok[conversion]) + if (conversion > 0xFF || ! ok[conversion]) { this->fatal_error(_(L"%.*ls: invalid conversion specification"), (int)(f + 1 - direc_start), direc_start); return 0; From 9f986d8a8660193d5a716a65307adb3708f14a24 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 27 Nov 2013 16:04:12 -0800 Subject: [PATCH 25/30] Implemented iothread_perform_on_main() to support background threads scheduling work on main thread --- fish_tests.cpp | 45 +++++++++++++ iothread.cpp | 171 ++++++++++++++++++++++++++++++++++++++----------- iothread.h | 13 +++- 3 files changed, 189 insertions(+), 40 deletions(-) diff --git a/fish_tests.cpp b/fish_tests.cpp index b226d3079..d00c7da29 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -489,6 +489,50 @@ static void test_fork(void) #undef FORK_COUNT } +// Little function that runs in the main thread +static int test_iothread_main_call(int *addr) +{ + *addr += 1; + return *addr; +} + +// Little function that runs in a background thread, bouncing to the main +static int test_iothread_thread_call(int *addr) +{ + int before = *addr; + iothread_perform_on_main(test_iothread_main_call, addr); + int after = *addr; + + // Must have incremented it at least once + if (before >= after) + { + err(L"Failed to increment from background thread"); + } + return after; +} + +static void test_iothread(void) +{ + say(L"Testing iothreads"); + int *int_ptr = new int(0); + int iterations = 1000; + for (int i=0; i < iterations; i++) + { + iothread_perform(test_iothread_thread_call, (void (*)(int *, int))NULL, int_ptr); + } + + // Now wait until we're done + iothread_drain_all(); + + // Should have incremented it once per thread + if (*int_ptr != iterations) + { + say(L"Expected int to be %d, but instead it was %d", iterations, *int_ptr); + } + + delete int_ptr; +} + /** Test the parser */ @@ -1878,6 +1922,7 @@ int main(int argc, char **argv) test_convert_nulls(); test_tok(); test_fork(); + test_iothread(); test_parser(); test_utils(); test_escape_sequences(); diff --git a/iothread.cpp b/iothread.cpp index 54117dc04..6f07aec0b 100644 --- a/iothread.cpp +++ b/iothread.cpp @@ -22,6 +22,11 @@ #define IO_MAX_THREADS 64 #endif +/* A special "thread index" that means service main thread requests */ +#define IO_SERVICE_MAIN_THREAD_REQUEST_QUEUE 99 + +static void iothread_service_main_thread_requests(void); + static int s_active_thread_count; typedef unsigned char ThreadIndex_t; @@ -32,16 +37,22 @@ static struct WorkerThread_t pthread_t thread; } threads[IO_MAX_THREADS]; -struct ThreadedRequest_t +struct SpawnRequest_t { - int sequenceNumber; - int (*handler)(void *); void (*completionCallback)(void *, int); void *context; int handlerResult; }; +struct MainThreadRequest_t +{ + int (*handler)(void *); + void *context; + volatile int handlerResult; + volatile bool done; +}; + static struct WorkerThread_t *next_vacant_thread_slot(void) { for (ThreadIndex_t i=0; i < IO_MAX_THREADS; i++) @@ -51,9 +62,17 @@ static struct WorkerThread_t *next_vacant_thread_slot(void) return NULL; } -static pthread_mutex_t s_request_queue_lock; -static std::queue s_request_queue; -static int s_last_sequence_number; +/* Spawn support */ +static pthread_mutex_t s_spawn_queue_lock; +static std::queue s_request_queue; + +/* "Do on main thread" support */ +static pthread_mutex_t s_main_thread_performer_lock; // protects the main thread requests +static pthread_cond_t s_main_thread_performer_condition; //protects the main thread requests +static pthread_mutex_t s_main_thread_request_queue_lock; // protects the queue +static std::queue s_main_thread_request_queue; + +/* Notifying pipes */ static int s_read_pipe, s_write_pipe; static void iothread_init(void) @@ -63,8 +82,11 @@ static void iothread_init(void) { inited = true; - /* Initialize the queue lock */ - VOMIT_ON_FAILURE(pthread_mutex_init(&s_request_queue_lock, NULL)); + /* Initialize some locks */ + VOMIT_ON_FAILURE(pthread_mutex_init(&s_spawn_queue_lock, NULL)); + VOMIT_ON_FAILURE(pthread_mutex_init(&s_main_thread_request_queue_lock, NULL)); + VOMIT_ON_FAILURE(pthread_mutex_init(&s_main_thread_performer_lock, NULL)); + VOMIT_ON_FAILURE(pthread_cond_init(&s_main_thread_performer_condition, NULL)); /* Initialize the completion pipes */ int pipes[2] = {0, 0}; @@ -84,16 +106,16 @@ static void iothread_init(void) } } -static void add_to_queue(struct ThreadedRequest_t *req) +static void add_to_queue(struct SpawnRequest_t *req) { - ASSERT_IS_LOCKED(s_request_queue_lock); + ASSERT_IS_LOCKED(s_spawn_queue_lock); s_request_queue.push(req); } -static ThreadedRequest_t *dequeue_request(void) +static SpawnRequest_t *dequeue_spawn_request(void) { - ThreadedRequest_t *result = NULL; - scoped_lock lock(s_request_queue_lock); + SpawnRequest_t *result = NULL; + scoped_lock lock(s_spawn_queue_lock); if (! s_request_queue.empty()) { result = s_request_queue.front(); @@ -109,7 +131,7 @@ static void *iothread_worker(void *threadPtr) struct WorkerThread_t *thread = (struct WorkerThread_t *)threadPtr; /* Grab a request off of the queue */ - struct ThreadedRequest_t *req = dequeue_request(); + struct SpawnRequest_t *req = dequeue_spawn_request(); /* Run the handler and store the result */ if (req) @@ -127,7 +149,7 @@ static void *iothread_worker(void *threadPtr) /* Spawn another thread if there's work to be done. */ static void iothread_spawn_if_needed(void) { - ASSERT_IS_LOCKED(s_request_queue_lock); + ASSERT_IS_LOCKED(s_spawn_queue_lock); if (! s_request_queue.empty() && s_active_thread_count < IO_MAX_THREADS) { struct WorkerThread_t *thread = next_vacant_thread_slot(); @@ -168,14 +190,13 @@ int iothread_perform_base(int (*handler)(void *), void (*completionCallback)(voi iothread_init(); /* Create and initialize a request. */ - struct ThreadedRequest_t *req = new ThreadedRequest_t(); + struct SpawnRequest_t *req = new SpawnRequest_t(); req->handler = handler; req->completionCallback = completionCallback; req->context = context; - req->sequenceNumber = ++s_last_sequence_number; /* Take our lock */ - scoped_lock lock(s_request_queue_lock); + scoped_lock lock(s_spawn_queue_lock); /* Add to the queue */ add_to_queue(req); @@ -196,31 +217,38 @@ void iothread_service_completion(void) ASSERT_IS_MAIN_THREAD(); ThreadIndex_t threadIdx = (ThreadIndex_t)-1; VOMIT_ON_FAILURE(1 != read_loop(iothread_port(), &threadIdx, sizeof threadIdx)); - assert(threadIdx < IO_MAX_THREADS); - struct WorkerThread_t *thread = &threads[threadIdx]; - assert(thread->thread != 0); - - struct ThreadedRequest_t *req = NULL; - VOMIT_ON_FAILURE(pthread_join(thread->thread, (void **)&req)); - - /* Free up this thread */ - thread->thread = 0; - assert(s_active_thread_count > 0); - s_active_thread_count -= 1; - - /* Handle the request */ - if (req) + if (threadIdx == IO_SERVICE_MAIN_THREAD_REQUEST_QUEUE) { - if (req->completionCallback) - req->completionCallback(req->context, req->handlerResult); - delete req; + iothread_service_main_thread_requests(); } + else + { + assert(threadIdx < IO_MAX_THREADS); - /* Maybe spawn another thread, if there's more work to be done. */ - VOMIT_ON_FAILURE(pthread_mutex_lock(&s_request_queue_lock)); - iothread_spawn_if_needed(); - VOMIT_ON_FAILURE(pthread_mutex_unlock(&s_request_queue_lock)); + struct WorkerThread_t *thread = &threads[threadIdx]; + assert(thread->thread != 0); + + struct SpawnRequest_t *req = NULL; + VOMIT_ON_FAILURE(pthread_join(thread->thread, (void **)&req)); + + /* Free up this thread */ + thread->thread = 0; + assert(s_active_thread_count > 0); + s_active_thread_count -= 1; + + /* Handle the request */ + if (req) + { + if (req->completionCallback) + req->completionCallback(req->context, req->handlerResult); + delete req; + } + + /* Maybe spawn another thread, if there's more work to be done. */ + scoped_lock locker(s_spawn_queue_lock); + iothread_spawn_if_needed(); + } } void iothread_drain_all(void) @@ -243,3 +271,68 @@ void iothread_drain_all(void) printf("(Waited %.02f msec for %d thread(s) to drain)\n", 1000 * (after - now), thread_count); #endif } + +/* "Do on main thread" support */ + +static void iothread_service_main_thread_requests(void) +{ + ASSERT_IS_MAIN_THREAD(); + + // Move the queue to a local variable + std::queue request_queue; + { + scoped_lock queue_lock(s_main_thread_request_queue_lock); + std::swap(request_queue, s_main_thread_request_queue); + } + + if (! request_queue.empty()) + { + // Perform each of the functions + // Note we are NOT responsible for deleting these. They are stack allocated in their respective threads! + scoped_lock cond_lock(s_main_thread_performer_lock); + while (! request_queue.empty()) + { + MainThreadRequest_t *req = request_queue.front(); + request_queue.pop(); + req->handlerResult = req->handler(req->context); + req->done = true; + } + + // Ok, we've handled everybody. Announce the good news, and allow ourselves to be unlocked + VOMIT_ON_FAILURE(pthread_cond_broadcast(&s_main_thread_performer_condition)); + } +} + +int iothread_perform_on_main_base(int (*handler)(void *), void *context) +{ + ASSERT_IS_BACKGROUND_THREAD(); + + // Make a new request. Note we are synchronous, so this can be stack allocated! + MainThreadRequest_t req; + req.handler = handler; + req.context = context; + req.handlerResult = 0; + req.done = false; + + // Append it + { + scoped_lock queue_lock(s_main_thread_request_queue_lock); + s_main_thread_request_queue.push(&req); + } + + // Tell the pipe + const ThreadIndex_t idx = IO_SERVICE_MAIN_THREAD_REQUEST_QUEUE; + VOMIT_ON_FAILURE(! write_loop(s_write_pipe, (const char *)&idx, sizeof idx)); + + // Wait on the condition, until we're done + scoped_lock perform_lock(s_main_thread_performer_lock); + while (! req.done) + { + // It would be nice to support checking for cancellation here, but the clients need a deterministic way to clean up to avoid leaks + VOMIT_ON_FAILURE(pthread_cond_wait(&s_main_thread_performer_condition, &s_main_thread_performer_lock)); + } + + // Ok, the request must now be done + assert(req.done); + return req.handlerResult; +} diff --git a/iothread.h b/iothread.h index 88c4a430c..ac328ace0 100644 --- a/iothread.h +++ b/iothread.h @@ -28,11 +28,22 @@ void iothread_service_completion(void); /** Waits for all iothreads to terminate. */ void iothread_drain_all(void); -/** Helper template */ +/** Performs a function on the main thread, blocking until it completes */ +int iothread_perform_on_main_base(int (*handler)(void *), void *context); + +/** Helper templates */ template int iothread_perform(int (*handler)(T *), void (*completionCallback)(T *, int), T *context) { return iothread_perform_base((int (*)(void *))handler, (void (*)(void *, int))completionCallback, static_cast(context)); } +/** Helper templates */ +template +int iothread_perform_on_main(int (*handler)(T *), T *context) +{ + return iothread_perform_on_main_base((int (*)(void *))handler, static_cast(context)); +} + + #endif From e1608362d0d1da493153e6884486ce82deab27dd Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Fri, 29 Nov 2013 15:26:33 +0100 Subject: [PATCH 26/30] Fix s/$remote// mistake. $remote could have contained /. --- share/functions/__fish_git_prompt.fish | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/functions/__fish_git_prompt.fish b/share/functions/__fish_git_prompt.fish index 3012f8ef4..ba59c5fa8 100644 --- a/share/functions/__fish_git_prompt.fish +++ b/share/functions/__fish_git_prompt.fish @@ -2,7 +2,7 @@ # # Written by Kevin Ballard # Updated by Brian Gernhardt -# +# # This is heavily based off of the git-prompt.bash script that ships with # git, which is Copyright (C) 2006,2007 Shawn O. Pearce . # The act of porting the code, along with any new code, are Copyright (C) 2012 @@ -246,7 +246,7 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi set -l cur_prefix for i in (seq (count $svn_remote)) set -l remote $svn_remote[$i] - set -l mod_upstream (echo $svn_upstream | sed "s/$remote//") + set -l mod_upstream (echo $svn_upstream | sed "s|$remote||") if test "$svn_upstream" != "$mod_upstream" # we found a valid remote set svn_upstream $mod_upstream From 4aaa9e7d9fd08ad3129b3b7ed0c82f368611ea6f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 29 Nov 2013 13:31:18 -0800 Subject: [PATCH 27/30] Allow autosuggestions to do job expansion. Fixes https://github.com/fish-shell/fish-shell/issues/1152 --- complete.cpp | 2 +- expand.cpp | 303 +++++++++++++++++++++++++++----------------------- highlight.cpp | 6 +- iothread.cpp | 6 +- iothread.h | 2 +- proc.cpp | 1 + 6 files changed, 174 insertions(+), 146 deletions(-) diff --git a/complete.cpp b/complete.cpp index de822a6bc..2b7423b5a 100644 --- a/complete.cpp +++ b/complete.cpp @@ -430,7 +430,7 @@ public: /* Never do command substitution in autosuggestions. Sadly, we also can't yet do job expansion because it's not thread safe. */ expand_flags_t result = 0; if (this->type() == COMPLETE_AUTOSUGGEST) - result |= EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS; + result |= EXPAND_SKIP_CMDSUBST; /* Allow fuzzy matching */ if (this->fuzzy()) diff --git a/expand.cpp b/expand.cpp index 2a3a1fe83..10e3cbf40 100644 --- a/expand.cpp +++ b/expand.cpp @@ -49,6 +49,7 @@ parameter expansion. #include "signal.h" #include "tokenizer.h" #include "complete.h" +#include "iothread.h" #include "parse_util.h" @@ -560,6 +561,166 @@ std::vector expand_get_all_process_names(void) return result; } +/* Helper function to do a job search. */ +struct find_job_data_t +{ + const wchar_t *proc; /* The process to search for - possibly numeric, possibly a name */ + expand_flags_t flags; + std::vector *completions; +}; + +/* The following function is invoked on the main thread, because the job list is not thread safe. It should search the job list for something matching the given proc, and then return 1 to stop the search, 0 to continue it */ +static int find_job(const struct find_job_data_t *info) +{ + ASSERT_IS_MAIN_THREAD(); + + const wchar_t * const proc = info->proc; + const expand_flags_t flags = info->flags; + std::vector &completions = *info->completions; + + const job_t *j; + int found = 0; + // do the empty param check first, because an empty string passes our 'numeric' check + if (wcslen(proc)==0) + { + /* + This is an empty job expansion: '%' + It expands to the last job backgrounded. + */ + job_iterator_t jobs; + while ((j = jobs.next())) + { + if (!j->command_is_empty()) + { + append_completion(completions, to_string(j->pgid)); + break; + } + } + /* + You don't *really* want to flip a coin between killing + the last process backgrounded and all processes, do you? + Let's not try other match methods with the solo '%' syntax. + */ + found = 1; + } + else if (iswnumeric(proc)) + { + /* + This is a numeric job string, like '%2' + */ + + if (flags & ACCEPT_INCOMPLETE) + { + job_iterator_t jobs; + while ((j = jobs.next())) + { + wchar_t jid[16]; + if (j->command_is_empty()) + continue; + + swprintf(jid, 16, L"%d", j->job_id); + + if (wcsncmp(proc, jid, wcslen(proc))==0) + { + wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr()); + append_completion(completions, + jid+wcslen(proc), + desc_buff, + 0); + } + } + } + else + { + int jid; + wchar_t *end; + + errno = 0; + jid = fish_wcstoi(proc, &end, 10); + if (jid > 0 && !errno && !*end) + { + j = job_get(jid); + if ((j != 0) && (j->command_wcstr() != 0) && (!j->command_is_empty())) + { + append_completion(completions, to_string(j->pgid)); + } + } + } + /* + Stop here so you can't match a random process name + when you're just trying to use job control. + */ + found = 1; + } + + if (! found) + { + job_iterator_t jobs; + while ((j = jobs.next())) + { + + if (j->command_is_empty()) + continue; + + size_t offset; + if (match_pid(j->command(), proc, flags, &offset)) + { + if (flags & ACCEPT_INCOMPLETE) + { + append_completion(completions, + j->command_wcstr() + offset + wcslen(proc), + COMPLETE_JOB_DESC, + 0); + } + else + { + append_completion(completions, to_string(j->pgid)); + found = 1; + } + } + } + + if (! found) + { + jobs.reset(); + while ((j = jobs.next())) + { + process_t *p; + if (j->command_is_empty()) + continue; + for (p=j->first_process; p; p=p->next) + { + if (p->actual_cmd.empty()) + continue; + + size_t offset; + if (match_pid(p->actual_cmd, proc, flags, &offset)) + { + if (flags & ACCEPT_INCOMPLETE) + { + append_completion(completions, + wcstring(p->actual_cmd, offset + wcslen(proc)), + COMPLETE_CHILD_PROCESS_DESC, + 0); + } + else + { + append_completion(completions, + to_string(p->pid), + L"", + 0); + found = 1; + } + } + } + } + } + } + + return found; +} + + /** Searches for a job with the specified job id, or a job or process which has the string \c proc as a prefix of its commandline. @@ -582,146 +743,8 @@ static int find_process(const wchar_t *proc, if (!(flags & EXPAND_SKIP_JOBS)) { - ASSERT_IS_MAIN_THREAD(); - const job_t *j; - - // do the empty param check first, because an empty string passes our 'numeric' check - if (wcslen(proc)==0) - { - /* - This is an empty job expansion: '%' - It expands to the last job backgrounded. - */ - job_iterator_t jobs; - while ((j = jobs.next())) - { - if (!j->command_is_empty()) - { - append_completion(out, to_string(j->pgid)); - break; - } - } - /* - You don't *really* want to flip a coin between killing - the last process backgrounded and all processes, do you? - Let's not try other match methods with the solo '%' syntax. - */ - found = 1; - } - else if (iswnumeric(proc)) - { - /* - This is a numeric job string, like '%2' - */ - - if (flags & ACCEPT_INCOMPLETE) - { - job_iterator_t jobs; - while ((j = jobs.next())) - { - wchar_t jid[16]; - if (j->command_is_empty()) - continue; - - swprintf(jid, 16, L"%d", j->job_id); - - if (wcsncmp(proc, jid, wcslen(proc))==0) - { - wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr()); - append_completion(out, - jid+wcslen(proc), - desc_buff, - 0); - } - } - } - else - { - int jid; - wchar_t *end; - - errno = 0; - jid = fish_wcstoi(proc, &end, 10); - if (jid > 0 && !errno && !*end) - { - j = job_get(jid); - if ((j != 0) && (j->command_wcstr() != 0) && (!j->command_is_empty())) - { - append_completion(out, to_string(j->pgid)); - } - } - } - /* - Stop here so you can't match a random process name - when you're just trying to use job control. - */ - found = 1; - } - if (found) - return 1; - - job_iterator_t jobs; - while ((j = jobs.next())) - { - - if (j->command_is_empty()) - continue; - - size_t offset; - if (match_pid(j->command(), proc, flags, &offset)) - { - if (flags & ACCEPT_INCOMPLETE) - { - append_completion(out, - j->command_wcstr() + offset + wcslen(proc), - COMPLETE_JOB_DESC, - 0); - } - else - { - append_completion(out, to_string(j->pgid)); - found = 1; - } - } - } - - if (found) - { - return 1; - } - - jobs.reset(); - while ((j = jobs.next())) - { - process_t *p; - if (j->command_is_empty()) - continue; - for (p=j->first_process; p; p=p->next) - { - if (p->actual_cmd.empty()) - continue; - - size_t offset; - if (match_pid(p->actual_cmd, proc, flags, &offset)) - { - if (flags & ACCEPT_INCOMPLETE) - { - append_completion(out, - wcstring(p->actual_cmd, offset + wcslen(proc)), - COMPLETE_CHILD_PROCESS_DESC, - 0); - } - else - { - append_completion(out, - to_string(p->pid), - L"", - 0); - found = 1; - } - } - } - } + const struct find_job_data_t data = {proc, flags, &out}; + found = iothread_perform_on_main(find_job, &data); if (found) { diff --git a/highlight.cpp b/highlight.cpp index 2e1543877..fd7aa481e 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -873,7 +873,7 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio { /* We can possibly handle this specially */ wcstring dir = parsed_arguments.back(); - if (expand_one(dir, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) + if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) { handled = true; bool is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); @@ -997,7 +997,7 @@ static void tokenize(const wchar_t * const buff, std::vector &color, const if (cmd == L"cd") { wcstring dir = tok_last(&tok); - if (expand_one(dir, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) + if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) { int is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); if (!is_help && ! is_potential_cd_path(dir, working_directory, PATH_EXPAND_TILDE, NULL)) @@ -1182,7 +1182,7 @@ static void tokenize(const wchar_t * const buff, std::vector &color, const case TOK_STRING: { target_str = tok_last(&tok); - if (expand_one(target_str, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS)) + if (expand_one(target_str, EXPAND_SKIP_CMDSUBST)) { target = target_str.c_str(); } diff --git a/iothread.cpp b/iothread.cpp index 6f07aec0b..736467925 100644 --- a/iothread.cpp +++ b/iothread.cpp @@ -305,7 +305,11 @@ static void iothread_service_main_thread_requests(void) int iothread_perform_on_main_base(int (*handler)(void *), void *context) { - ASSERT_IS_BACKGROUND_THREAD(); + // If this is the main thread, just do it + if (is_main_thread()) + { + return handler(context); + } // Make a new request. Note we are synchronous, so this can be stack allocated! MainThreadRequest_t req; diff --git a/iothread.h b/iothread.h index ac328ace0..8ac3bd9d8 100644 --- a/iothread.h +++ b/iothread.h @@ -42,7 +42,7 @@ int iothread_perform(int (*handler)(T *), void (*completionCallback)(T *, int), template int iothread_perform_on_main(int (*handler)(T *), T *context) { - return iothread_perform_on_main_base((int (*)(void *))handler, static_cast(context)); + return iothread_perform_on_main_base((int (*)(void *))handler, (void *)(context)); } diff --git a/proc.cpp b/proc.cpp index 1ca700999..a774d3597 100644 --- a/proc.cpp +++ b/proc.cpp @@ -106,6 +106,7 @@ job_iterator_t::job_iterator_t(job_list_t &jobs) : job_list(&jobs) job_iterator_t::job_iterator_t() : job_list(&parser_t::principal_parser().job_list()) { + ASSERT_IS_MAIN_THREAD(); this->reset(); } From 263f919bebf2e5be3a95c7445034fab70fed9fab Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 29 Nov 2013 23:44:26 -0800 Subject: [PATCH 28/30] Replace autosuggestions "completions to load" mechanism with moderately less hackish and far simpler "perform on main thread" mechanism --- complete.cpp | 40 ++++++++++++++++------------------------ complete.h | 7 ++----- fish_tests.cpp | 4 ++-- reader.cpp | 28 +++------------------------- reader.h | 2 +- 5 files changed, 24 insertions(+), 57 deletions(-) diff --git a/complete.cpp b/complete.cpp index 2b7423b5a..ed0fc102d 100644 --- a/complete.cpp +++ b/complete.cpp @@ -44,6 +44,7 @@ #include "parser_keywords.h" #include "wutil.h" #include "path.h" +#include "iothread.h" /* Completion description strings, mostly for different types of files, such as sockets, block devices, etc. @@ -341,7 +342,6 @@ class completer_t const completion_request_flags_t flags; const wcstring initial_cmd; std::vector completions; - wcstring_list_t commands_to_load; /** Table of completions conditions that have already been tested and the corresponding test results */ typedef std::map condition_cache_t; @@ -438,18 +438,6 @@ public: return result; } - - void get_commands_to_load(wcstring_list_t *lst) - { - if (lst) - lst->insert(lst->end(), commands_to_load.begin(), commands_to_load.end()); - } - - bool has_commands_to_load() const - { - return ! commands_to_load.empty(); - } - }; /* Autoloader for completions */ @@ -1350,6 +1338,15 @@ void complete_load(const wcstring &name, bool reload) completion_autoloader.load(name, reload); } +// Performed on main thread, from background thread. Return type is ignored. +static int complete_load_no_reload(wcstring *name) +{ + assert(name != NULL); + ASSERT_IS_MAIN_THREAD(); + complete_load(*name, false); + return 0; +} + /** Find completion for the argument str of command cmd_orig with previous option popt. Insert results into comp_out. Return 0 if file @@ -1372,14 +1369,15 @@ bool completer_t::complete_param(const wcstring &scmd_orig, const wcstring &spop if (this->type() == COMPLETE_DEFAULT) { + ASSERT_IS_MAIN_THREAD(); complete_load(cmd, true); } else if (this->type() == COMPLETE_AUTOSUGGEST) { - /* Maybe indicate we should try loading this on the main thread */ - if (! list_contains_string(this->commands_to_load, cmd) && ! completion_autoloader.has_tried_loading(cmd)) + /* Maybe load this command (on the main thread) */ + if (! completion_autoloader.has_tried_loading(cmd)) { - this->commands_to_load.push_back(cmd); + iothread_perform_on_main(complete_load_no_reload, &cmd); } } @@ -1790,7 +1788,7 @@ bool completer_t::try_complete_user(const wcstring &str) return res; } -void complete(const wcstring &cmd, std::vector &comps, completion_request_flags_t flags, wcstring_list_t *commands_to_load) +void complete(const wcstring &cmd, std::vector &comps, completion_request_flags_t flags) { /* Make our completer */ completer_t completer(cmd, flags); @@ -1999,12 +1997,7 @@ void complete(const wcstring &cmd, std::vector &comps, completion_ if (completer.empty()) do_file = true; - /* But if we are planning on loading commands, don't do file completions. - See https://github.com/fish-shell/fish-shell/issues/378 */ - if (commands_to_load != NULL && completer.has_commands_to_load()) - do_file = false; - - /* And if we're autosuggesting, and the token is empty, don't do file suggestions */ + /* If we're autosuggesting, and the token is empty, don't do file suggestions */ if ((flags & COMPLETION_REQUEST_AUTOSUGGESTION) && current_token_unescape.empty()) do_file = false; @@ -2016,7 +2009,6 @@ void complete(const wcstring &cmd, std::vector &comps, completion_ } comps = completer.get_completions(); - completer.get_commands_to_load(commands_to_load); } diff --git a/complete.h b/complete.h index 72d5a7214..cd4f22a16 100644 --- a/complete.h +++ b/complete.h @@ -216,14 +216,11 @@ void complete_remove(const wchar_t *cmd, const wchar_t *long_opt); -/** Find all completions of the command cmd, insert them into out. If to_load is - * not NULL, append all commands that we would autoload, but did not (presumably - * because this is not the main thread) +/** Find all completions of the command cmd, insert them into out. */ void complete(const wcstring &cmd, std::vector &comp, - completion_request_flags_t flags, - wcstring_list_t *to_load = NULL); + completion_request_flags_t flags); /** Print a list of all current completions into the string. diff --git a/fish_tests.cpp b/fish_tests.cpp index d00c7da29..e7047c4bc 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -1358,7 +1358,7 @@ void perf_complete() str[0]=c; reader_set_buffer(str, 0); - complete(str, out, COMPLETION_REQUEST_DEFAULT, NULL); + complete(str, out, COMPLETION_REQUEST_DEFAULT); matches += out.size(); out.clear(); @@ -1378,7 +1378,7 @@ void perf_complete() reader_set_buffer(str, 0); - complete(str, out, COMPLETION_REQUEST_DEFAULT, NULL); + complete(str, out, COMPLETION_REQUEST_DEFAULT); matches += out.size(); out.clear(); diff --git a/reader.cpp b/reader.cpp index 5b2a5e0a2..5660ff268 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1410,12 +1410,8 @@ struct autosuggestion_context_t file_detection_context_t detector; const wcstring working_directory; const env_vars_snapshot_t vars; - wcstring_list_t commands_to_load; const unsigned int generation_count; - // don't reload more than once - bool has_tried_reloading; - autosuggestion_context_t(history_t *history, const wcstring &term, size_t pos) : search_string(term), cursor_pos(pos), @@ -1423,8 +1419,7 @@ struct autosuggestion_context_t detector(history, term), working_directory(env_get_pwd_slash()), vars(env_vars_snapshot_t::highlighting_keys), - generation_count(s_generation_count), - has_tried_reloading(false) + generation_count(s_generation_count) { } @@ -1494,7 +1489,7 @@ struct autosuggestion_context_t /* Try normal completions */ std::vector completions; - complete(search_string, completions, COMPLETION_REQUEST_AUTOSUGGESTION, &this->commands_to_load); + complete(search_string, completions, COMPLETION_REQUEST_AUTOSUGGESTION); if (! completions.empty()) { const completion_t &comp = completions.at(0); @@ -1523,23 +1518,6 @@ static bool can_autosuggest(void) static void autosuggest_completed(autosuggestion_context_t *ctx, int result) { - - /* Extract the commands to load */ - wcstring_list_t commands_to_load; - ctx->commands_to_load.swap(commands_to_load); - - /* If we have autosuggestions to load, load them and try again */ - if (! result && ! commands_to_load.empty() && ! ctx->has_tried_reloading) - { - ctx->has_tried_reloading = true; - for (wcstring_list_t::const_iterator iter = commands_to_load.begin(); iter != commands_to_load.end(); ++iter) - { - complete_load(*iter, false); - } - iothread_perform(threaded_autosuggest, autosuggest_completed, ctx); - return; - } - if (result && can_autosuggest() && ctx->search_string == data->command_line && @@ -3271,7 +3249,7 @@ const wchar_t *reader_readline(void) const wcstring buffcpy = wcstring(cmdsub_begin, token_end); //fprintf(stderr, "Complete (%ls)\n", buffcpy.c_str()); - data->complete_func(buffcpy, comp, COMPLETION_REQUEST_DEFAULT | COMPLETION_REQUEST_DESCRIPTIONS | COMPLETION_REQUEST_FUZZY_MATCH, NULL); + data->complete_func(buffcpy, comp, COMPLETION_REQUEST_DEFAULT | COMPLETION_REQUEST_DESCRIPTIONS | COMPLETION_REQUEST_FUZZY_MATCH); /* Munge our completions */ sort_and_make_unique(comp); diff --git a/reader.h b/reader.h index 0d7a58f17..b954c1bea 100644 --- a/reader.h +++ b/reader.h @@ -166,7 +166,7 @@ void reader_pop(); - The command to be completed as a null terminated array of wchar_t - An array_list_t in which completions will be inserted. */ -typedef void (*complete_function_t)(const wcstring &, std::vector &, completion_request_flags_t, wcstring_list_t * lst); +typedef void (*complete_function_t)(const wcstring &, std::vector &, completion_request_flags_t); void reader_set_complete_function(complete_function_t); /** From 3978de2cde12867eb19a736a61ad81254c440b64 Mon Sep 17 00:00:00 2001 From: David Adam Date: Sat, 30 Nov 2013 15:11:05 +0800 Subject: [PATCH 29/30] autoconf build: clean up Makefile, remove fish.spec Removes some unused variables and out-of-date references. Wraps some tests in quotes to avoid expansion errors. Removes the fish.spec generated file as it is out of date and is arguably better maintained by downstream packagers. See http://github.com/zanchey/fish-build/ for a better RPM spec file. --- .gitignore | 1 - Makefile.in | 67 ++-------------- configure.ac | 2 +- fish.spec.in | 221 --------------------------------------------------- 4 files changed, 6 insertions(+), 285 deletions(-) delete mode 100644 fish.spec.in diff --git a/.gitignore b/.gitignore index b2ea73dc2..b55ce1e23 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ doc_src/commands.hdr doc_src/index.hdr po/*.gmo fish -fish.spec fish_indent fish_pager fish_tests diff --git a/Makefile.in b/Makefile.in index 2b161607f..6a336f74b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,14 +20,7 @@ # # Makefile for the fish shell. Can build fish and associated -# applications, install them, recalculate dependencies and also create -# binary distributions in tar.bz2, tar.gz and rpm formats. -# - -# -# The fish buildprocess is quite complex. Do not stare directly into -# the Makefile. Doing so may cause nausea, dizziness and -# hallucinations. +# applications, install them, and recalculate dependencies. # # Used by docdir @@ -186,48 +179,6 @@ HELP_SRC := $(wildcard doc_src/*.txt) TEST_IN := $(wildcard tests/test*.in) - -# -# Files that should be added to the tar archives -# - -# -# Files in ./doc_src/ -# - -DOC_SRC_DIR_FILES := $(HDR_FILES_SRC) $(HELP_SRC) - - -# -# Files in ./ -# - -MAIN_DIR_FILES_UNSORTED := Doxyfile Doxyfile.user Doxyfile.help \ - Makefile.in configure configure.ac config.h.in install-sh \ - key_reader.cpp $(MIME_OBJS:.o=.h) \ - $(MIME_OBJS:.o=.cpp) $(FISH_OBJS:.o=.h) $(BUILTIN_FILES) \ - $(COMMON_FILES) $(COMMON_FILES:.cpp=.h) $(FISH_OBJS:.o=.cpp) \ - fish.spec.in INSTALL README user_doc.head.html \ - ChangeLog config.sub config.guess fish_tests.cpp fish.cpp fish_pager.cpp \ - fishd.cpp make_vcs_completions.fish $(FISH_INDENT_OBJS:.o=.cpp) - -# -# The sorting is not meaningful in itself, but it has the side effect -# of removing duplicates, which means there will be fewer warnings -# during building. -# - -MAIN_DIR_FILES := $(sort $(MAIN_DIR_FILES_UNSORTED)) - - -# -# Files in ./tests/ -# - -TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \ - $(TEST_IN:.in=.status) tests/test.fish tests/gen_output.fish - - # # Files in ./share/completions/ # @@ -449,7 +400,7 @@ doc.h: $(HDR_FILES) # %.po:messages.pot - if test $(HAVE_GETTEXT) = 1;then \ + if test "$(HAVE_GETTEXT)" = 1;then \ if test -f $*.po; then \ msgmerge -U --backup=existing $*.po messages.pot;\ else \ @@ -463,7 +414,7 @@ doc.h: $(HDR_FILES) # messages.pot: *.cpp *.h share/completions/*.fish share/functions/*.fish - if test $(HAVE_GETTEXT) = 1;then \ + if test "$(HAVE_GETTEXT)" = 1; then \ xgettext -k_ -kN_ *.cpp *.h -o messages.pot; \ if xgettext -j -k_ -kN_ -k--description -LShell share/completions/*.fish share/functions/*.fish -o messages.pot; then true; else \ echo "Your xgettext version is too old to build the messages.pot file"\ @@ -714,7 +665,7 @@ uninstall-legacy: uninstall .PHONY: uninstall-legacy install-translations: $(TRANSLATIONS) - if test $(HAVE_GETTEXT) = 1; then \ + if test "$(HAVE_GETTEXT)" = 1; then \ for i in $(TRANSLATIONS); do \ $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES/fish.mo; \ @@ -724,7 +675,7 @@ install-translations: $(TRANSLATIONS) .PHONY: install-translations uninstall-translations: - if test $(HAVE_GETTEXT) = 1; then \ + if test "$(HAVE_GETTEXT)" = 1; then \ for i in $(TRANSLATIONS_SRC); do \ rm -f $(DESTDIR)$(datadir)/locale/*/LC_MESSAGES/fish.mo; \ done; \ @@ -800,13 +751,6 @@ depend: ./config.status .PHONY: depend -# -# Build the RPM spec file. -# - -fish.spec: fish.spec.in - ./config.status - # # Cleanup targets # @@ -816,7 +760,6 @@ fish.spec: fish.spec.in # distclean: clean - rm -f fish.spec rm -f config.status config.log config.h Makefile .PHONY: distclean diff --git a/configure.ac b/configure.ac index 82e591b2f..64a6f1ecb 100644 --- a/configure.ac +++ b/configure.ac @@ -873,7 +873,7 @@ case $target_os in esac # Tell the world what we know -AC_CONFIG_FILES([Makefile fish.spec]) +AC_CONFIG_FILES([Makefile]) AC_OUTPUT if test ! x$local_found_posix_switch = xyes; then diff --git a/fish.spec.in b/fish.spec.in deleted file mode 100644 index 0b57e96bd..000000000 --- a/fish.spec.in +++ /dev/null @@ -1,221 +0,0 @@ -Summary: A friendly interactive shell -Name: @PACKAGE_NAME@ - -Version: @PACKAGE_VERSION@ -Release: 0%{?dist} - -License: GPL -Group: System Environment/Shells -URL: http://fishshell.com/ - -Source0: http://ridiculousfish.com/shell/files/%{version}/%{name}-%{version}.tar.bz2 - -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: ncurses-devel gettext groff - - -# Locate correct build time-dependencies for providing X headers -%if "%fedora" >= "5" - -# Modern Fedora version, has modular X.org -BuildRequires: xorg-x11-proto-devel libX11-devel libXt-devel libXext-devel - -%endif - -%if "%fedora" < "5" -%if "%fedora" >= "3" - -# Semi-old Fedora version, has non-modular X.org -BuildRequires: xorg-x11-devel - -%endif -%endif - -%if 0%{?fedora} -%if "%fedora" < "3" - -# Ancient Fedora version, has XFree86 -BuildRequires: XFree86-devel - -%endif -%else - -# The %fedora variable has not been correctly defined, or this is is -# not a Fedora system, try guessing BuildRequires by looking at the -# directory structure -%define xinclude /usr%(if [ -d /usr/X11R6/include ]; then echo /X11R6; fi)/include -BuildRequires: %{xinclude}/X11/StringDefs.h, %{xinclude}/X11/Xlib.h -BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h - -%endif - - -%description - -fish is a shell geared towards interactive use. Its features are -focused on user friendliness and discoverability. The language syntax -is simple but incompatible with other shell languages. - - -%prep -%setup -q - - - - -%build -# The docdir argument is to make the name of the cosumantation -# directory 'fish-VERSION', instead of the default, which is simply -# 'fish'. -%configure docdir=%_datadir/doc/%{name}-%{version} -make %{?_smp_mflags} - - - - -%install -rm -rf $RPM_BUILD_ROOT -make install DESTDIR="$RPM_BUILD_ROOT" - -# Find translation files -%find_lang %{name}.\* - - - -%clean -rm -rf $RPM_BUILD_ROOT - - - - -%post -# Add fish to the list of allowed shells in /etc/shells -if ! grep %_bindir/fish %_sysconfdir/shells >/dev/null; then - echo %_bindir/fish >>%_sysconfdir/shells -fi - - - - -%postun -# Remove fish from the list of allowed shells in /etc/shells -if [ "$1" = 0 ]; then - grep -v %_bindir/fish %_sysconfdir/shells >%_sysconfdir/fish.tmp - mv %_sysconfdir/fish.tmp %_sysconfdir/shells -fi - - - - -%files -f %{name}.\*.lang - -%defattr(-,root,root,-) - -# The documentation directory -%doc %_datadir/doc/%{name}-%{version} - -# man files -%_mandir/man1/fish.1* -%_mandir/man1/fish_pager.1* -%_mandir/man1/fish_indent.1* -%_mandir/man1/fishd.1* -%_mandir/man1/mimedb.1* -%_mandir/man1/set_color.1* - -# The program binaries -%attr(0755,root,root) %_bindir/fish -%attr(0755,root,root) %_bindir/fish_indent -%attr(0755,root,root) %_bindir/fish_pager -%attr(0755,root,root) %_bindir/fishd -%attr(0755,root,root) %_bindir/mimedb -%attr(0755,root,root) %_bindir/set_color - -# Configuration files -%config %_sysconfdir/fish/config.fish -%dir %_sysconfdir/fish - -# Non-configuration initialization files -%dir %_datadir/fish -%_datadir/fish/config.fish - -# Program specific tab-completions -%dir %_datadir/fish/completions -%_datadir/fish/completions/*.fish - -# Dynamically loaded shellscript functions -%dir %_datadir/fish/functions -%_datadir/fish/functions/*.fish - -# Documentation for builtins and shellscript functions -%dir %_datadir/fish/man -%_datadir/fish/man/*.1 - - - -%changelog -* Sat Apr 21 2007 Axel Liljencrantz 1.23.0-0 -- Add fish_indent command - -* Thu Feb 8 2007 Axel Liljencrantz 1.22.3-0 -- Tell rpm about the help pages in %_datadir/fish/man/ - -* Sat Oct 14 2006 Axel Liljencrantz 1.22.0-0 -- Update names of various configuration files - -* Fri Aug 4 2006 Axel Liljencrantz 1.21.10-4 -- Add better translation finding code from fedora spec to main spec. Thank you to Michael Schwendt. -- Add missing dependency libXext-devel. -- Remove one nesting level from dependency checking code. - -* Tue Aug 1 2006 Axel Liljencrantz 1.21.10-1 -- Improved the dependency check for X headers. Thank you to Michael Schwendt for pointers on how to do this - -* Mon Jul 31 2006 Axel Liljencrantz 1.21.10-1 -- Fixed spelling and punctuation as a per patch from Paul Howarth -- Fixed dependencies as per patch from Paul Howarth - -* Tue Nov 29 2005 Axel Liljencrantz 1.17.0-0 -- 1.17.0 - -* Sat Sep 24 2005 Axel Liljencrantz 1.14.0-0 -- 1.14.0 - -* Mon Sep 12 2005 Axel Liljencrantz 1.13.4-0 -- 1.13.4 - -* Wed Sep 07 2005 Axel Liljencrantz 1.13.3-0 -- 1.13.3 - -* Tue Sep 06 2005 Axel Liljencrantz 1.13.2-0 -- 1.13.2 - -* Fri Aug 30 2005 Axel Liljencrantz 1.13.1-0 -- 1.13.1 - -* Sun Aug 28 2005 Axel Liljencrantz 1.13.0-0 -- 1.13.0 - -* Sat Aug 13 2005 Axel Liljencrantz 1.13.0-0 -- Add completions subdirectory - -* Thu Jul 28 2005 Axel Liljencrantz 1.12.1-0 -- 1.12.1 - -* Fri Jul 15 2005 Axel Liljencrantz 1.12.0-1 -- 1.12.0 - -* Thu Jun 30 2005 Michael Schwendt 1.11.1-9 -- Set CFLAGS the proper way - -* Thu Jun 30 2005 Axel Liljencrantz 1.11.1-8 -- Fix revision number in changelog - -* Wed Jun 29 2005 Axel Liljencrantz 1.11.1-7 -- Send post-script output to /dev/null - -* Wed Jun 29 2005 Axel Liljencrantz 1.11.1-6 -- Add changelog section to spec file -- Add macros to source tags -- Add smp_mflags to 'make all' -- Fix typo in post install scriptlet test -- Set CFLAGS from spec file From 2efc0bad1c414d5e74b9a43148daf8cba202a02b Mon Sep 17 00:00:00 2001 From: David Adam Date: Sat, 30 Nov 2013 15:18:22 +0800 Subject: [PATCH 30/30] add correct version number to manpage output --- Makefile.in | 2 +- build_tools/build_documentation.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 6a336f74b..6433eadeb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -459,7 +459,7 @@ share/man: $(HELP_SRC) -mkdir share/man touch share/man -rm -Rf share/man/man1 - ./build_tools/build_documentation.sh Doxyfile.help ./doc_src ./share + PROJECT_NUMBER=`echo $(FISH_BUILD_VERSION)| sed "s/-.*//"` ./build_tools/build_documentation.sh Doxyfile.help ./doc_src ./share # # The build rules for installing/uninstalling fish diff --git a/build_tools/build_documentation.sh b/build_tools/build_documentation.sh index 76c19a04e..0c4a2aac8 100755 --- a/build_tools/build_documentation.sh +++ b/build_tools/build_documentation.sh @@ -86,7 +86,7 @@ done # Input is kept as . because we cd to the input directory beforehand # This prevents doxygen from generating "documentation" for intermediate directories DOXYPARAMS=$(cat <