This commit is contained in:
Fabian Homborg 2020-11-22 14:39:48 +01:00
parent e30f661867
commit 2e55e34544
52 changed files with 370 additions and 239 deletions

View File

@ -13,6 +13,7 @@ import re
import shlex import shlex
import subprocess import subprocess
import sys import sys
try: try:
from itertools import zip_longest from itertools import zip_longest
except ImportError: except ImportError:
@ -20,7 +21,7 @@ except ImportError:
from difflib import SequenceMatcher from difflib import SequenceMatcher
# Directives can occur at the beginning of a line, or anywhere in a line that does not start with #. # Directives can occur at the beginning of a line, or anywhere in a line that does not start with #.
COMMENT_RE = r'^(?:[^#].*)?#\s*' COMMENT_RE = r"^(?:[^#].*)?#\s*"
# A regex showing how to run the file. # A regex showing how to run the file.
RUN_RE = re.compile(COMMENT_RE + r"RUN:\s+(.*)\n") RUN_RE = re.compile(COMMENT_RE + r"RUN:\s+(.*)\n")
@ -139,9 +140,10 @@ class Line(object):
ret = ret.replace("{", "{{").replace("}", "}}") ret = ret.replace("{", "{{").replace("}", "}}")
return ret return ret
class RunCmd(object): class RunCmd(object):
""" A command to run on a given Checker. """A command to run on a given Checker.
Attributes: Attributes:
args: Unexpanded shell command as a string. args: Unexpanded shell command as a string.
""" """
@ -215,10 +217,16 @@ class TestFailure(object):
"", "",
] ]
if self.error_annotation_lines: if self.error_annotation_lines:
fields["error_annotation"] = " ".join([x.text for x in self.error_annotation_lines]) fields["error_annotation"] = " ".join(
fields["error_annotation_lineno"] = str(self.error_annotation_lines[0].number) [x.text for x in self.error_annotation_lines]
)
fields["error_annotation_lineno"] = str(
self.error_annotation_lines[0].number
)
if len(self.error_annotation_lines) > 1: if len(self.error_annotation_lines) > 1:
fields["error_annotation_lineno"] += ":" + str(self.error_annotation_lines[-1].number) fields["error_annotation_lineno"] += ":" + str(
self.error_annotation_lines[-1].number
)
fmtstrs += [ fmtstrs += [
" additional output on stderr:{error_annotation_lineno}:", " additional output on stderr:{error_annotation_lineno}:",
" {BOLD}{error_annotation}{RESET}", " {BOLD}{error_annotation}{RESET}",
@ -229,14 +237,19 @@ class TestFailure(object):
lastcheckline = None lastcheckline = None
for d in self.diff.get_grouped_opcodes(): for d in self.diff.get_grouped_opcodes():
for op, alo, ahi, blo, bhi in d: for op, alo, ahi, blo, bhi in d:
color="{BOLD}" color = "{BOLD}"
if op == 'replace' or op == 'delete': if op == "replace" or op == "delete":
color="{RED}" color = "{RED}"
# We got a new chunk, so we print a marker. # We got a new chunk, so we print a marker.
if alo > lasthi: if alo > lasthi:
fmtstrs += [ fmtstrs += [
" [...] from line " + str(self.checks[blo].line.number) " [...] from line "
+ " (" + self.lines[alo].file + ":" + str(self.lines[alo].number) + "):" + str(self.checks[blo].line.number)
+ " ("
+ self.lines[alo].file
+ ":"
+ str(self.lines[alo].number)
+ "):"
] ]
lasthi = ahi lasthi = ahi
@ -244,17 +257,41 @@ class TestFailure(object):
lastcheck = False lastcheck = False
for a, b in zip_longest(self.lines[alo:ahi], self.checks[blo:bhi]): for a, b in zip_longest(self.lines[alo:ahi], self.checks[blo:bhi]):
# Clean up strings for use in a format string - double up the curlies. # Clean up strings for use in a format string - double up the curlies.
astr = color + a.escaped_text(for_formatting=True) + "{RESET}" if a else "" astr = (
color + a.escaped_text(for_formatting=True) + "{RESET}"
if a
else ""
)
if b: if b:
bstr = "'{BLUE}" + b.line.escaped_text(for_formatting=True) + "{RESET}'" + " on line " + str(b.line.number) bstr = (
"'{BLUE}"
+ b.line.escaped_text(for_formatting=True)
+ "{RESET}'"
+ " on line "
+ str(b.line.number)
)
lastcheckline = b.line.number lastcheckline = b.line.number
if op == 'equal': if op == "equal":
fmtstrs += [" " + astr] fmtstrs += [" " + astr]
elif b and a: elif b and a:
fmtstrs += [" " + astr + " <= does not match " + b.type + " " + bstr] fmtstrs += [
" "
+ astr
+ " <= does not match "
+ b.type
+ " "
+ bstr
]
elif b: elif b:
fmtstrs += [" " + astr + " <= nothing to match " + b.type + " " + bstr] fmtstrs += [
" "
+ astr
+ " <= nothing to match "
+ b.type
+ " "
+ bstr
]
elif not b: elif not b:
string = " " + astr string = " " + astr
if bhi == len(self.checks): if bhi == len(self.checks):
@ -262,7 +299,10 @@ class TestFailure(object):
string += " <= no more checks" string += " <= no more checks"
lastcheck = True lastcheck = True
elif lastcheckline is not None: elif lastcheckline is not None:
string += " <= no check matches this, previous check on line " + str(lastcheckline) string += (
" <= no check matches this, previous check on line "
+ str(lastcheckline)
)
else: else:
string += " <= no check matches" string += " <= no check matches"
fmtstrs.append(string) fmtstrs.append(string)
@ -276,8 +316,8 @@ class TestFailure(object):
def perform_substitution(input_str, subs): def perform_substitution(input_str, subs):
""" Perform the substitutions described by subs to str """Perform the substitutions described by subs to str
Return the substituted string. Return the substituted string.
""" """
# Sort our substitutions into a list of tuples (key, value), descending by length. # Sort our substitutions into a list of tuples (key, value), descending by length.
# It needs to be descending because we need to try longer substitutions first. # It needs to be descending because we need to try longer substitutions first.
@ -368,11 +408,22 @@ class TestRun(object):
# If there's a mismatch or still lines or checkers, we have a failure. # If there's a mismatch or still lines or checkers, we have a failure.
# Otherwise it's success. # Otherwise it's success.
if mismatches: if mismatches:
return TestFailure(mismatches[0][0], mismatches[0][1], self, diff=diff, lines=usedlines, checks=usedchecks) return TestFailure(
mismatches[0][0],
mismatches[0][1],
self,
diff=diff,
lines=usedlines,
checks=usedchecks,
)
elif lineq: elif lineq:
return TestFailure(lineq[-1], None, self, diff=diff, lines=usedlines, checks=usedchecks) return TestFailure(
lineq[-1], None, self, diff=diff, lines=usedlines, checks=usedchecks
)
elif checkq: elif checkq:
return TestFailure(None, checkq[-1], self, diff=diff, lines=usedlines, checks=usedchecks) return TestFailure(
None, checkq[-1], self, diff=diff, lines=usedlines, checks=usedchecks
)
else: else:
# Success! # Success!
return None return None
@ -381,8 +432,8 @@ class TestRun(object):
""" Run the command. Return a TestFailure, or None. """ """ Run the command. Return a TestFailure, or None. """
def split_by_newlines(s): def split_by_newlines(s):
""" Decode a string and split it by newlines only, """Decode a string and split it by newlines only,
retaining the newlines. retaining the newlines.
""" """
return [s + "\n" for s in s.decode("utf-8").split("\n")] return [s + "\n" for s in s.decode("utf-8").split("\n")]
@ -420,7 +471,7 @@ class TestRun(object):
# non-matching or unmatched stderr text, then annotate the outfail # non-matching or unmatched stderr text, then annotate the outfail
# with it. # with it.
if outfail and errfail and errfail.line: if outfail and errfail and errfail.line:
outfail.error_annotation_lines = errlines[errfail.line.number - 1:] outfail.error_annotation_lines = errlines[errfail.line.number - 1 :]
# Trim a trailing newline # Trim a trailing newline
if outfail.error_annotation_lines[-1].text == "\n": if outfail.error_annotation_lines[-1].text == "\n":
del outfail.error_annotation_lines[-1] del outfail.error_annotation_lines[-1]
@ -528,8 +579,8 @@ def check_path(path, subs, config, failure_handler):
def parse_subs(subs): def parse_subs(subs):
""" Given a list of input substitutions like 'foo=bar', """Given a list of input substitutions like 'foo=bar',
return a dictionary like {foo:bar}, or exit if invalid. return a dictionary like {foo:bar}, or exit if invalid.
""" """
result = {} result = {}
for sub in subs: for sub in subs:

View File

@ -79,7 +79,7 @@ def pexpect_error_type(err):
class Message(object): class Message(object):
""" Some text either sent-to or received-from the spawned proc. """Some text either sent-to or received-from the spawned proc.
Attributes: Attributes:
dir: the message direction, either DIR_INPUT or DIR_OUTPUT dir: the message direction, either DIR_INPUT or DIR_OUTPUT
@ -115,7 +115,7 @@ class Message(object):
class SpawnedProc(object): class SpawnedProc(object):
""" A process, talking to our ptty. This wraps pexpect.spawn. """A process, talking to our ptty. This wraps pexpect.spawn.
Attributes: Attributes:
colorize: whether error messages should have ANSI color escapes colorize: whether error messages should have ANSI color escapes
@ -127,15 +127,15 @@ class SpawnedProc(object):
""" """
def __init__(self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy()): def __init__(self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy()):
""" Construct from a name, timeout, and environment. """Construct from a name, timeout, and environment.
Args: Args:
name: the name of the executable to launch, as a key into the name: the name of the executable to launch, as a key into the
environment dictionary. By default this is 'fish' but may be environment dictionary. By default this is 'fish' but may be
other executables. other executables.
timeout: A timeout to pass to pexpect. This indicates how long to wait timeout: A timeout to pass to pexpect. This indicates how long to wait
before giving up on some expected output. before giving up on some expected output.
env: a string->string dictionary, describing the environment variables. env: a string->string dictionary, describing the environment variables.
""" """
if name not in env: if name not in env:
raise ValueError("'name' variable not found in environment" % name) raise ValueError("'name' variable not found in environment" % name)
@ -155,8 +155,8 @@ class SpawnedProc(object):
return now - self.start_time return now - self.start_time
def send(self, s): def send(self, s):
""" Cover over pexpect.spawn.send(). """Cover over pexpect.spawn.send().
Send the given string to the tty, returning the number of bytes written. Send the given string to the tty, returning the number of bytes written.
""" """
res = self.spawn.send(s) res = self.spawn.send(s)
when = self.time_since_first_message() when = self.time_since_first_message()
@ -164,22 +164,22 @@ class SpawnedProc(object):
return res return res
def sendline(self, s): def sendline(self, s):
""" Cover over pexpect.spawn.sendline(). """Cover over pexpect.spawn.sendline().
Send the given string + linesep to the tty, returning the number of bytes written. Send the given string + linesep to the tty, returning the number of bytes written.
""" """
return self.send(s + os.linesep) return self.send(s + os.linesep)
def expect_re(self, pat, pat_desc=None, unmatched=None, **kwargs): def expect_re(self, pat, pat_desc=None, unmatched=None, **kwargs):
""" Cover over pexpect.spawn.expect(). """Cover over pexpect.spawn.expect().
Consume all "new" output of self.spawn until the given pattern is matched, or Consume all "new" output of self.spawn until the given pattern is matched, or
the timeout is reached. the timeout is reached.
Note that output between the current position and the location of the match is Note that output between the current position and the location of the match is
consumed as well. consumed as well.
The pattern is typically a regular expression in string form, but may also be The pattern is typically a regular expression in string form, but may also be
any of the types accepted by pexpect.spawn.expect(). any of the types accepted by pexpect.spawn.expect().
If the 'unmatched' parameter is given, it is printed as part of the error message If the 'unmatched' parameter is given, it is printed as part of the error message
of any failure. of any failure.
On failure, this prints an error and exits. On failure, this prints an error and exits.
""" """
try: try:
self.spawn.expect(pat, **kwargs) self.spawn.expect(pat, **kwargs)
@ -201,15 +201,15 @@ class SpawnedProc(object):
return self.expect_re(re.escape(s), **kwargs) return self.expect_re(re.escape(s), **kwargs)
def expect_prompt(self, *args, increment=True, **kwargs): def expect_prompt(self, *args, increment=True, **kwargs):
""" Convenience function which matches some text and then a prompt. """Convenience function which matches some text and then a prompt.
Match the given positional arguments as expect_re, and then look Match the given positional arguments as expect_re, and then look
for a prompt. for a prompt.
If increment is set, then this should be a new prompt and the prompt counter If increment is set, then this should be a new prompt and the prompt counter
should be bumped; otherwise this is not a new prompt. should be bumped; otherwise this is not a new prompt.
Returns None on success, and exits on failure. Returns None on success, and exits on failure.
Example: Example:
sp.sendline("echo hello world") sp.sendline("echo hello world")
sp.expect_prompt("hello world") sp.expect_prompt("hello world")
""" """
if args: if args:
self.expect_re(*args, **kwargs) self.expect_re(*args, **kwargs)
@ -221,10 +221,10 @@ class SpawnedProc(object):
) )
def report_exception_and_exit(self, pat, unmatched, err): def report_exception_and_exit(self, pat, unmatched, err):
""" Things have gone badly. """Things have gone badly.
We have an exception 'err', some pexpect.ExceptionPexpect. We have an exception 'err', some pexpect.ExceptionPexpect.
Report it to stdout, along with the offending call site. Report it to stdout, along with the offending call site.
If 'unmatched' is set, print it to stdout. If 'unmatched' is set, print it to stdout.
""" """
colors = self.colors() colors = self.colors()
failtype = pexpect_error_type(err) failtype = pexpect_error_type(err)

