Пример #1
0
/**
   Returns a description for the specified function
*/
static const wchar_t *complete_function_desc( const wchar_t *fn )
{
	const wchar_t *res = function_get_desc( fn );

	if( !res )
		res = function_get_definition( fn );

	return res;
}
Пример #2
0
static int report_function_metadata(const wchar_t *funcname, bool verbose, io_streams_t &streams,
                                    bool metadata_as_comments) {
    const wchar_t *path = L"n/a";
    const wchar_t *autoloaded = L"n/a";
    const wchar_t *shadows_scope = L"n/a";
    wcstring description = L"n/a";
    int line_number = 0;

    if (function_exists(funcname)) {
        auto props = function_get_properties(funcname);
        path = function_get_definition_file(funcname);
        if (path) {
            autoloaded = function_is_autoloaded(funcname) ? L"autoloaded" : L"not-autoloaded";
            line_number = function_get_definition_lineno(funcname);
        } else {
            path = L"stdin";
        }
        shadows_scope = props->shadow_scope ? L"scope-shadowing" : L"no-scope-shadowing";
        function_get_desc(funcname, description);
        description = escape_string(description, ESCAPE_NO_QUOTED);
    }

    if (metadata_as_comments) {
        if (std::wcscmp(path, L"stdin")) {
            streams.out.append_format(L"# Defined in %ls @ line %d\n", path, line_number);
        }
    } else {
        streams.out.append_format(L"%ls\n", path);
        if (verbose) {
            streams.out.append_format(L"%ls\n", autoloaded);
            streams.out.append_format(L"%d\n", line_number);
            streams.out.append_format(L"%ls\n", shadows_scope);
            streams.out.append_format(L"%ls\n", description.c_str());
        }
    }

    return STATUS_CMD_OK;
}
Пример #3
0
/// Return a definition of the specified function. Used by the functions builtin.
static wcstring functions_def(const wcstring &name) {
    CHECK(!name.empty(), L"");  //!OCLINT(multiple unary operator)
    wcstring out;
    wcstring desc, def;
    function_get_desc(name, desc);
    function_get_definition(name, def);
    std::vector<std::shared_ptr<event_handler_t>> ev = event_get_function_handlers(name);

    out.append(L"function ");

    // Typically we prefer to specify the function name first, e.g. "function foo --description bar"
    // But If the function name starts with a -, we'll need to output it after all the options.
    bool defer_function_name = (name.at(0) == L'-');
    if (!defer_function_name) {
        out.append(escape_string(name, true));
    }

    if (!desc.empty()) {
        wcstring esc_desc = escape_string(desc, true);
        out.append(L" --description ");
        out.append(esc_desc);
    }

    auto props = function_get_properties(name);
    assert(props && "Should have function properties");
    if (!props->shadow_scope) {
        out.append(L" --no-scope-shadowing");
    }

    for (const auto &next : ev) {
        const event_description_t &d = next->desc;
        switch (d.type) {
            case event_type_t::signal: {
                append_format(out, L" --on-signal %ls", sig2wcs(d.param1.signal));
                break;
            }
            case event_type_t::variable: {
                append_format(out, L" --on-variable %ls", d.str_param1.c_str());
                break;
            }
            case event_type_t::exit: {
                if (d.param1.pid > 0)
                    append_format(out, L" --on-process-exit %d", d.param1.pid);
                else
                    append_format(out, L" --on-job-exit %d", -d.param1.pid);
                break;
            }
            case event_type_t::job_exit: {
                const job_t *j = job_t::from_job_id(d.param1.job_id);
                if (j) append_format(out, L" --on-job-exit %d", j->pgid);
                break;
            }
            case event_type_t::generic: {
                append_format(out, L" --on-event %ls", d.str_param1.c_str());
                break;
            }
            case event_type_t::any:
            default: {
                DIE("unexpected next->type");
                break;
            }
        }
    }

    const wcstring_list_t &named = props->named_arguments;
    if (!named.empty()) {
        append_format(out, L" --argument");
        for (const auto &name : named) {
            append_format(out, L" %ls", name.c_str());
        }
    }

    // Output the function name if we deferred it.
    if (defer_function_name) {
        out.append(L" -- ");
        out.append(escape_string(name, true));
    }

    // Output any inherited variables as `set -l` lines.
    std::map<wcstring, env_var_t> inherit_vars = function_get_inherit_vars(name);
    for (const auto &kv : inherit_vars) {
        wcstring_list_t lst;
        kv.second.to_list(lst);

        // This forced tab is crummy, but we don't know what indentation style the function uses.
        append_format(out, L"\n\tset -l %ls", kv.first.c_str());
        for (const auto &arg : lst) {
            wcstring earg = escape_string(arg, ESCAPE_ALL);
            out.push_back(L' ');
            out.append(earg);
        }
    }

    // This forced tab is sort of crummy - not all functions start with a tab.
    append_format(out, L"\n\t%ls", def.c_str());

    // Append a newline before the 'end', unless there already is one there.
    if (!string_suffixes_string(L"\n", def)) {
        out.push_back(L'\n');
    }
    out.append(L"end\n");
    return out;
}