mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
implement status function
when in a breakpoint
Another step to fixing #1310. This changes means that `status -L0 function` reports the correct function when inside a breakpoint.
This commit is contained in:
parent
1bee66548a
commit
30368d5526
6 changed files with 64 additions and 23 deletions
|
@ -42,7 +42,7 @@ The following operations (sub-commands) are available:
|
|||
|
||||
- `filename` prints the filename of the currently running script. Also `current-filename`, `-f` or `--current-filename`.
|
||||
|
||||
- `function` prints the name of the currently called function if able, when missing displays "Not a function". Also `current-function`, `-u` or `--current-function`.
|
||||
- `function` prints the name of the currently called function if able, when missing displays "N/A". Also `current-function`, `-u` or `--current-function`.
|
||||
|
||||
- `line-number` prints the line number of the currently running script. Also `current-line-number`, `-n` or `--current-line-number`.
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Define the default debugging prompt command.
|
||||
function fish_breakpoint_prompt --description "A right prompt to be used when `breakpoint` is executed"
|
||||
set -l saved_status $status
|
||||
set -l function (status current-function)
|
||||
set -l line (status current-line-number)
|
||||
set -l function (status -L0 function)
|
||||
set -l line (status -L0 line-number)
|
||||
# At the moment we don't include the filename because, even if we truncate it, it makes the
|
||||
# prompt too long.
|
||||
#set -l filename (status current-filename)
|
||||
#set -l filename (status filename)
|
||||
#set -l prompt "$filename:$function:$line >"
|
||||
set -l prompt "$function:$line"
|
||||
if test $saved_status -ne 0
|
||||
|
|
|
@ -78,16 +78,16 @@ int job_control_str_to_mode(const wchar_t *mode, wchar_t *cmd, io_streams_t &str
|
|||
|
||||
struct status_cmd_opts_t {
|
||||
bool print_help = false;
|
||||
status_cmd_t status_cmd = STATUS_UNDEF;
|
||||
int level = 1;
|
||||
int new_job_control_mode = -1;
|
||||
bool breakpoint_context = false;
|
||||
status_cmd_t status_cmd = STATUS_UNDEF;
|
||||
};
|
||||
|
||||
/// Note: Do not add new flags that represent subcommands. We're encouraging people to switch to
|
||||
/// the non-flag subcommand form. While these flags are deprecated they must be supported at
|
||||
/// least until fish 3.0 and possibly longer to avoid breaking everyones config.fish and other
|
||||
/// scripts.
|
||||
static const wchar_t *short_options = L":Bcbilfnhj:t";
|
||||
static const wchar_t *short_options = L":L:cbilfnhj:t";
|
||||
static const struct woption long_options[] = {{L"help", no_argument, NULL, 'h'},
|
||||
{L"is-command-substitution", no_argument, NULL, 'c'},
|
||||
{L"is-block", no_argument, NULL, 'b'},
|
||||
|
@ -98,12 +98,12 @@ static const struct woption long_options[] = {{L"help", no_argument, NULL, 'h'},
|
|||
{L"is-no-job-control", no_argument, NULL, 3},
|
||||
{L"filename", no_argument, NULL, 'f'},
|
||||
{L"current-filename", no_argument, NULL, 'f'},
|
||||
{L"level", required_argument, NULL, 'L'},
|
||||
{L"line", no_argument, NULL, 'n'},
|
||||
{L"line-number", no_argument, NULL, 'n'},
|
||||
{L"current-line-number", no_argument, NULL, 'n'},
|
||||
{L"job-control", required_argument, NULL, 'j'},
|
||||
{L"print-stack-trace", no_argument, NULL, 't'},
|
||||
{L"breakpoint", no_argument, NULL, 'B'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
/// Remember the status subcommand and disallow selecting more than one status subcommand.
|
||||
|
@ -149,8 +149,15 @@ static int parse_cmd_opts(status_cmd_opts_t &opts, int *optind, //!OCLINT(high
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'B': {
|
||||
opts.breakpoint_context = true;
|
||||
case 'L': {
|
||||
opts.level = fish_wcstoi(w.woptarg);
|
||||
if (opts.level < 0 || errno == ERANGE) {
|
||||
streams.err.append_format(_(L"%ls: Invalid level value '%ls'\n"), argv[0], w.woptarg);
|
||||
return STATUS_INVALID_ARGS;
|
||||
} else if (errno) {
|
||||
streams.err.append_format(BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
|
@ -301,20 +308,23 @@ int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
CHECK_FOR_UNEXPECTED_STATUS_ARGS(opts.status_cmd)
|
||||
const wchar_t *fn = parser.current_filename();
|
||||
|
||||
if (!fn) fn = _(L"Standard input");
|
||||
if (!fn) fn = _(L"stdin");
|
||||
streams.out.append_format(L"%ls\n", fn);
|
||||
break;
|
||||
}
|
||||
case STATUS_FUNCTION: {
|
||||
CHECK_FOR_UNEXPECTED_STATUS_ARGS(opts.status_cmd)
|
||||
const wchar_t *fn = parser.get_function_name();
|
||||
const wchar_t *fn = parser.get_function_name(opts.level);
|
||||
|
||||
if (!fn) fn = _(L"Not a function");
|
||||
if (!fn) fn = _(L"N/A");
|
||||
streams.out.append_format(L"%ls\n", fn);
|
||||
break;
|
||||
}
|
||||
case STATUS_LINE_NUMBER: {
|
||||
CHECK_FOR_UNEXPECTED_STATUS_ARGS(opts.status_cmd)
|
||||
// TBD is how to interpret the level argument when fetching the line number.
|
||||
// See issue #4161.
|
||||
// streams.out.append_format(L"%d\n", parser.get_lineno(opts.level));
|
||||
streams.out.append_format(L"%d\n", parser.get_lineno());
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -434,14 +434,15 @@ void parser_t::stack_trace_internal(size_t block_idx, wcstring *buff) const {
|
|||
}
|
||||
|
||||
/// Returns the name of the currently evaluated function if we are currently evaluating a function,
|
||||
/// null otherwise. This is tested by moving down the block-scope-stack, checking every block if it
|
||||
/// is of type FUNCTION_CALL.
|
||||
const wchar_t *parser_t::is_function() const {
|
||||
/// NULL otherwise. This is tested by moving down the block-scope-stack, checking every block if it
|
||||
/// is of type FUNCTION_CALL. If the caller doesn't specify a starting position in the stack we
|
||||
/// begin with the current block.
|
||||
const wchar_t *parser_t::is_function(size_t idx) const {
|
||||
// PCA: Have to make this a string somehow.
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
|
||||
const wchar_t *result = NULL;
|
||||
for (size_t block_idx = 0; block_idx < this->block_count(); block_idx++) {
|
||||
for (size_t block_idx = idx; block_idx < this->block_count(); block_idx++) {
|
||||
const block_t *b = this->block_at_index(block_idx);
|
||||
if (b->type() == FUNCTION_CALL || b->type() == FUNCTION_CALL_NO_SHADOW) {
|
||||
const function_block_t *fb = static_cast<const function_block_t *>(b);
|
||||
|
@ -455,7 +456,37 @@ const wchar_t *parser_t::is_function() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
const wchar_t *parser_t::get_function_name() { return this->is_function(); }
|
||||
/// Return the function name for the specified stack frame. Default is zero (current frame).
|
||||
/// The special value zero means the function frame immediately above the closest breakpoint frame.
|
||||
const wchar_t *parser_t::get_function_name(int level) {
|
||||
if (level == 0) {
|
||||
// Return the function name for the level preceding the most recent breakpoint. If there
|
||||
// isn't one return the function name for the current level.
|
||||
int idx = 0;
|
||||
for (const auto &b : block_stack) {
|
||||
const enum block_type_t type = b->type();
|
||||
if (type == BREAKPOINT) {
|
||||
return this->is_function(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return NULL; // couldn't find a breakpoint frame
|
||||
} else if (level == 1) {
|
||||
// Return the function name for the current level.
|
||||
return this->is_function();
|
||||
}
|
||||
|
||||
// Return the function name for the specific function stack frame.
|
||||
int idx = 0;
|
||||
for (const auto &b : block_stack) {
|
||||
const enum block_type_t type = b->type();
|
||||
if (type == FUNCTION_CALL || type == FUNCTION_CALL_NO_SHADOW) {
|
||||
if (--level == 0) return this->is_function(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return NULL; // couldn't find that function level
|
||||
}
|
||||
|
||||
int parser_t::get_lineno() const {
|
||||
int lineno = -1;
|
||||
|
|
|
@ -217,7 +217,7 @@ class parser_t {
|
|||
/// Returns the name of the currently evaluated function if we are currently evaluating a
|
||||
/// function, null otherwise. This is tested by moving down the block-scope-stack, checking
|
||||
/// every block if it is of type FUNCTION_CALL.
|
||||
const wchar_t *is_function() const;
|
||||
const wchar_t *is_function(size_t idx=0) const;
|
||||
|
||||
/// Helper for stack_trace().
|
||||
void stack_trace_internal(size_t block_idx, wcstring *out) const;
|
||||
|
@ -264,7 +264,7 @@ class parser_t {
|
|||
static void expand_argument_list(const wcstring &arg_src, expand_flags_t flags,
|
||||
std::vector<completion_t> *output);
|
||||
|
||||
/// Returns a string describing the current parser pisition in the format 'FILENAME (line
|
||||
/// Returns a string describing the current parser position in the format 'FILENAME (line
|
||||
/// LINE_NUMBER): LINE'. Example:
|
||||
///
|
||||
/// init.fish (line 127): ls|grep pancake
|
||||
|
@ -307,8 +307,8 @@ class parser_t {
|
|||
/// Return a description of the given blocktype.
|
||||
const wchar_t *get_block_desc(int block) const;
|
||||
|
||||
/// Return the current function name.
|
||||
const wchar_t *get_function_name();
|
||||
/// Return the function name for the specified stack frame. Default is one (current frame).
|
||||
const wchar_t *get_function_name(int level=1);
|
||||
|
||||
/// Removes a job.
|
||||
bool job_remove(job_t *job);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Not a function
|
||||
N/A
|
||||
test_function
|
||||
test_function
|
||||
|
|
Loading…
Reference in a new issue