View File

@ -114,8 +114,8 @@ pygments_style = None
# of _static/pygments.css # of _static/pygments.css
html_theme_path = ["."] html_theme_path = ["."]
html_theme = "python_docs_theme" html_theme = "python_docs_theme"
#html_theme_path = ["./cloud_sptheme/themes"] # html_theme_path = ["./cloud_sptheme/themes"]
#html_theme = "cloud" # html_theme = "cloud"
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
@ -196,7 +196,13 @@ man_pages = [
("tutorial", "fish-tutorial", "fish-shell tutorial", [author], 1), ("tutorial", "fish-tutorial", "fish-shell tutorial", [author], 1),
("CHANGELOG", "fish-changelog", "fish-shell changelog", [author], 1), ("CHANGELOG", "fish-changelog", "fish-shell changelog", [author], 1),
("completions", "fish-completions", "Writing fish completions", [author], 1), ("completions", "fish-completions", "Writing fish completions", [author], 1),
("fish_for_bash_users", "fish-for-bash-users", "A quick fish primer for those coming from bash", [author], 1), (
"fish_for_bash_users",
"fish-for-bash-users",
"A quick fish primer for those coming from bash",
[author],
1,
),
("faq", "fish-faq", "fish-shell faq", [author], 1), ("faq", "fish-faq", "fish-shell faq", [author], 1),
] ]
for path in sorted(glob.glob("cmds/*")): for path in sorted(glob.glob("cmds/*")):

View File

