Exemplo n.º 1
0
/// Appends a character to the end of the line that the output cursor is on. This function
/// automatically handles linebreaks and lines longer than the screen width.
static void s_desired_append_char(screen_t *s, wchar_t b, highlight_spec_t c, int indent,
                                  size_t prompt_width) {
    int line_no = s->desired.cursor.y;

    if (b == L'\n') {
        // Current line is definitely hard wrapped.
        s->desired.create_line(s->desired.line_count());
        s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
        s->desired.cursor.y++;
        s->desired.cursor.x = 0;
        for (size_t i = 0; i < prompt_width + indent * INDENT_STEP; i++) {
            s_desired_append_char(s, L' ', highlight_spec_t{}, indent, prompt_width);
        }
    } else if (b == L'\r') {
        line_t &current = s->desired.line(line_no);
        current.clear();
        s->desired.cursor.x = 0;
    } else {
        int screen_width = common_get_width();
        int cw = fish_wcwidth_min_0(b);

        s->desired.create_line(line_no);

        // Check if we are at the end of the line. If so, continue on the next line.
        if ((s->desired.cursor.x + cw) > screen_width) {
            // Current line is soft wrapped (assuming we support it).
            s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
            // std::fwprintf(stderr, L"\n\n1 Soft wrapping %d\n\n", s->desired.cursor.y);

            line_no = (int)s->desired.line_count();
            s->desired.add_line();
            s->desired.cursor.y++;
            s->desired.cursor.x = 0;
        }

        line_t &line = s->desired.line(line_no);
        line.append(b, c);
        s->desired.cursor.x += cw;

        // Maybe wrap the cursor to the next line, even if the line itself did not wrap. This
        // avoids wonkiness in the last column.
        if (s->desired.cursor.x >= screen_width) {
            line.is_soft_wrapped = true;
            s->desired.cursor.x = 0;
            s->desired.cursor.y++;
        }
    }
}
Exemplo n.º 2
0
void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_prompt,
             const wcstring &commandline, size_t explicit_len,
             const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
             size_t cursor_pos, const page_rendering_t &pager, bool cursor_is_within_pager) {
    screen_data_t::cursor_t cursor_arr;

    // Turn the command line into the explicit portion and the autosuggestion.
    const wcstring explicit_command_line = commandline.substr(0, explicit_len);
    const wcstring autosuggestion = commandline.substr(explicit_len);

    // If we are using a dumb terminal, don't try any fancy stuff, just print out the text.
    // right_prompt not supported.
    if (is_dumb()) {
        const std::string prompt_narrow = wcs2string(left_prompt);
        const std::string command_line_narrow = wcs2string(explicit_command_line);

        write_loop(STDOUT_FILENO, "\r", 1);
        write_loop(STDOUT_FILENO, prompt_narrow.c_str(), prompt_narrow.size());
        write_loop(STDOUT_FILENO, command_line_narrow.c_str(), command_line_narrow.size());

        return;
    }

    s_check_status(s);
    const size_t screen_width = common_get_width();

    // Completely ignore impossibly small screens.
    if (screen_width < 4) {
        return;
    }

    // Compute a layout.
    const screen_layout_t layout = compute_layout(s, screen_width, left_prompt, right_prompt,
                                                  explicit_command_line, autosuggestion, indent);

    // Determine whether, if we have an autosuggestion, it was truncated.
    s->autosuggestion_is_truncated =
        !autosuggestion.empty() && autosuggestion != layout.autosuggestion;

    // Clear the desired screen.
    s->desired.resize(0);
    s->desired.cursor.x = s->desired.cursor.y = 0;

    // Append spaces for the left prompt.
    for (size_t i = 0; i < layout.left_prompt_space; i++) {
        s_desired_append_char(s, L' ', highlight_spec_t{}, 0, layout.left_prompt_space);
    }

    // If overflowing, give the prompt its own line to improve the situation.
    size_t first_line_prompt_space = layout.left_prompt_space;
    if (layout.prompts_get_own_line) {
        s_desired_append_char(s, L'\n', highlight_spec_t{}, 0, 0);
        first_line_prompt_space = 0;
    }

    // Reconstruct the command line.
    wcstring effective_commandline = explicit_command_line + layout.autosuggestion;

    // Output the command line.
    size_t i;
    for (i = 0; i < effective_commandline.size(); i++) {
        // Grab the current cursor's x,y position if this character matches the cursor's offset.
        if (!cursor_is_within_pager && i == cursor_pos) {
            cursor_arr = s->desired.cursor;
        }
        s_desired_append_char(s, effective_commandline.at(i), colors[i], indent[i],
                              first_line_prompt_space);
    }

    // Cursor may have been at the end too.
    if (!cursor_is_within_pager && i == cursor_pos) {
        cursor_arr = s->desired.cursor;
    }

    // Now that we've output everything, set the cursor to the position that we saved in the loop
    // above.
    s->desired.cursor = cursor_arr;

    if (cursor_is_within_pager) {
        s->desired.cursor.x = (int)cursor_pos;
        s->desired.cursor.y = (int)s->desired.line_count();
    }

    // Append pager_data (none if empty).
    s->desired.append_lines(pager.screen_data);

    s_update(s, layout.left_prompt, layout.right_prompt);
    s_save_status(s);
}
Exemplo n.º 3
0
void s_write( screen_t *s,
	      const wchar_t *prompt,
	      const wchar_t *commandline, 
	      size_t explicit_len,
	      const int *c, 
	      const int *indent,
	      size_t cursor_pos )
{
	screen_data_t::cursor_t cursor_arr;

	size_t prompt_width;
	size_t screen_width;

	int current_line_width = 0, newline_count = 0, explicit_portion_width = 0;
    size_t max_line_width = 0;
	
	CHECK( s, );
	CHECK( prompt, );
	CHECK( commandline, );
	CHECK( c, );
	CHECK( indent, );

	/*
	  If we are using a dumb terminal, don't try any fancy stuff,
	  just print out the text.
	 */
	if( is_dumb() )
	{
		char *prompt_narrow = wcs2str( prompt );
		char *buffer_narrow = wcs2str( commandline );
		
		write_loop( 1, "\r", 1 );
		write_loop( 1, prompt_narrow, strlen( prompt_narrow ) );
		write_loop( 1, buffer_narrow, strlen( buffer_narrow ) );

		free( prompt_narrow );
		free( buffer_narrow );
		
		return;
	}
	
	prompt_width = calc_prompt_width( prompt );
	screen_width = common_get_width();

	s_check_status( s );

	/*
	  Ignore prompts wider than the screen - only print a two
	  character placeholder...

	  It would be cool to truncate the prompt, but because it can
	  contain escape sequences, this is harder than you'd think.
	*/
	if( prompt_width >= screen_width )
	{
		prompt = L"> ";
		prompt_width = 2;
	}
	
	/*
	  Completely ignore impossibly small screens
	*/
	if( screen_width < 4 )
	{
		return;
	}

	/*
	  Check if we are overflowing
	 */
    size_t last_char_that_fits = 0;
	for( size_t i=0; commandline[i]; i++ )
	{
		if( commandline[i] == L'\n' )
		{
			if( current_line_width > max_line_width )
				max_line_width = current_line_width;
			current_line_width = indent[i]*INDENT_STEP;
            newline_count++;
		}
		else
		{
            int width = fish_wcwidth(commandline[i]);
			current_line_width += width;
            if (i < explicit_len)
                explicit_portion_width += width;
                
            if (prompt_width + current_line_width < screen_width)
                last_char_that_fits = i;
		}
	}
	if( current_line_width > max_line_width )
		max_line_width = current_line_width;

    s->desired.resize(0);
	s->desired.cursor.x = s->desired.cursor.y = 0;
    
    /* If we cannot fit with the autosuggestion, but we can fit without it, truncate the autosuggestion. We limit this check to just one line to avoid confusion; not sure how well this would work with multiple lines */
    wcstring truncated_autosuggestion_line;
    if (newline_count == 0 && prompt_width + max_line_width >= screen_width && prompt_width + explicit_portion_width < screen_width)
    {
        assert(screen_width - prompt_width >= 1);
        max_line_width = screen_width - prompt_width - 1;
        truncated_autosuggestion_line = wcstring(commandline, 0, last_char_that_fits);
        commandline = truncated_autosuggestion_line.c_str();
    }
	for( size_t i=0; i<prompt_width; i++ )
	{
		s_desired_append_char( s, L' ', 0, 0, prompt_width );
	}

	/*
	  If overflowing, give the prompt its own line to improve the
	  situation.
	 */
	if( max_line_width + prompt_width >= screen_width )
	{
		s_desired_append_char( s, L'\n', 0, 0, 0 );
		prompt_width=0;
	}
	
    size_t i;
	for( i=0; commandline[i]; i++ )
	{
		int col = c[i];
		
		if( i == cursor_pos )
		{
			col = 0;
		}
		
		if( i == cursor_pos )
		{
            cursor_arr = s->desired.cursor;
		}
		
		s_desired_append_char( s, commandline[i], col, indent[i], prompt_width );
		
	}
	if( i == cursor_pos )
	{
        cursor_arr = s->desired.cursor;
	}
	
    s->desired.cursor = cursor_arr;
	s_update( s, prompt );
	s_save_status( s );
}
Exemplo n.º 4
0
/**
   Appends a character to the end of the line that the output cursor is
   on. This function automatically handles linebreaks and lines longer
   than the screen width. 
*/
static void s_desired_append_char( screen_t *s,
                                  wchar_t b,
                                  int c,
                                  int indent,
                                  size_t prompt_width )
{
	int line_no = s->desired.cursor.y;
	
	switch( b )
	{
		case L'\n':
		{
			int i;
            s->desired.create_line(s->desired.line_count());
			s->desired.cursor.y++;
			s->desired.cursor.x=0;
			for( i=0; i < prompt_width+indent*INDENT_STEP; i++ )
			{
				s_desired_append_char( s, L' ', 0, indent, prompt_width );
			}
			break;
		}
            
		case L'\r':
		{
            line_t &current = s->desired.line(line_no);
            current.clear();
            s->desired.cursor.x = 0;
			break;
		}
            
		default:
		{
			int screen_width = common_get_width();
			int cw = fish_wcwidth(b);
			
            s->desired.create_line(line_no);
            
			/*
             Check if we are at the end of the line. If so, continue on the next line.
             */
			if( (s->desired.cursor.x + cw) > screen_width )
			{
                line_no = (int)s->desired.line_count();
                s->desired.add_line();
				s->desired.cursor.y++;
				s->desired.cursor.x=0;
                for( size_t i=0; i < prompt_width; i++ )
                {
                    s_desired_append_char( s, L' ', 0, indent, prompt_width );
                }
			}
			
            line_t &line = s->desired.line(line_no);
            line.append(b, c);
			s->desired.cursor.x+= cw;
			break;
		}
	}
	
}
Exemplo n.º 5
0
/**
   Appends a character to the end of the line that the output cursor is
   on. This function automatically handles linebreaks and lines longer
   than the screen width.
*/
static void s_desired_append_char(screen_t *s,
                                  wchar_t b,
                                  int c,
                                  int indent,
                                  size_t prompt_width)
{
    int line_no = s->desired.cursor.y;

    switch (b)
    {
        case L'\n':
        {
            int i;
            /* Current line is definitely hard wrapped */
            s->desired.create_line(s->desired.line_count());
            s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
            s->desired.cursor.y++;
            s->desired.cursor.x=0;
            for (i=0; i < prompt_width+indent*INDENT_STEP; i++)
            {
                s_desired_append_char(s, L' ', 0, indent, prompt_width);
            }
            break;
        }

        case L'\r':
        {
            line_t &current = s->desired.line(line_no);
            current.clear();
            s->desired.cursor.x = 0;
            break;
        }

        default:
        {
            int screen_width = common_get_width();
            int cw = fish_wcwidth_min_0(b);

            s->desired.create_line(line_no);

            /*
                   Check if we are at the end of the line. If so, continue on the next line.
                   */
            if ((s->desired.cursor.x + cw) > screen_width)
            {
                /* Current line is soft wrapped (assuming we support it) */
                s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
                //fprintf(stderr, "\n\n1 Soft wrapping %d\n\n", s->desired.cursor.y);

                line_no = (int)s->desired.line_count();
                s->desired.add_line();
                s->desired.cursor.y++;
                s->desired.cursor.x=0;
                for (size_t i=0; i < prompt_width; i++)
                {
                    s_desired_append_char(s, L' ', 0, indent, prompt_width);
                }
            }

            line_t &line = s->desired.line(line_no);
            line.append(b, c);
            s->desired.cursor.x+= cw;

            /* Maybe wrap the cursor to the next line, even if the line itself did not wrap. This avoids wonkiness in the last column. */
            if (s->desired.cursor.x >= screen_width)
            {
                line.is_soft_wrapped = true;
                s->desired.cursor.x = 0;
                s->desired.cursor.y++;
            }
            break;
        }
    }

}
Exemplo n.º 6
0
void s_write(screen_t *s,
             const wcstring &left_prompt,
             const wcstring &right_prompt,
             const wcstring &commandline,
             size_t explicit_len,
             const int *colors,
             const int *indent,
             size_t cursor_pos)
{
    screen_data_t::cursor_t cursor_arr;

    CHECK(s,);
    CHECK(indent,);

    /* Turn the command line into the explicit portion and the autosuggestion */
    const wcstring explicit_command_line = commandline.substr(0, explicit_len);
    const wcstring autosuggestion = commandline.substr(explicit_len);

    /*
      If we are using a dumb terminal, don't try any fancy stuff,
      just print out the text. right_prompt not supported.
     */
    if (is_dumb())
    {
        const std::string prompt_narrow = wcs2string(left_prompt);
        const std::string command_line_narrow = wcs2string(explicit_command_line);

        write_loop(STDOUT_FILENO, "\r", 1);
        write_loop(STDOUT_FILENO, prompt_narrow.c_str(), prompt_narrow.size());
        write_loop(STDOUT_FILENO, command_line_narrow.c_str(), command_line_narrow.size());

        return;
    }

    s_check_status(s);
    const size_t screen_width = common_get_width();

    /* Completely ignore impossibly small screens */
    if (screen_width < 4)
    {
        return;
    }

    /* Compute a layout */
    const screen_layout_t layout = compute_layout(s, screen_width, left_prompt, right_prompt, explicit_command_line, autosuggestion, indent);

    /* Determine whether, if we have an autosuggestion, it was truncated */
    s->autosuggestion_is_truncated = ! autosuggestion.empty() && autosuggestion != layout.autosuggestion;

    /* Clear the desired screen */
    s->desired.resize(0);
    s->desired.cursor.x = s->desired.cursor.y = 0;

    /* Append spaces for the left prompt */
    for (size_t i=0; i < layout.left_prompt_space; i++)
    {
        s_desired_append_char(s, L' ', 0, 0, layout.left_prompt_space);
    }

    /* If overflowing, give the prompt its own line to improve the situation. */
    size_t first_line_prompt_space = layout.left_prompt_space;
    if (layout.prompts_get_own_line)
    {
        s_desired_append_char(s, L'\n', 0, 0, 0);
        first_line_prompt_space = 0;
    }

    /* Reconstruct the command line */
    wcstring effective_commandline = explicit_command_line + layout.autosuggestion;

    /* Output the command line */
    size_t i;
    for (i=0; i < effective_commandline.size(); i++)
    {
        int color = colors[i];

        if (i == cursor_pos)
        {
            color = 0;
        }

        if (i == cursor_pos)
        {
            cursor_arr = s->desired.cursor;
        }

        s_desired_append_char(s, effective_commandline.at(i), color, indent[i], first_line_prompt_space);
    }
    if (i == cursor_pos)
    {
        cursor_arr = s->desired.cursor;
    }

    s->desired.cursor = cursor_arr;
    s_update(s, layout.left_prompt.c_str(), layout.right_prompt.c_str());
    s_save_status(s);
}