Example #1
0
wcstring parser_t::current_line()
{
    if (execution_contexts.empty())
    {
        return wcstring();
    }
    const parse_execution_context_t *context = execution_contexts.back();
    assert(context != NULL);

    int source_offset = context->get_current_source_offset();
    if (source_offset < 0)
    {
        return wcstring();
    }

    const int lineno = this->get_lineno();
    const wchar_t *file = this->current_filename();

    wcstring prefix;

    /* If we are not going to print a stack trace, at least print the line number and filename */
    if (!get_is_interactive() || is_function())
    {
        if (file)
        {
            append_format(prefix, _(L"%ls (line %d): "), user_presentable_path(file).c_str(), lineno);
        }
        else if (is_within_fish_initialization)
        {
            append_format(prefix, L"%ls: ", _(L"Startup"), lineno);
        }
        else
        {
            append_format(prefix, L"%ls: ", _(L"Standard input"), lineno);
        }
    }

    bool is_interactive = get_is_interactive();
    bool skip_caret = is_interactive && ! is_function();

    /* Use an error with empty text */
    assert(source_offset >= 0);
    parse_error_t empty_error = {};
    empty_error.source_start = source_offset;

    wcstring line_info = empty_error.describe_with_prefix(context->get_source(), prefix, is_interactive, skip_caret);
    if (! line_info.empty())
    {
        line_info.push_back(L'\n');
    }

    line_info.append(this->stack_trace());
    return line_info;
}
Example #2
0
void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &errors, wcstring *output) const
{
    assert(output != NULL);
    if (! errors.empty())
    {
        const parse_error_t &err = errors.at(0);

        const bool is_interactive = get_is_interactive();

        // Determine if we want to try to print a caret to point at the source error
        // The err.source_start <= src.size() check is due to the nasty way that slices work,
        // which is by rewriting the source (!)
        size_t which_line = 0;
        bool skip_caret = true;
        if (err.source_start != SOURCE_LOCATION_UNKNOWN && err.source_start <= src.size())
        {
            // Determine which line we're on
            which_line = 1 + std::count(src.begin(), src.begin() + err.source_start, L'\n');

            // Don't include the caret if we're interactive, this is the first line of text, and our source is at its beginning, because then it's obvious
            skip_caret = (is_interactive && which_line == 1 && err.source_start == 0);
        }

        wcstring prefix;
        const wchar_t *filename = this->current_filename();
        if (filename)
        {
            if (which_line > 0)
            {
                prefix = format_string(_(L"%ls (line %lu): "), user_presentable_path(filename).c_str(), which_line);
            }
            else
            {
                prefix = format_string(_(L"%ls: "), user_presentable_path(filename).c_str());
            }
        }
        else
        {
            prefix = L"fish: ";
        }

        const wcstring description = err.describe_with_prefix(src, prefix, is_interactive, skip_caret);
        if (! description.empty())
        {
            output->append(description);
            output->push_back(L'\n');
        }
        output->append(this->stack_trace());
    }
}
Example #3
0
/**
  Properly sets all locale information
*/
static void handle_locale()
{
    const env_var_t lc_all = env_get_string(L"LC_ALL");
    const wcstring old_locale = wsetlocale(LC_MESSAGES, NULL);

    /*
      Array of locale constants corresponding to the local variable names defined in locale_variable
    */
    static const int cat[] =
    {
        0,
        LC_ALL,
        LC_COLLATE,
        LC_CTYPE,
        LC_MESSAGES,
        LC_MONETARY,
        LC_NUMERIC,
        LC_TIME
    }
    ;

    if (!lc_all.missing())
    {
        wsetlocale(LC_ALL, lc_all.c_str());
    }
    else
    {
        const env_var_t lang = env_get_string(L"LANG");
        if (!lang.missing())
        {
            wsetlocale(LC_ALL, lang.c_str());
        }

        for (int i=2; locale_variable[i]; i++)
        {
            const env_var_t val = env_get_string(locale_variable[i]);

            if (!val.missing())
            {
                wsetlocale(cat[i], val.c_str());
            }
        }
    }

    const wcstring new_locale = wsetlocale(LC_MESSAGES, NULL);
    if (old_locale != new_locale)
    {

        /*
           Try to make change known to gettext. Both changing
           _nl_msg_cat_cntr and calling dcgettext might potentially
           tell some gettext implementation that the translation
           strings should be reloaded. We do both and hope for the
           best.
        */

        extern int _nl_msg_cat_cntr;
        _nl_msg_cat_cntr++;

        fish_dcgettext("fish", "Changing language to English", LC_MESSAGES);

        if (get_is_interactive())
        {
            debug(2, _(L"Changing language to English"));
        }
    }
}