@ -62,9 +62,9 @@ ROLE_TO_TOKEN = {
def token_for_text_and_role(text, role): def token_for_text_and_role(text, role):
""" Return the pygments token for some input text and a fish role """Return the pygments token for some input text and a fish role
This applies any special cases of ROLE_TO_TOKEN. This applies any special cases of ROLE_TO_TOKEN.
""" """
if text.isspace(): if text.isspace():
# Here fish will return 'normal' or 'statement_terminator' for newline. # Here fish will return 'normal' or 'statement_terminator' for newline.
@ -77,13 +77,13 @@ def token_for_text_and_role(text, role):
def tokenize_fish_command(code, offset): def tokenize_fish_command(code, offset):
""" Tokenize some fish code, offset in a parent string, by shelling """Tokenize some fish code, offset in a parent string, by shelling
out to fish_indent. out to fish_indent.
fish_indent will output a list of csv lines: start,end,type.
This function returns a list of (start, tok, value) tuples, as fish_indent will output a list of csv lines: start,end,type.
Pygments expects.
This function returns a list of (start, tok, value) tuples, as
Pygments expects.
""" """
proc = subprocess.Popen( proc = subprocess.Popen(
["fish_indent", "--pygments"], ["fish_indent", "--pygments"],
@ -108,11 +108,11 @@ class FishIndentLexer(Lexer):
filenames = ["*.fish"] filenames = ["*.fish"]
def get_tokens_unprocessed(self, input_text): def get_tokens_unprocessed(self, input_text):
""" Return a list of (start, tok, value) tuples. """Return a list of (start, tok, value) tuples.
start is the index into the string start is the index into the string
tok is the token type (as above) tok is the token type (as above)
value is the string contents of the token value is the string contents of the token
""" """
result = [] result = []
if not any(s.startswith(">") for s in input_text.splitlines()): if not any(s.startswith(">") for s in input_text.splitlines()):

View File

@ -3,10 +3,9 @@ import os
def setup(app): def setup(app):
current_dir = os.path.abspath(os.path.dirname(__file__)) current_dir = os.path.abspath(os.path.dirname(__file__))
app.add_html_theme( app.add_html_theme("python_docs_theme", current_dir)
'python_docs_theme', current_dir)
return { return {
'parallel_read_safe': True, "parallel_read_safe": True,
'parallel_write_safe': True, "parallel_write_safe": True,
} }

View File

@ -6,14 +6,14 @@ function __fish_list_bluetoothctl_devices
# Output of `bluetoothctl devices`: # Output of `bluetoothctl devices`:
# Device 01:23:34:56:89:AB Name1 # Device 01:23:34:56:89:AB Name1
# Device 01:23:34:56:89:AC Name2 # Device 01:23:34:56:89:AC Name2
bluetoothctl devices 2> /dev/null | string replace -r "^Device " "" | string replace " " \t bluetoothctl devices 2>/dev/null | string replace -r "^Device " "" | string replace " " \t
end end
function __fish_list_bluetoothctl_controllers function __fish_list_bluetoothctl_controllers
# Output of `bluetoothctl list`: # Output of `bluetoothctl list`:
# Controller 01:23:34:56:89:AB Name1 [default] # Controller 01:23:34:56:89:AB Name1 [default]
# Controller 01:23:34:56:89:AC Name2 # Controller 01:23:34:56:89:AC Name2
bluetoothctl list 2> /dev/null | string replace -r "^Controller " "" | string replace " " \t bluetoothctl list 2>/dev/null | string replace -r "^Controller " "" | string replace " " \t
end end
complete -f -c bluetoothctl -n "not __fish_seen_subcommand_from $cmds" -a list -d "List available controllers" complete -f -c bluetoothctl -n "not __fish_seen_subcommand_from $cmds" -a list -d "List available controllers"

View File

@ -83,7 +83,7 @@ function __fish_ffmpeg_filters
end end
ffmpeg -hide_banner -loglevel quiet -filters | ffmpeg -hide_banner -loglevel quiet -filters |
string match -e -- '->' | # skip past the header string match -e -- '->' | # skip past the header
string match -er $filter | string match -er $filter |
string replace -rf '^ [TSC.]{3} +(\S+) +\S+->\S+ +(.*)' '$1\t$2' string replace -rf '^ [TSC.]{3} +(\S+) +\S+->\S+ +(.*)' '$1\t$2'
end end
@ -97,7 +97,7 @@ end
function __fish_ffmpeg_tunes function __fish_ffmpeg_tunes
set -l cmdline (commandline) set -l cmdline (commandline)
if string match -req '264' if string match -req 264
printf "%s\n" film animation grain stillimage fastdecode zerolatency psnr ssim printf "%s\n" film animation grain stillimage fastdecode zerolatency psnr ssim
end end
if string match -req '265|hevc' if string match -req '265|hevc'
@ -110,7 +110,7 @@ function __fish_ffmpeg_crfs
end end
function __fish_ffmpeg_profile function __fish_ffmpeg_profile
if string match -req '264' if string match -req 264
printf "%s\n" baseline main high printf "%s\n" baseline main high
end end
if string match -req '265|hevc' if string match -req '265|hevc'
@ -204,7 +204,7 @@ complete -c ffmpeg -s b -o "b:v" -d "Video bitrate"
complete -c ffmpeg -o dn -d "Disable data" complete -c ffmpeg -o dn -d "Disable data"
# Advanced video options # Advanced video options
complete -c ffmpeg -o pix_fmt complete -c ffmpeg -o pix_fmt
__fish_ffmpeg_complete_regex "-pix_fmt" "(__fish_ffmpeg_pix_fmts)" __fish_ffmpeg_complete_regex -pix_fmt "(__fish_ffmpeg_pix_fmts)"
# Audio options # Audio options
complete -c ffmpeg -o aframes -d "Set the number of audio frames to output" complete -c ffmpeg -o aframes -d "Set the number of audio frames to output"
@ -231,11 +231,11 @@ complete -c ffmpeg -o spre -d "Set the subtitle options to the indicated preset"
complete -c ffmpeg -o pre -o preset -d "Preset name" complete -c ffmpeg -o pre -o preset -d "Preset name"
__fish_ffmpeg_complete_regex 'pre(set)?' "(__fish_ffmpeg_presets)" __fish_ffmpeg_complete_regex 'pre(set)?' "(__fish_ffmpeg_presets)"
complete -c ffmpeg -o tune complete -c ffmpeg -o tune
__fish_ffmpeg_complete_regex 'tune' "(__fish_ffmpeg_tunes)" __fish_ffmpeg_complete_regex tune "(__fish_ffmpeg_tunes)"
complete -c ffmpeg -o crf -o q complete -c ffmpeg -o crf -o q
__fish_ffmpeg_complete_regex 'crf|q' "(__fish_ffmpeg_crfs)" __fish_ffmpeg_complete_regex 'crf|q' "(__fish_ffmpeg_crfs)"
complete -c ffmpeg -o profile complete -c ffmpeg -o profile
__fish_ffmpeg_complete_regex 'profile' "(__fish_ffmpeg_profiles)" __fish_ffmpeg_complete_regex profile "(__fish_ffmpeg_profiles)"
# Filters # Filters
# #
@ -281,11 +281,11 @@ function __fish_ffmpeg_concat_filter_args
end end
function __fish_ffmpeg_complete_filter function __fish_ffmpeg_complete_filter
set -l filter_type "all" set -l filter_type all
if string match -rq -- '^-(vf(ilter)?|f(ilter)?:v)' (__fish_ffmpeg_last_arg) if string match -rq -- '^-(vf(ilter)?|f(ilter)?:v)' (__fish_ffmpeg_last_arg)
set filter_type "video" set filter_type video
else if string match -rq -- '^-(af(ilter)?|f(ilter)?:a' (__fish_ffmpeg_last_arg) else if string match -rq -- '^-(af(ilter)?|f(ilter)?:a' (__fish_ffmpeg_last_arg)
set filter_type "audio" set filter_type audio
end end
# echo -e "\n **** $filter_type **** \n" > /dev/tty # echo -e "\n **** $filter_type **** \n" > /dev/tty

View File

@ -9,4 +9,4 @@ complete -f -c gapplication -n __fish_use_subcommand -a list-actions -d "List av
complete -f -c gapplication -n __fish_use_subcommand -a action -d "Activate an action" complete -f -c gapplication -n __fish_use_subcommand -a action -d "Activate an action"
# Arguments of help command # Arguments of help command
complete -f -c gapplication -n "__fish_seen_subcommand_from help" -a "help version list-apps launch list-actions action" -d "Command" complete -f -c gapplication -n "__fish_seen_subcommand_from help" -a "help version list-apps launch list-actions action" -d Command

View File

@ -4,7 +4,7 @@
set -l supported_schemes admin afc afp archive burn cdda computer dav dav+sd davs davs+sd dns-sd file ftp ftpis ftps google-drive gphoto2 http https localtest mtp network nfs recent sftp smb ssh test trash set -l supported_schemes admin afc afp archive burn cdda computer dav dav+sd davs davs+sd dns-sd file ftp ftpis ftps google-drive gphoto2 http https localtest mtp network nfs recent sftp smb ssh test trash
for scheme in $supported_schemes for scheme in $supported_schemes
complete -c gio -n "__fish_seen_subcommand_from cat copy info list mkdir monitor mount move open rename remove save set trash tree" -a "$scheme": -d "Scheme" complete -c gio -n "__fish_seen_subcommand_from cat copy info list mkdir monitor mount move open rename remove save set trash tree" -a "$scheme": -d Scheme
end end
# Commands # Commands
@ -28,7 +28,7 @@ complete -f -c gio -n __fish_use_subcommand -a trash -d "Move files to the trash
complete -f -c gio -n __fish_use_subcommand -a tree -d "Lists the contents of locations in a tree" complete -f -c gio -n __fish_use_subcommand -a tree -d "Lists the contents of locations in a tree"
# Arguments of help command # Arguments of help command
complete -f -c gio -n "__fish_seen_subcommand_from help" -a "version cat copy info list mime mkdir monitor mount move open rename remove save set trash tree" -d "Command" complete -f -c gio -n "__fish_seen_subcommand_from help" -a "version cat copy info list mime mkdir monitor mount move open rename remove save set trash tree" -d Command
# Arguments of mime command # Arguments of mime command
function __fish_gio_list_mimetypes function __fish_gio_list_mimetypes
@ -76,13 +76,13 @@ complete -f -c gio -n "__fish_seen_subcommand_from monitor" -s m -l mounts -d "W
# Options of mount command # Options of mount command
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s m -l mountable -d "Mount as mountable" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s m -l mountable -d "Mount as mountable"
complete -x -c gio -n "__fish_seen_subcommand_from mount" -s d -l device -d "Mount volume" complete -x -c gio -n "__fish_seen_subcommand_from mount" -s d -l device -d "Mount volume"
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s u -l unmount -d "Unmount" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s u -l unmount -d Unmount
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s e -l eject -d "Eject" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s e -l eject -d Eject
complete -x -c gio -n "__fish_seen_subcommand_from mount" -s t -l stop -d "Stop drive" complete -x -c gio -n "__fish_seen_subcommand_from mount" -s t -l stop -d "Stop drive"
complete -x -c gio -n "__fish_seen_subcommand_from mount" -s s -l unmount-scheme -a "$supported_schemes" -d "Unmount all mounts with the given scheme" complete -x -c gio -n "__fish_seen_subcommand_from mount" -s s -l unmount-scheme -a "$supported_schemes" -d "Unmount all mounts with the given scheme"
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s f -l force -d "Ignore outstanding file operations" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s f -l force -d "Ignore outstanding file operations"
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s a -l anonymous -d "Use an anonymous user" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s a -l anonymous -d "Use an anonymous user"
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s l -l list -d "List" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s l -l list -d List
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s o -l monitor -d "Monitor events" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s o -l monitor -d "Monitor events"
complete -f -c gio -n "__fish_seen_subcommand_from mount" -s i -l detail -d "Show extra information" complete -f -c gio -n "__fish_seen_subcommand_from mount" -s i -l detail -d "Show extra information"
complete -x -c gio -n "__fish_seen_subcommand_from mount" -l tcrypt-pim -d "The numeric PIM when unlocking a VeraCrypt volume" complete -x -c gio -n "__fish_seen_subcommand_from mount" -l tcrypt-pim -d "The numeric PIM when unlocking a VeraCrypt volume"

View File

@ -11,4 +11,4 @@ complete -f -c gresource -n "__fish_not_contain_opt section && __fish_use_subcom
complete -f -c gresource -n "__fish_not_contain_opt section && __fish_use_subcommand" -a help -d "Prints help" complete -f -c gresource -n "__fish_not_contain_opt section && __fish_use_subcommand" -a help -d "Prints help"
# Arguments of help command # Arguments of help command
complete -f -c gresource -n "__fish_seen_subcommand_from help" -a "list details extract sections help" -d "Command" complete -f -c gresource -n "__fish_seen_subcommand_from help" -a "list details extract sections help" -d Command

View File

@ -2,24 +2,24 @@
complete -c vips -s l -l list -d 'List objects' complete -c vips -s l -l list -d 'List objects'
complete -c vips -s p -l plugin -d 'Load PLUGIN' complete -c vips -s p -l plugin -d 'Load PLUGIN'
complete -c vips -s v -l version -d 'Print version' complete -c vips -s v -l version -d 'Print version'
complete -c vips -l vips-concurrency -d 'Evaluate with N threads' complete -c vips -l vips-concurrency -d 'Evaluate with N threads'
complete -c vips -l vips-progress -d 'Show progress feedback' complete -c vips -l vips-progress -d 'Show progress feedback'
complete -c vips -l vips-leak -d 'Leak-check on exit' complete -c vips -l vips-leak -d 'Leak-check on exit'
complete -c vips -l vips-profile -d 'Profile and dump timing on exit' complete -c vips -l vips-profile -d 'Profile and dump timing on exit'
complete -c vips -l vips-disc-threshold -d 'Decompress images larger than N' complete -c vips -l vips-disc-threshold -d 'Decompress images larger than N'
complete -c vips -l vips-novector -d 'Disable vectorised operations' complete -c vips -l vips-novector -d 'Disable vectorised operations'
complete -c vips -l vips-cache-max -d 'Cache at most N operations' complete -c vips -l vips-cache-max -d 'Cache at most N operations'
complete -c vips -l vips-cache-max-memory -d 'Cache at most N bytes in memory' complete -c vips -l vips-cache-max-memory -d 'Cache at most N bytes in memory'
complete -c vips -l vips-cache-max-files -d 'Allow at most N open files' complete -c vips -l vips-cache-max-files -d 'Allow at most N open files'
complete -c vips -l vips-cache-trace -d 'Trace operation cache' complete -c vips -l vips-cache-trace -d 'Trace operation cache'
complete -c vips -l vips-cache-dump -d 'Dump operation cache on exit' complete -c vips -l vips-cache-dump -d 'Dump operation cache on exit'
complete -c vips -l vips-version -d 'Print libvips version' complete -c vips -l vips-version -d 'Print libvips version'
complete -c vips -l vips-config -d 'Print libvips config' complete -c vips -l vips-config -d 'Print libvips config'
complete -c vips -l vips-pipe-read-limit -d 'Pipe read limit (bytes)' complete -c vips -l vips-pipe-read-limit -d 'Pipe read limit (bytes)'
# Operations # Operations
complete -c vips -n '__fish_is_first_token' -xa "(__fish_vips_ops)" complete -c vips -n __fish_is_first_token -xa "(__fish_vips_ops)"
function __fish_vips_ops function __fish_vips_ops
vips -l | string match -rv _base | string replace -rf '^\s*\S+ \((.+?)\), +(\S.*?)(?:\s*[,(].*)?$' '$1\t$2' vips -l | string match -rv _base | string replace -rf '^\s*\S+ \((.+?)\), +(\S.*?)(?:\s*[,(].*)?$' '$1\t$2'
end end

View File

@ -135,7 +135,6 @@ function __fish_complete_mount_opts
barrier={0,1}\ barrier={0,1}\
user_xattr\ user_xattr\
acl\ acl\
set -l token (commandline -tc | string replace -r '^-o' -- '') set -l token (commandline -tc | string replace -r '^-o' -- '')
set -l args (string split , -- $token) set -l args (string split , -- $token)

View File

@ -29,7 +29,7 @@ function __fish_print_pipestatus --description "Print pipestatus for prompt"
set last_status_string " "$status_color$last_status set last_status_string " "$status_color$last_status
end end
printf "%s" $brace_sep_color $left_brace \ printf "%s" $brace_sep_color $left_brace \
$status_color $last_pipestatus_string \ $status_color $last_pipestatus_string \
$brace_sep_color $right_brace $last_status_string (set_color normal) $brace_sep_color $right_brace $last_status_string (set_color normal)
end end
end end

View File

@ -8,8 +8,8 @@ function __fish_print_zfs_snapshots -d "Lists ZFS snapshots"
set current_dataset (string replace -rf "([^@]+)@?.*" '$1' -- $current_token) set current_dataset (string replace -rf "([^@]+)@?.*" '$1' -- $current_token)
set filtered_results (string match -ie -- $current_dataset $fast_results) set filtered_results (string match -ie -- $current_dataset $fast_results)
if contains -- --force $argv || if contains -- --force $argv ||
string match -ieq @ -- $current_token || string match -ieq @ -- $current_token ||
not set -q filtered_results[2] not set -q filtered_results[2]
# Ignore errors because the dataset specified could be non-existent # Ignore errors because the dataset specified could be non-existent
zfs list -t snapshot -o name -H -d 1 $current_dataset 2>/dev/null zfs list -t snapshot -o name -H -d 1 $current_dataset 2>/dev/null

View File

@ -2,10 +2,10 @@ function __fish_status_to_signal --description "Print signal name from argument
for arg in $argv for arg in $argv
if test $arg -gt 128 if test $arg -gt 128
set -l signals SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABRT SIGBUS \ set -l signals SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABRT SIGBUS \
SIGFPE SIGKILL SIGUSR1 SIGSEGV SIGUSR2 SIGPIPE SIGALRM \ SIGFPE SIGKILL SIGUSR1 SIGSEGV SIGUSR2 SIGPIPE SIGALRM \
SIGTERM SIGSTKFLT SIGCHLD SIGCONT SIGSTOP SIGTSTP \ SIGTERM SIGSTKFLT SIGCHLD SIGCONT SIGSTOP SIGTSTP \
SIGTTIN SIGTTOU SIGURG SIGXCPU SIGXFSZ SIGVTALRM \ SIGTTIN SIGTTOU SIGURG SIGXCPU SIGXFSZ SIGVTALRM \
SIGPROF SIGWINCH SIGIO SIGPWR SIGSYS SIGPROF SIGWINCH SIGIO SIGPWR SIGSYS
set -l sigix (math $arg - 128) set -l sigix (math $arg - 128)
if test $sigix -le (count $signals) if test $sigix -le (count $signals)
echo $signals[$sigix] echo $signals[$sigix]

View File

@ -59,14 +59,14 @@ else if type -q pkgfile
end end
else if type -q pacman else if type -q pacman
function fish_command_not_found function fish_command_not_found
set -l paths $argv[1] set -l paths $argv[1]
# If we've not been given an absolute path, try $PATH as the starting point, # If we've not been given an absolute path, try $PATH as the starting point,
# otherwise pacman will try *every path*, and e.g. bash-completion # otherwise pacman will try *every path*, and e.g. bash-completion
# isn't helpful. # isn't helpful.
string match -q '/*' -- $argv[1]; or set paths $PATH/$argv[1] string match -q '/*' -- $argv[1]; or set paths $PATH/$argv[1]
# Pacman only prints the path, so we still need to print the error. # Pacman only prints the path, so we still need to print the error.
__fish_default_command_not_found_handler $argv[1] __fish_default_command_not_found_handler $argv[1]
pacman -F $paths pacman -F $paths
end end
end end
# Use standard fish command not found handler otherwise # Use standard fish command not found handler otherwise

View File

@ -392,7 +392,9 @@ class Type2ManParser(ManParser):
options_section_regex = re.compile("\.SH OPTIONS(.*?)(\.SH|\Z)", re.DOTALL) options_section_regex = re.compile("\.SH OPTIONS(.*?)(\.SH|\Z)", re.DOTALL)
options_section = re.search(options_section_regex, manpage).group(1) options_section = re.search(options_section_regex, manpage).group(1)
options_parts_regex = re.compile("\.[IT]P( \d+(\.\d)?i?)?(.*?)\.([IT]P|UNINDENT|UN|SH)", re.DOTALL) options_parts_regex = re.compile(
"\.[IT]P( \d+(\.\d)?i?)?(.*?)\.([IT]P|UNINDENT|UN|SH)", re.DOTALL
)
options_matched = re.search(options_parts_regex, options_section) options_matched = re.search(options_parts_regex, options_section)
add_diagnostic("Command is %r" % CMDNAME) add_diagnostic("Command is %r" % CMDNAME)
@ -421,6 +423,7 @@ class Type2ManParser(ManParser):
options_section = options_section[options_matched.end() - 3 :] options_section = options_section[options_matched.end() - 3 :]
options_matched = re.search(options_parts_regex, options_section) options_matched = re.search(options_parts_regex, options_section)
class Type3ManParser(ManParser): class Type3ManParser(ManParser):
def is_my_type(self, manpage): def is_my_type(self, manpage):
return compile_and_search("\.SH DESCRIPTION(.*?)", manpage) != None return compile_and_search("\.SH DESCRIPTION(.*?)", manpage) != None
@ -467,7 +470,9 @@ class Type4ManParser(ManParser):
return compile_and_search("\.SH FUNCTION LETTERS(.*?)", manpage) != None return compile_and_search("\.SH FUNCTION LETTERS(.*?)", manpage) != None
def parse_man_page(self, manpage): def parse_man_page(self, manpage):
options_section_regex = re.compile("\.SH FUNCTION LETTERS(.*?)(\.SH|\Z)", re.DOTALL) options_section_regex = re.compile(
"\.SH FUNCTION LETTERS(.*?)(\.SH|\Z)", re.DOTALL
)
options_section = re.search(options_section_regex, manpage).group(1) options_section = re.search(options_section_regex, manpage).group(1)
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL) options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
@ -502,9 +507,15 @@ class Type4ManParser(ManParser):
options_section = options_section[options_matched.end() - 3 :] options_section = options_section[options_matched.end() - 3 :]
options_matched = re.search(options_parts_regex, options_section) options_matched = re.search(options_parts_regex, options_section)
class TypeScdocManParser(ManParser): class TypeScdocManParser(ManParser):
def is_my_type(self, manpage): def is_my_type(self, manpage):
return compile_and_search(r"\.(\\)(\") Generated by scdoc(.*?)\.SH OPTIONS(.*?)", manpage) != None return (
compile_and_search(
r"\.(\\)(\") Generated by scdoc(.*?)\.SH OPTIONS(.*?)", manpage
)
!= None
)
def parse_man_page(self, manpage): def parse_man_page(self, manpage):
options_section_regex = re.compile("\.SH OPTIONS(.*?)\.SH", re.DOTALL) options_section_regex = re.compile("\.SH OPTIONS(.*?)\.SH", re.DOTALL)
@ -524,7 +535,7 @@ class TypeScdocManParser(ManParser):
while options_matched != None: while options_matched != None:
# Get first option and move options_section # Get first option and move options_section
option = options_matched.group(1) option = options_matched.group(1)
options_section = options_section[options_matched.end()::] options_section = options_section[options_matched.end() : :]
options_matched = re.match(options_parts_regex, options_section) options_matched = re.match(options_parts_regex, options_section)
option = remove_groff_formatting(option) option = remove_groff_formatting(option)
@ -540,7 +551,7 @@ class TypeScdocManParser(ManParser):
if len(option_clean) < 2: if len(option_clean) < 2:
add_diagnostic("Unable to split option from description") add_diagnostic("Unable to split option from description")
continue continue
# Name and description, others lines are ignored # Name and description, others lines are ignored
option_name = option_clean[0] option_name = option_clean[0]
option_description = option_clean[1] option_description = option_clean[1]
@ -758,6 +769,7 @@ def cleanup_autogenerated_file(path):
except (OSError, IOError): except (OSError, IOError):
pass pass
def parse_manpage_at_path(manpage_path, output_directory): def parse_manpage_at_path(manpage_path, output_directory):
# Return if CMDNAME is in 'ignoredcommands' # Return if CMDNAME is in 'ignoredcommands'
ignoredcommands = [ ignoredcommands = [
@ -862,14 +874,15 @@ def parse_manpage_at_path(manpage_path, output_directory):
output_file = codecs.open(fullpath, "w", encoding="utf-8") output_file = codecs.open(fullpath, "w", encoding="utf-8")
except IOError as err: except IOError as err:
add_diagnostic( add_diagnostic(
"Unable to open file '%s': error(%d): %s" "Unable to open file '%s': error(%d): %s"
% (fullpath, err.errno, err.strerror) % (fullpath, err.errno, err.strerror)
) )
return False return False
# Output the magic word Autogenerated so we can tell if we can overwrite this # Output the magic word Autogenerated so we can tell if we can overwrite this
built_command_output.insert(0, "# " + CMDNAME + built_command_output.insert(
"\n# Autogenerated from man page " + manpage_path) 0, "# " + CMDNAME + "\n# Autogenerated from man page " + manpage_path
)
# built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABLE PARSER! Was really using Type2 but reporting TypeDeroffManParser # built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABLE PARSER! Was really using Type2 but reporting TypeDeroffManParser
for line in built_command_output: for line in built_command_output:
@ -1021,7 +1034,10 @@ if __name__ == "__main__":
action="append", action="append",
) )
parser.add_argument( parser.add_argument(
"-d", "--directory", type=str, help="The directory to save the completions in", "-d",
"--directory",
type=str,
help="The directory to save the completions in",
) )
parser.add_argument( parser.add_argument(
"-k", "-k",
@ -1030,13 +1046,22 @@ if __name__ == "__main__":
action="store_true", action="store_true",
) )
parser.add_argument( parser.add_argument(
"-m", "--manpath", help="Whether to use manpath", action="store_true", "-m",
"--manpath",
help="Whether to use manpath",
action="store_true",
) )
parser.add_argument( parser.add_argument(
"-p", "--progress", help="Whether to show progress", action="store_true", "-p",
"--progress",
help="Whether to show progress",
action="store_true",
) )
parser.add_argument( parser.add_argument(
"-s", "--stdout", help="Write the completions to stdout", action="store_true", "-s",
"--stdout",
help="Write the completions to stdout",
action="store_true",
) )
parser.add_argument( parser.add_argument(
"-v", "-v",
@ -1046,7 +1071,10 @@ if __name__ == "__main__":
help="The level of debug output to show", help="The level of debug output to show",
) )
parser.add_argument( parser.add_argument(
"-z", "--deroff-only", help="Whether to just deroff", action="store_true", "-z",
"--deroff-only",
help="Whether to just deroff",
action="store_true",
) )
parser.add_argument("file_paths", type=str, nargs="*") parser.add_argument("file_paths", type=str, nargs="*")

View File

@ -165,8 +165,7 @@ def better_color(c1, c2):
def parse_color(color_str): def parse_color(color_str):
""" A basic function to parse a color string, for example, 'red' '--bold'. """A basic function to parse a color string, for example, 'red' '--bold'."""
"""
comps = color_str.split(" ") comps = color_str.split(" ")
color = "normal" color = "normal"
background_color = "" background_color = ""
@ -1174,7 +1173,9 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
except ImportError: except ImportError:
# If the platform doesn't support multiprocessing, we just do it one at a time. # If the platform doesn't support multiprocessing, we just do it one at a time.
# This happens e.g. on Termux. # This happens e.g. on Termux.
print("Platform doesn't support multiprocessing, running one at a time. This may take a while.") print(
"Platform doesn't support multiprocessing, running one at a time. This may take a while."
)
result.append(self.do_get_current_prompt()) result.append(self.do_get_current_prompt())
result.extend([self.read_one_sample_prompt(path) for path in paths]) result.extend([self.read_one_sample_prompt(path) for path in paths])
return result return result
@ -1499,6 +1500,7 @@ print(
) )
print("%sHit ENTER to stop.%s" % (esc["bold"], esc["exit_attribute_mode"])) print("%sHit ENTER to stop.%s" % (esc["bold"], esc["exit_attribute_mode"]))
def runThing(): def runThing():
if isMacOS10_12_5_OrLater(): if isMacOS10_12_5_OrLater():
subprocess.check_call(["open", fileurl]) subprocess.check_call(["open", fileurl])
@ -1509,6 +1511,7 @@ def runThing():
else: else:
webbrowser.open(fileurl) webbrowser.open(fileurl)
# Some browsers still block webbrowser.open if they haven't been opened before, # Some browsers still block webbrowser.open if they haven't been opened before,
# so we just spawn it in a thread. # so we just spawn it in a thread.
thread = threading.Thread(target=runThing) thread = threading.Thread(target=runThing)

View File

@ -197,7 +197,7 @@ void accept_field_visitor(FieldVisitor &v, bool /*reverse*/, Field &field) {
// Call visit_field on visitor \p v, for the field \p field and also \p rest. // Call visit_field on visitor \p v, for the field \p field and also \p rest.
template <typename FieldVisitor, typename Field, typename... Rest> template <typename FieldVisitor, typename Field, typename... Rest>
void accept_field_visitor(FieldVisitor &v, bool reverse, Field &field, Rest &... rest) { void accept_field_visitor(FieldVisitor &v, bool reverse, Field &field, Rest &...rest) {
if (!reverse) visit_1_field(v, field); if (!reverse) visit_1_field(v, field);
accept_field_visitor<FieldVisitor, Rest...>(v, reverse, rest...); accept_field_visitor<FieldVisitor, Rest...>(v, reverse, rest...);
if (reverse) visit_1_field(v, field); if (reverse) visit_1_field(v, field);

View File

@ -4,7 +4,8 @@
// //
// 1). Create a function in builtin.c with the following signature: // 1). Create a function in builtin.c with the following signature:
// //
// <tt>static maybe_t<int> builtin_NAME(parser_t &parser, io_streams_t &streams, wchar_t **argv)</tt> // <tt>static maybe_t<int> builtin_NAME(parser_t &parser, io_streams_t &streams, wchar_t
// **argv)</tt>
// //
// where NAME is the name of the builtin, and args is a zero-terminated list of arguments. // where NAME is the name of the builtin, and args is a zero-terminated list of arguments.
// //
@ -257,7 +258,8 @@ static maybe_t<int> builtin_count(parser_t &parser, io_streams_t &streams, wchar
/// This function handles both the 'continue' and the 'break' builtins that are used for loop /// This function handles both the 'continue' and the 'break' builtins that are used for loop
/// control. /// control.
static maybe_t<int> builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar_t **argv) { static maybe_t<int> builtin_break_continue(parser_t &parser, io_streams_t &streams,
wchar_t **argv) {
int is_break = (std::wcscmp(argv[0], L"break") == 0); int is_break = (std::wcscmp(argv[0], L"break") == 0);
int argc = builtin_count_args(argv); int argc = builtin_count_args(argv);

View File

@ -23,12 +23,10 @@ struct command_cmd_opts_t {
bool all_paths = false; bool all_paths = false;
}; };
static const wchar_t *const short_options = L":ahqsv"; static const wchar_t *const short_options = L":ahqsv";
static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h'}, static const struct woption long_options[] = {
{L"all", no_argument, nullptr, 'a'}, {L"help", no_argument, nullptr, 'h'}, {L"all", no_argument, nullptr, 'a'},
{L"quiet", no_argument, nullptr, 'q'}, {L"quiet", no_argument, nullptr, 'q'}, {L"query", no_argument, nullptr, 'q'},
{L"query", no_argument, nullptr, 'q'}, {L"search", no_argument, nullptr, 's'}, {nullptr, 0, nullptr, 0}};
{L"search", no_argument, nullptr, 's'},
{nullptr, 0, nullptr, 0}};
static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, wchar_t **argv, static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, wchar_t **argv,
parser_t &parser, io_streams_t &streams) { parser_t &parser, io_streams_t &streams) {

View File

@ -79,7 +79,8 @@ maybe_t<int> builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv)
streams.err.append_format(_(L"%ls: No suitable job: %d\n"), cmd, pid); streams.err.append_format(_(L"%ls: No suitable job: %d\n"), cmd, pid);
job = nullptr; job = nullptr;
} else if (!job->wants_job_control()) { } else if (!job->wants_job_control()) {
streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n"), streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to foreground because "
L"it is not under job control\n"),
cmd, pid, job->command_wcstr()); cmd, pid, job->command_wcstr());
job = nullptr; job = nullptr;
} }

