diff options
Diffstat (limited to 'src/env_parallel.fish')
-rwxr-xr-x | src/env_parallel.fish | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/env_parallel.fish b/src/env_parallel.fish new file mode 100755 index 0000000..b0abc50 --- /dev/null +++ b/src/env_parallel.fish @@ -0,0 +1,194 @@ +#!/usr/bin/env fish + +# This file must be sourced in fish: +# +# . (which env_parallel.fish) +# +# after which 'env_parallel' works +# +# +# Copyright (C) 2016-2024 Ole Tange, http://ole.tange.dk and Free +# Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/> +# or write to the Free Software Foundation, Inc., 51 Franklin St, +# Fifth Floor, Boston, MA 02110-1301 USA +# +# SPDX-FileCopyrightText: 2021-2024 Ole Tange, http://ole.tange.dk and Free Software and Foundation, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later + +# If you are a fisherman feel free to improve the code +# +# The code needs to deal with variables like: +# set funky (perl -e 'print pack "c*", 2..254') +# +# Problem: +# Tell the difference between: +# set tmp "a' 'b' 'c" +# set tmparr1 "a' 'b" 'c' +# set tmparr2 'a' "b' 'c" +# The output from `set` is exactly the same. +# Solution: +# for-loop for each variable. Each value is separated with a +# separator. + +function env_parallel + # env_parallel.fish + + # --session + perl -e 'exit grep { /^--session/ } @ARGV' -- $argv; or begin; + setenv PARALLEL_IGNORED_NAMES ( + begin; + functions -n + set -n; + end | perl -pe 's/\n/,/g'; + ) + return 0 + end; + setenv PARALLEL_ENV ( + begin; + set _grep_REGEXP ( + begin; + perl -e ' + for(@ARGV){ + /^_$/ and $next_is_env = 0; + $next_is_env and push @envvar, split/,/, $_; + $next_is_env = /^--env$/; + } + $vars = join "|",map { quotemeta $_ } @envvar; + print $vars ? "($vars)" : "(.*)"; + ' -- $argv; + end; + ) + # Deal with --env _ + set _ignore_UNDERSCORE ( + begin; + perl -e ' + for(@ARGV){ + $next_is_env and push @envvar, split/,/, $_; + $next_is_env=/^--env$/; + } + if(grep { /^_$/ } @envvar) { + if(not open(IN, "<", "$ENV{HOME}/.parallel/ignored_vars")) { + print STDERR "parallel: Error: ", + "Run \"parallel --record-env\" in a clean environment first.\n"; + } else { + chomp(@ignored_vars = <IN>); + } + } + if($ENV{PARALLEL_IGNORED_NAMES}) { + push @ignored_vars, split/,/, $ENV{PARALLEL_IGNORED_NAMES}; + chomp @ignored_vars; + } + $vars = join "|",map { quotemeta $_ } @ignored_vars; + print $vars ? "($vars)" : "(,,nO,,VaRs,,)"; + ' -- $argv; + end; + ) + + # --record-env + perl -e 'exit grep { /^--record-env$/ } @ARGV' -- $argv; or begin; + begin; + functions -n | perl -pe 's/,/\n/g'; + set -n; + end | cat > $HOME/.parallel/ignored_vars; + end; + + # Export function definitions + # Keep the ones from --env + # Ignore the ones from ~/.parallel/ignored_vars + # Dump each function defition + # Replace \001 with \002 because \001 is used by env_parallel + # Convert \n to \001 + functions -n | perl -pe 's/,/\n/g' | \ + grep -Ev '^(PARALLEL_ENV|PARALLEL_TMP)$' | \ + grep -E "^$_grep_REGEXP"\$ | grep -vE "^$_ignore_UNDERSCORE"\$ | \ + while read d; functions $d; end | \ + perl -pe 's/\001/\002/g and not $printed++ and print STDERR + "env_parallel: Warning: ASCII value 1 in functions is not supported\n"; + s/\n/\001/g'; + # Convert scalar vars to fish \XX quoting + # Keep the ones from --env + # Ignore the ones from ~/.parallel/ignored_vars + # Ignore read only vars + # Execute 'set' of the content + eval (set -L | \ + grep -Ev '^(PARALLEL_TMP)$' | \ + grep -E "^$_grep_REGEXP " | grep -vE "^$_ignore_UNDERSCORE " | \ + perl -ne 'chomp; + ($name,$val)=split(/ /,$_,2); + $name=~/^(HOME|USER|COLUMNS|FISH_VERSION|LINES|PWD|SHLVL|_| + history|status|version)$|\./x and next; + if($val=~/^'"'"'/) { next; } + print "set $name \"\$$name\";\n"; + ') + # Generate commands to set scalar variables + # Keep the ones from --env + # Ignore the ones from ~/.parallel/ignored_vars + # + begin; + for v in (set -n | \ + grep -Ev '^(PARALLEL_TMP)$' | \ + grep -E "^$_grep_REGEXP\$" | grep -vE "^$_ignore_UNDERSCORE\$"); + # Separate variables with the string: \000 + # array_name1 val1\0 + # array_name1 val2\0 + # array_name2 val3\0 + # array_name2 val4\0 + eval "for i in \$$v; + echo -n $v \$i; + perl -e print\\\"\\\\0\\\"; + end;" + end; + # A final line to flush the last variable in Perl + perl -e print\"\\0\"; + end | perl -0 -ne ' + # Remove separator string \0 + chop; + # Split line into name and value + ($name,$val)=split(/ /,$_,2); + # Ignore read-only vars + $name=~/^(HOME|USER|COLUMNS|FISH_VERSION|LINES|PWD|SHLVL|_| + fish_pid|history|hostname|status|version)$/x and next; + # Single quote $val + if($val =~ /[^-_.+a-z0-9\/]/i) { + $val =~ s/\047/\047"\047"\047/g; # "-quote single quotes + $val = "\047$val\047"; # single-quote entire string + $val =~ s/^\047\047|\047\047$//g; # Remove unneeded '' at ends + } elsif ($val eq "") { + $val = "\047\047"; + } + + if($name ne $last and $last) { + # The $name is different, so this is a new variable. + # Print the last one. + # Separate list elements by 2 spaces + $"=" "; + print "set $last @qval;\n"; + @qval=(); + } + push @qval,$val; + $last=$name; + '| \ + perl -pe 's/\001/\002/g and not $printed++ and print STDERR + "env_parallel: Warning: ASCII value 1 in variables is not supported\n"; + s/\n/\001/g' + end; + ) + # If --record-env: exit + perl -e 'exit grep { /^--record-env$/ } @ARGV' -- $argv; and parallel $argv; + set _parallel_exit_CODE $status + set -e PARALLEL_ENV + return $_parallel_exit_CODE +end |