View File

@ -199,8 +199,9 @@ static int validate_function_name(int argc, const wchar_t *const *argv, wcstring
/// Define a function. Calls into `function.cpp` to perform the heavy lifting of defining a /// Define a function. Calls into `function.cpp` to perform the heavy lifting of defining a
/// function. /// function.
maybe_t<int> builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, maybe_t<int> builtin_function(parser_t &parser, io_streams_t &streams,
const parsed_source_ref_t &source, const ast::block_statement_t &func_node) { const wcstring_list_t &c_args, const parsed_source_ref_t &source,
const ast::block_statement_t &func_node) {
assert(source && "Missing source in builtin_function"); assert(source && "Missing source in builtin_function");
// The wgetopt function expects 'function' as the first argument. Make a new wcstring_list with // The wgetopt function expects 'function' as the first argument. Make a new wcstring_list with
// that property. This is needed because this builtin has a different signature than the other // that property. This is needed because this builtin has a different signature than the other

View File

@ -12,6 +12,7 @@ namespace ast {
struct block_statement_t; struct block_statement_t;
} }
maybe_t<int> builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, maybe_t<int> builtin_function(parser_t &parser, io_streams_t &streams,
const parsed_source_ref_t &source, const ast::block_statement_t &func_node); const wcstring_list_t &c_args, const parsed_source_ref_t &source,
const ast::block_statement_t &func_node);
#endif #endif

View File

@ -286,7 +286,8 @@ maybe_t<int> builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t
wcstring new_func; wcstring new_func;
if (argc - optind != 2) { if (argc - optind != 2) {
streams.err.append_format(_(L"%ls: Expected exactly two names (current function name, and new function name)\n"), streams.err.append_format(_(L"%ls: Expected exactly two names (current function name, "
L"and new function name)\n"),
cmd); cmd);
builtin_print_error_trailer(parser, streams.err, cmd); builtin_print_error_trailer(parser, streams.err, cmd);
return STATUS_INVALID_ARGS; return STATUS_INVALID_ARGS;

View File

@ -129,14 +129,11 @@ maybe_t<int> builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **arg
bool print_last = false; bool print_last = false;
static const wchar_t *const short_options = L":cghlpq"; static const wchar_t *const short_options = L":cghlpq";
static const struct woption long_options[] = {{L"command", no_argument, nullptr, 'c'}, static const struct woption long_options[] = {
{L"group", no_argument, nullptr, 'g'}, {L"command", no_argument, nullptr, 'c'}, {L"group", no_argument, nullptr, 'g'},
{L"help", no_argument, nullptr, 'h'}, {L"help", no_argument, nullptr, 'h'}, {L"last", no_argument, nullptr, 'l'},
{L"last", no_argument, nullptr, 'l'}, {L"pid", no_argument, nullptr, 'p'}, {L"quiet", no_argument, nullptr, 'q'},
{L"pid", no_argument, nullptr, 'p'}, {L"query", no_argument, nullptr, 'q'}, {nullptr, 0, nullptr, 0}};
{L"quiet", no_argument, nullptr, 'q'},
{L"query", no_argument, nullptr, 'q'},
{nullptr, 0, nullptr, 0}};
int opt; int opt;
wgetopter_t w; wgetopter_t w;

View File

@ -489,8 +489,9 @@ maybe_t<int> builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **arg
int stream_stdin_is_a_tty = isatty(streams.stdin_fd); int stream_stdin_is_a_tty = isatty(streams.stdin_fd);
if (stream_stdin_is_a_tty && !opts.split_null) { if (stream_stdin_is_a_tty && !opts.split_null) {
// Read interactively using reader_readline(). This does not support splitting on null. // Read interactively using reader_readline(). This does not support splitting on null.
exit_res = read_interactive(parser, buff, opts.nchars, opts.shell, opts.silent, exit_res =
opts.prompt, opts.right_prompt, opts.commandline, streams.stdin_fd); read_interactive(parser, buff, opts.nchars, opts.shell, opts.silent, opts.prompt,
opts.right_prompt, opts.commandline, streams.stdin_fd);
} else if (!opts.nchars && !stream_stdin_is_a_tty && } else if (!opts.nchars && !stream_stdin_is_a_tty &&
lseek(streams.stdin_fd, 0, SEEK_CUR) != -1) { lseek(streams.stdin_fd, 0, SEEK_CUR) != -1) {
exit_res = read_in_chunks(streams.stdin_fd, buff, opts.split_null); exit_res = read_in_chunks(streams.stdin_fd, buff, opts.split_null);

View File

@ -91,7 +91,8 @@ maybe_t<int> builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t *
std::strerror(errno)); std::strerror(errno));
} else { } else {
// Who knows. Probably a bug in our wrealpath() implementation. // Who knows. Probably a bug in our wrealpath() implementation.
streams.err.append_format(_(L"builtin %ls: Invalid path: %ls\n"), cmd, argv[optind]); streams.err.append_format(_(L"builtin %ls: Invalid path: %ls\n"), cmd,
argv[optind]);
} }
return STATUS_CMD_ERROR; return STATUS_CMD_ERROR;

View File

@ -643,7 +643,8 @@ static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc,
parser_t &parser, io_streams_t &streams) { parser_t &parser, io_streams_t &streams) {
int ret = STATUS_CMD_OK; int ret = STATUS_CMD_OK;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
int scope = compute_scope(opts); // calculate the variable scope based on the provided options int scope =
compute_scope(opts); // calculate the variable scope based on the provided options
wchar_t *dest = argv[i]; wchar_t *dest = argv[i];
std::vector<long> indexes; std::vector<long> indexes;
@ -675,7 +676,8 @@ static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc,
wcstring_list_t result; wcstring_list_t result;
dest_var->to_list(result); dest_var->to_list(result);
erase_values(result, indexes); erase_values(result, indexes);
retval = env_set_reporting_errors(cmd, dest, scope, result, streams, parser.vars(), &evts); retval =
env_set_reporting_errors(cmd, dest, scope, result, streams, parser.vars(), &evts);
} }
// Fire any events. // Fire any events.

View File

@ -33,7 +33,8 @@
class parser_t; class parser_t;
static void print_modifiers(outputter_t &outp, bool bold, bool underline, bool italics, bool dim, bool reverse, rgb_color_t bg) { static void print_modifiers(outputter_t &outp, bool bold, bool underline, bool italics, bool dim,
bool reverse, rgb_color_t bg) {
if (bold && enter_bold_mode) { if (bold && enter_bold_mode) {
// These casts are needed to work with different curses implementations. // These casts are needed to work with different curses implementations.
writembs_nofail(outp, tparm(const_cast<char *>(enter_bold_mode))); writembs_nofail(outp, tparm(const_cast<char *>(enter_bold_mode)));
@ -59,11 +60,10 @@ static void print_modifiers(outputter_t &outp, bool bold, bool underline, bool i
if (!bg.is_none() && bg.is_normal()) { if (!bg.is_none() && bg.is_normal()) {
writembs_nofail(outp, tparm(const_cast<char *>(exit_attribute_mode))); writembs_nofail(outp, tparm(const_cast<char *>(exit_attribute_mode)));
} }
} }
static void print_colors(io_streams_t &streams, bool bold, bool underline, bool italics, bool dim,
static void print_colors(io_streams_t &streams, bool bold, bool underline, bool italics, bool dim, bool reverse, rgb_color_t bg) { bool reverse, rgb_color_t bg) {
outputter_t outp; outputter_t outp;
for (const auto &color_name : rgb_color_t::named_color_names()) { for (const auto &color_name : rgb_color_t::named_color_names()) {
if (!streams.out_is_redirected && isatty(STDOUT_FILENO)) { if (!streams.out_is_redirected && isatty(STDOUT_FILENO)) {
@ -134,7 +134,8 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
} }
const wchar_t *bgcolor = nullptr; const wchar_t *bgcolor = nullptr;
bool bold = false, underline = false, italics = false, dim = false, reverse = false, print = false; bool bold = false, underline = false, italics = false, dim = false, reverse = false,
print = false;
// Parse options to obtain the requested operation and the modifiers. // Parse options to obtain the requested operation and the modifiers.
int opt; int opt;

View File

@ -4,6 +4,7 @@
#include "builtin_type.h" #include "builtin_type.h"
#include <unistd.h> #include <unistd.h>
#include <string> #include <string>
#include "builtin.h" #include "builtin.h"

View File

@ -206,10 +206,11 @@ bool is_windows_subsystem_for_linux() {
int status = -1; int status = -1;
if (info.dli_sname[0] == '_') if (info.dli_sname[0] == '_')
demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
swprintf( swprintf(text, sizeof(text) / sizeof(wchar_t), L"%-3d %s + %td", i - skip_levels,
text, sizeof(text) / sizeof(wchar_t), L"%-3d %s + %td", i - skip_levels, status == 0 ? demangled
status == 0 ? demangled : info.dli_sname == nullptr ? symbols[i] : info.dli_sname, : info.dli_sname == nullptr ? symbols[i]
static_cast<char *>(callstack[i]) - static_cast<char *>(info.dli_saddr)); : info.dli_sname,
static_cast<char *>(callstack[i]) - static_cast<char *>(info.dli_saddr));
free(demangled); free(demangled);
} else { } else {
swprintf(text, sizeof(text) / sizeof(wchar_t), L"%-3d %s", i - skip_levels, symbols[i]); swprintf(text, sizeof(text) / sizeof(wchar_t), L"%-3d %s", i - skip_levels, symbols[i]);
@ -227,7 +228,7 @@ bool is_windows_subsystem_for_linux() {
debug_shared(msg_level, L"Backtrace:\n" + join_strings(bt, L'\n') + L'\n'); debug_shared(msg_level, L"Backtrace:\n" + join_strings(bt, L'\n') + L'\n');
} }
#else // HAVE_BACKTRACE_SYMBOLS #else // HAVE_BACKTRACE_SYMBOLS
[[gnu::noinline]] void show_stackframe(const wchar_t msg_level, int, int) { [[gnu::noinline]] void show_stackframe(const wchar_t msg_level, int, int) {
debug_shared(msg_level, L"Sorry, but your system does not support backtraces"); debug_shared(msg_level, L"Sorry, but your system does not support backtraces");

View File

@ -579,7 +579,7 @@ using std::make_unique;
#else #else
/// make_unique implementation /// make_unique implementation
template <typename T, typename... Args> template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args &&... args) { std::unique_ptr<T> make_unique(Args &&...args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
#endif #endif

View File

@ -1327,7 +1327,7 @@ using test_list_t = std::vector<test_t>;
// Add a new test to a test list based on a series of ints and texts. // Add a new test to a test list based on a series of ints and texts.
template <typename... Types> template <typename... Types>
void add_test(test_list_t *v, const Types &... types) { void add_test(test_list_t *v, const Types &...types) {
segment_t segments[] = {types...}; segment_t segments[] = {types...};
v->emplace_back(std::begin(segments), std::end(segments)); v->emplace_back(std::begin(segments), std::end(segments));
} }

View File

@ -139,7 +139,7 @@ class logger_t {
} }
template <typename T, typename... Ts> template <typename T, typename... Ts>
void log_args_impl(const T &arg, const Ts &... rest) { void log_args_impl(const T &arg, const Ts &...rest) {
log1(arg); log1(arg);
log1(' '); log1(' ');
log_args_impl<Ts...>(rest...); log_args_impl<Ts...>(rest...);
@ -151,7 +151,7 @@ class logger_t {
logger_t(); logger_t();
template <typename... Args> template <typename... Args>
void log_args(const category_t &cat, const Args &... args) { void log_args(const category_t &cat, const Args &...args) {
log1(cat.name); log1(cat.name);
log1(": "); log1(": ");
log_args_impl(args...); log_args_impl(args...);

View File

@ -79,7 +79,7 @@ class latch_t : detail::fixed_t {
void operator=(T &&value) { *this = make_unique<T>(std::move(value)); } void operator=(T &&value) { *this = make_unique<T>(std::move(value)); }
template <typename... Args> template <typename... Args>
void emplace(Args &&... args) { void emplace(Args &&...args) {
*this = make_unique<T>(std::forward<Args>(args)...); *this = make_unique<T>(std::forward<Args>(args)...);
} }
}; };

View File

@ -1116,8 +1116,8 @@ static bool should_import_bash_history_line(const wcstring &line) {
if (line.find(L"]]") != std::string::npos) return false; if (line.find(L"]]") != std::string::npos) return false;
if (line.find(L"((") != std::string::npos) return false; if (line.find(L"((") != std::string::npos) return false;
if (line.find(L"))") != std::string::npos) return false; if (line.find(L"))") != std::string::npos) return false;
// Skip lines with literal tabs since we don't handle them well and we don't know what they mean. // Skip lines with literal tabs since we don't handle them well and we don't know what they
// It could just be whitespace or it's actually passed somewhere (like e.g. `sed`). // mean. It could just be whitespace or it's actually passed somewhere (like e.g. `sed`).
if (line.find(L'\t') != std::string::npos) return false; if (line.find(L'\t') != std::string::npos) return false;
// Skip lines that end with a backslash. We do not handle multiline commands from bash history. // Skip lines that end with a backslash. We do not handle multiline commands from bash history.

View File

@ -194,8 +194,9 @@ class input_event_queue_t {
char_event_t readb(); char_event_t readb();
int in_{0}; int in_{0};
public: public:
input_event_queue_t(int in = 0) : in_(in) {}; input_event_queue_t(int in = 0) : in_(in){};
/// Function used by input_readch to read bytes from stdin until enough bytes have been read to /// Function used by input_readch to read bytes from stdin until enough bytes have been read to
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously /// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously

View File

@ -156,7 +156,7 @@ class maybe_t : private maybe_detail::conditionally_copyable_t<T> {
// Construct a value in-place. // Construct a value in-place.
template <class... Args> template <class... Args>
void emplace(Args &&... args) { void emplace(Args &&...args) {
reset(); reset();
impl_.filled = true; impl_.filled = true;
new (impl_.storage) T(std::forward<Args>(args)...); new (impl_.storage) T(std::forward<Args>(args)...);

View File

@ -208,7 +208,8 @@ enum class pipeline_position_t {
/// Error message on reaching maximum call stack depth. /// Error message on reaching maximum call stack depth.
#define CALL_STACK_LIMIT_EXCEEDED_ERR_MSG \ #define CALL_STACK_LIMIT_EXCEEDED_ERR_MSG \
_(L"The function call stack limit has been exceeded. Do you have an accidental infinite loop?") _(L"The function call stack limit has been exceeded. Do you have an accidental infinite " \
L"loop?")
/// Error message when encountering an illegal command name. /// Error message when encountering an illegal command name.
#define ILLEGAL_CMD_ERR_MSG _(L"Illegal command name '%ls'") #define ILLEGAL_CMD_ERR_MSG _(L"Illegal command name '%ls'")

View File

@ -754,7 +754,8 @@ end_execution_reason_t parse_execution_context_t::handle_command_not_found(
// Redirect to stderr // Redirect to stderr
auto io = io_chain_t{}; auto io = io_chain_t{};
io.append_from_specs({redirection_spec_t{STDOUT_FILENO, redirection_mode_t::fd, L"2"}}, L""); io.append_from_specs({redirection_spec_t{STDOUT_FILENO, redirection_mode_t::fd, L"2"}},
L"");
if (function_exists(L"fish_command_not_found", *parser)) { if (function_exists(L"fish_command_not_found", *parser)) {
buffer = L"fish_command_not_found"; buffer = L"fish_command_not_found";

View File

@ -380,7 +380,8 @@ void safe_report_exec_error(int err, const char *actual_cmd, const char *const *
auto len = strlen(interpreter); auto len = strlen(interpreter);
if (len && interpreter[len - 1] == '\r') { if (len && interpreter[len - 1] == '\r') {
debug_safe(0, debug_safe(0,
"The file uses windows line endings (\\r\\n). Run dos2unix or similar to fix it."); "The file uses windows line endings (\\r\\n). Run dos2unix or "
"similar to fix it.");
} else { } else {
debug_safe(0, debug_safe(0,
"The file '%s' specified the interpreter '%s', which is not an " "The file '%s' specified the interpreter '%s', which is not an "

View File

@ -144,10 +144,10 @@ static operation_context_t get_bg_context(const std::shared_ptr<environment_t> &
return operation_context_t{nullptr, *env, std::move(cancel_checker)}; return operation_context_t{nullptr, *env, std::move(cancel_checker)};
} }
/// We try to ensure that syntax highlighting completes appropriately before executing what the user typed. /// We try to ensure that syntax highlighting completes appropriately before executing what the user
/// But we do not want it to block forever - e.g. it may hang on determining if an arbitrary argument /// typed. But we do not want it to block forever - e.g. it may hang on determining if an arbitrary
/// is a path. This is how long we'll wait (in milliseconds) before giving up and performing a /// argument is a path. This is how long we'll wait (in milliseconds) before giving up and
/// no-io syntax highlighting. See #7418, #5912. /// performing a no-io syntax highlighting. See #7418, #5912.
static constexpr long kHighlightTimeoutForExecutionMs = 250; static constexpr long kHighlightTimeoutForExecutionMs = 250;
/// Get the debouncer for autosuggestions and background highlighting. /// Get the debouncer for autosuggestions and background highlighting.
@ -411,8 +411,7 @@ class reader_history_search_t {
// We can skip dedup in history_search_t because we do it ourselves in skips_. // We can skip dedup in history_search_t because we do it ourselves in skips_.
search_ = history_search_t( search_ = history_search_t(
*hist, text, *hist, text,
by_prefix() ? history_search_type_t::prefix : history_search_type_t::contains, by_prefix() ? history_search_type_t::prefix : history_search_type_t::contains, flags);
flags);
} }
/// Reset to inactive search. /// Reset to inactive search.
@ -952,7 +951,7 @@ void reader_data_t::paint_layout(const wchar_t *reason) {
if (!conf.in_silent_mode && !data.history_search_text.empty()) { if (!conf.in_silent_mode && !data.history_search_text.empty()) {
const wcstring &needle = data.history_search_text; const wcstring &needle = data.history_search_text;
const wcstring &haystack = cmd_line->text(); const wcstring &haystack = cmd_line->text();
size_t match_pos = ifind(haystack,needle); size_t match_pos = ifind(haystack, needle);
if (match_pos != wcstring::npos) { if (match_pos != wcstring::npos) {
for (size_t i = 0; i < needle.size(); i++) { for (size_t i = 0; i < needle.size(); i++) {
colors.at(match_pos + i).background = highlight_role_t::search_match; colors.at(match_pos + i).background = highlight_role_t::search_match;
@ -2071,7 +2070,8 @@ static void acquire_tty_or_exit(pid_t shell_pgid) {
if (check_for_orphaned_process(loop_count, shell_pgid)) { if (check_for_orphaned_process(loop_count, shell_pgid)) {
// We're orphaned, so we just die. Another sad statistic. // We're orphaned, so we just die. Another sad statistic.
const wchar_t *fmt = const wchar_t *fmt =
_(L"I appear to be an orphaned process, so I am quitting politely. My pid is %d."); _(L"I appear to be an orphaned process, so I am quitting politely. My pid is "
L"%d.");
FLOGF(warning, fmt, static_cast<int>(getpid())); FLOGF(warning, fmt, static_cast<int>(getpid()));
exit_without_destructors(1); exit_without_destructors(1);
} }
@ -2823,8 +2823,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
// //
// Also paging is already cancelled above. // Also paging is already cancelled above.
if (rls.complete_did_insert && if (rls.complete_did_insert &&
(rls.last_cmd == rl::complete (rls.last_cmd == rl::complete || rls.last_cmd == rl::complete_and_search)) {
|| rls.last_cmd == rl::complete_and_search)) {
editable_line_t *el = active_edit_line(); editable_line_t *el = active_edit_line();
el->undo(); el->undo();
update_buff_pos(el); update_buff_pos(el);
@ -3150,10 +3149,10 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
reader_history_search_t::mode_t mode = reader_history_search_t::mode_t mode =
(c == rl::history_token_search_backward || c == rl::history_token_search_forward) (c == rl::history_token_search_backward || c == rl::history_token_search_forward)
? reader_history_search_t::token ? reader_history_search_t::token
: (c == rl::history_prefix_search_backward || : (c == rl::history_prefix_search_backward ||
c == rl::history_prefix_search_forward) c == rl::history_prefix_search_forward)
? reader_history_search_t::prefix ? reader_history_search_t::prefix
: reader_history_search_t::line; : reader_history_search_t::line;
bool was_active_before = history_search.active(); bool was_active_before = history_search.active();
@ -3241,10 +3240,9 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
case rl::backward_kill_path_component: case rl::backward_kill_path_component:
case rl::backward_kill_bigword: { case rl::backward_kill_bigword: {
move_word_style_t style = move_word_style_t style =
(c == rl::backward_kill_bigword (c == rl::backward_kill_bigword ? move_word_style_whitespace
? move_word_style_whitespace : c == rl::backward_kill_path_component ? move_word_style_path_components
: c == rl::backward_kill_path_component ? move_word_style_path_components : move_word_style_punctuation);
: move_word_style_punctuation);
// Is this the same killring item as the last kill? // Is this the same killring item as the last kill?
bool newv = (rls.last_cmd != rl::backward_kill_word && bool newv = (rls.last_cmd != rl::backward_kill_word &&
rls.last_cmd != rl::backward_kill_path_component && rls.last_cmd != rl::backward_kill_path_component &&
@ -3783,7 +3781,8 @@ maybe_t<wcstring> reader_data_t::readline(int nchars_or_0) {
// Redraw the command line. This is what ensures the autosuggestion is hidden, etc. after the // Redraw the command line. This is what ensures the autosuggestion is hidden, etc. after the
// user presses enter. // user presses enter.
if (this->is_repaint_needed() || conf.in != STDIN_FILENO) this->layout_and_repaint(L"prepare to execute"); if (this->is_repaint_needed() || conf.in != STDIN_FILENO)
this->layout_and_repaint(L"prepare to execute");
// Finish any outstanding syntax highlighting (but do not wait forever). // Finish any outstanding syntax highlighting (but do not wait forever).
finish_highlighting_before_exec(); finish_highlighting_before_exec();

View File

@ -430,7 +430,8 @@ wcstring normalize_path(const wcstring &path, bool allow_leading_double_slashes)
wcstring result = join_strings(new_comps, sep); wcstring result = join_strings(new_comps, sep);
// Prepend one or two leading slashes. // Prepend one or two leading slashes.
// Two slashes are preserved. Three+ slashes are collapsed to one. (!) // Two slashes are preserved. Three+ slashes are collapsed to one. (!)
result.insert(0, allow_leading_double_slashes && leading_slashes > 2 ? 1 : leading_slashes, sep); result.insert(0, allow_leading_double_slashes && leading_slashes > 2 ? 1 : leading_slashes,
sep);
// Ensure ./ normalizes to . and not empty. // Ensure ./ normalizes to . and not empty.
if (result.empty()) result.push_back(L'.'); if (result.empty()) result.push_back(L'.');
return result; return result;

View File

@ -309,5 +309,5 @@ expect_prompt("\nb c d")
# Check that ctrl-z can be bound # Check that ctrl-z can be bound
sendline('bind \cz "echo bound ctrl-z"') sendline('bind \cz "echo bound ctrl-z"')
expect_prompt() expect_prompt()
send('\x1A') send("\x1A")
expect_str("bound ctrl-z") expect_str("bound ctrl-z")

View File

@ -4,7 +4,13 @@ from pexpect_helper import SpawnedProc
import signal import signal
sp = SpawnedProc() sp = SpawnedProc()
send, sendline, sleep, expect_str, expect_prompt = sp.send, sp.sendline, sp.sleep, sp.expect_str, sp.expect_prompt send, sendline, sleep, expect_str, expect_prompt = (
sp.send,
sp.sendline,
sp.sleep,
sp.expect_str,
sp.expect_prompt,
)
expect_prompt() expect_prompt()
# Verify that cancel-commandline does what we expect - see #7384. # Verify that cancel-commandline does what we expect - see #7384.

View File

@ -50,9 +50,11 @@ expect_prompt()
# Verify that asking to exit a second time does so. # Verify that asking to exit a second time does so.
send("exit\r") send("exit\r")
for t in range(0,3): for t in range(0, 3):
proc = subprocess.run( proc = subprocess.run(
["pgrep", "-l", "-f", "sleep 11"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ["pgrep", "-l", "-f", "sleep 11"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
) )
if proc.returncode != 0: if proc.returncode != 0:
break break

View File

@ -18,11 +18,13 @@ expect_prompt()
sendline("test -t 0; echo $status") sendline("test -t 0; echo $status")
expect_prompt("0") expect_prompt("0")
sendline("""function t sendline(
"""function t
test -t 0 && echo stdin test -t 0 && echo stdin
test -t 1 && echo stdout test -t 1 && echo stdout
test -t 2 && echo stderr test -t 2 && echo stderr
end""") end"""
)
expect_prompt() expect_prompt()
sendline("t") sendline("t")

View File

@ -40,7 +40,7 @@ expect_re("Job.*Group.*(CPU)?.*State.*Command")
expect_re(".*running.*sleep 20 &") expect_re(".*running.*sleep 20 &")
expect_prompt() expect_prompt()
sendline("echo $my_pid") sendline("echo $my_pid")
m = expect_re('\d+\r\n') m = expect_re("\d+\r\n")
expect_prompt() expect_prompt()
os.kill(int(m.group()), signal.SIGTERM) os.kill(int(m.group()), signal.SIGTERM)
expect_re("[0-9]+:0:sleep 20 &:SIGTERM:Polite quit request", timeout=20) expect_re("[0-9]+:0:sleep 20 &:SIGTERM:Polite quit request", timeout=20)

View File

@ -7,7 +7,9 @@ sendline, expect_prompt, expect_str = sp.sendline, sp.expect_prompt, sp.expect_s
# Test fish_postexec and $status_generation for interactive shells. # Test fish_postexec and $status_generation for interactive shells.
expect_prompt() expect_prompt()
sendline("function test_fish_postexec --on-event fish_postexec; printf 'pipestatus:%s, generation:%d, command:%s\\n' (string join '|' $pipestatus) $status_generation $argv; end") sendline(
"function test_fish_postexec --on-event fish_postexec; printf 'pipestatus:%s, generation:%d, command:%s\\n' (string join '|' $pipestatus) $status_generation $argv; end"
)
expect_prompt() expect_prompt()
generation = 1 generation = 1
@ -38,7 +40,9 @@ expect_prompt()
# multiple backgrounded jobs # multiple backgrounded jobs
sendline("sleep 1000 &; sleep 2000 &") sendline("sleep 1000 &; sleep 2000 &")
expect_str("pipestatus:0|1, generation:%d, command:sleep 1000 &; sleep 2000 &" % generation) expect_str(
"pipestatus:0|1, generation:%d, command:sleep 1000 &; sleep 2000 &" % generation
)
expect_prompt() expect_prompt()
# valid variable assignment # valid variable assignment
@ -48,18 +52,25 @@ expect_prompt()
# valid variable assignment with background job # valid variable assignment with background job
sendline("set foo bar; sleep 1000 &") sendline("set foo bar; sleep 1000 &")
expect_str("pipestatus:0|1, generation:%d, command:set foo bar; sleep 1000 &" % generation) expect_str(
"pipestatus:0|1, generation:%d, command:set foo bar; sleep 1000 &" % generation
)
expect_prompt() expect_prompt()
# Increments $status_generation if any job was foreground. # Increments $status_generation if any job was foreground.
sendline("false|true; sleep 1000 &") sendline("false|true; sleep 1000 &")
generation += 1 generation += 1
expect_str("pipestatus:1|0, generation:%d, command:false|true; sleep 1000 &" % generation) expect_str(
"pipestatus:1|0, generation:%d, command:false|true; sleep 1000 &" % generation
)
expect_prompt() expect_prompt()
sendline("sleep 1000 &; true|false|true") sendline("sleep 1000 &; true|false|true")
generation += 1 generation += 1
expect_str("pipestatus:0|1|0, generation:%d, command:sleep 1000 &; true|false|true" % generation) expect_str(
"pipestatus:0|1|0, generation:%d, command:sleep 1000 &; true|false|true"
% generation
)
expect_prompt() expect_prompt()
# Increments $status_generation for empty if/while blocks. # Increments $status_generation for empty if/while blocks.
@ -83,7 +94,9 @@ expect_prompt()
# This is an implementation detail, but the test case should prevent regressions. # This is an implementation detail, but the test case should prevent regressions.
sendline("function fail; false; end") sendline("function fail; false; end")
generation += 1 generation += 1
expect_str("pipestatus:0, generation:%d, command:function fail; false; end" % generation) expect_str(
"pipestatus:0, generation:%d, command:function fail; false; end" % generation
)
expect_prompt() expect_prompt()
# or an invalid variable assignment # or an invalid variable assignment
@ -111,15 +124,24 @@ expect_prompt()
# Or begin/end block with only backgrounded jobs. # Or begin/end block with only backgrounded jobs.
sendline("begin; sleep 200 &; sleep 400 &; end") sendline("begin; sleep 200 &; sleep 400 &; end")
expect_str("pipestatus:0|1|0, generation:%d, command:begin; sleep 200 &; sleep 400 &; end" % generation) expect_str(
"pipestatus:0|1|0, generation:%d, command:begin; sleep 200 &; sleep 400 &; end"
% generation
)
expect_prompt() expect_prompt()
# Or a combination of begin/end block and backgrounded job. # Or a combination of begin/end block and backgrounded job.
sendline("begin; sleep 200 &; end; sleep 400 &") sendline("begin; sleep 200 &; end; sleep 400 &")
expect_str("pipestatus:0|1|0, generation:%d, command:begin; sleep 200 &; end; sleep 400 &" % generation) expect_str(
"pipestatus:0|1|0, generation:%d, command:begin; sleep 200 &; end; sleep 400 &"
% generation
)
expect_prompt() expect_prompt()
# Or a combination with variable assignments # Or a combination with variable assignments
sendline("begin; set foo bar; sleep 1000 &; end; set bar baz; sleep 2000 &") sendline("begin; set foo bar; sleep 1000 &; end; set bar baz; sleep 2000 &")
expect_str("pipestatus:0|1|0, generation:%d, command:begin; set foo bar; sleep 1000 &; end; set bar baz; sleep 2000 &" % generation) expect_str(
"pipestatus:0|1|0, generation:%d, command:begin; set foo bar; sleep 1000 &; end; set bar baz; sleep 2000 &"
% generation
)
expect_prompt() expect_prompt()

View File

@ -41,7 +41,7 @@ expect_str("\x1b[33myellow")
expect_str("normal") expect_str("normal")
expect_prompt() expect_prompt()
sendline ("set_color --background blue --print-colors") sendline("set_color --background blue --print-colors")
expect_str("black") expect_str("black")
expect_str("blue") expect_str("blue")
expect_str("brblack") expect_str("brblack")
@ -60,4 +60,3 @@ expect_str("white")
expect_str("yellow") expect_str("yellow")
expect_str("normal") expect_str("normal")
expect_prompt() expect_prompt()

View File

@ -8,7 +8,9 @@ expect_prompt()
sendline("status job-control full") sendline("status job-control full")
expect_prompt() expect_prompt()
sendline("$fish -c 'status job-control full ; $fish_test_helper report_foreground' &; wait") sendline(
"$fish -c 'status job-control full ; $fish_test_helper report_foreground' &; wait"
)
expect_prompt() expect_prompt()
sendline("echo it worked") sendline("echo it worked")