예제 #1
0
/// Replace/append/insert the selection with/at/after the specified string.
///
/// \param begin beginning of selection
/// \param end end of selection
/// \param insert the string to insert
/// \param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the
/// test update is performed
static void replace_part(const wchar_t *begin, const wchar_t *end, const wchar_t *insert,
                         int append_mode) {
    const wchar_t *buff = get_buffer();
    size_t out_pos = get_cursor_pos();

    wcstring out;

    out.append(buff, begin - buff);

    switch (append_mode) {
        case REPLACE_MODE: {
            out.append(insert);
            out_pos = wcslen(insert) + (begin - buff);
            break;
        }
        case APPEND_MODE: {
            out.append(begin, end - begin);
            out.append(insert);
            break;
        }
        case INSERT_MODE: {
            long cursor = get_cursor_pos() - (begin - buff);
            out.append(begin, cursor);
            out.append(insert);
            out.append(begin + cursor, end - begin - cursor);
            out_pos += wcslen(insert);
            break;
        }
    }
    out.append(end);
    reader_set_buffer(out, out_pos);
}
예제 #2
0
/// Replace/append/insert the selection with/at/after the specified string.
///
/// \param begin beginning of selection
/// \param end end of selection
/// \param insert the string to insert
/// \param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the
/// test update is performed
/// \param buff the original command line buffer
/// \param cursor_pos the position of the cursor in the command line
static void replace_part(const wchar_t *begin, const wchar_t *end, const wchar_t *insert,
                         int append_mode, const wchar_t *buff, size_t cursor_pos) {
    size_t out_pos = cursor_pos;

    wcstring out;

    out.append(buff, begin - buff);

    switch (append_mode) {
        case REPLACE_MODE: {
            out.append(insert);
            out_pos = wcslen(insert) + (begin - buff);
            break;
        }
        case APPEND_MODE: {
            out.append(begin, end - begin);
            out.append(insert);
            break;
        }
        case INSERT_MODE: {
            long cursor = cursor_pos - (begin - buff);
            out.append(begin, cursor);
            out.append(insert);
            out.append(begin + cursor, end - begin - cursor);
            out_pos += wcslen(insert);
            break;
        }
        default: {
            DIE("unexpected append_mode");
            break;
        }
    }
    out.append(end);
    reader_set_buffer(out, out_pos);
}
예제 #3
0
/**
   Replace/append/insert the selection with/at/after the specified string.

   \param begin beginning of selection
   \param end end of selection
   \param insert the string to insert
   \param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed
*/
static void replace_part( const wchar_t *begin,
						  const wchar_t *end,
						  wchar_t *insert,
						  int append_mode )
{
	const wchar_t *buff = get_buffer();
	string_buffer_t out;
	int out_pos=get_cursor_pos();

	sb_init( &out );

	sb_append_substring( &out, buff, begin-buff );

	switch( append_mode)
	{
		case REPLACE_MODE:
		{

			sb_append( &out, insert );
			out_pos = wcslen( insert ) + (begin-buff);
			break;

		}
		case APPEND_MODE:
		{
			sb_append_substring( &out, begin, end-begin );
			sb_append( &out, insert );
			break;
		}
		case INSERT_MODE:
		{
			int cursor = get_cursor_pos() -(begin-buff);
			sb_append_substring( &out, begin, cursor );
			sb_append( &out, insert );
			sb_append_substring( &out, begin+cursor, end-begin-cursor );
			out_pos +=  wcslen( insert );
			break;
		}
	}
	sb_append( &out, end );
	reader_set_buffer( (wchar_t *)out.buff, out_pos );
	sb_destroy( &out );
}
예제 #4
0
/**
   The commandline builtin. It is used for specifying a new value for
   the commandline.
*/
static int builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
    wgetopter_t w;
    int buffer_part=0;
    int cut_at_cursor=0;

    int argc = builtin_count_args(argv);
    int append_mode=0;

    int function_mode = 0;
    int selection_mode = 0;

    int tokenize = 0;

    int cursor_mode = 0;
    int line_mode = 0;
    int search_mode = 0;
    int paging_mode = 0;
    const wchar_t *begin = NULL, *end = NULL;
    
    scoped_push<const wchar_t *> saved_current_buffer(&current_buffer);
    scoped_push<size_t> saved_current_cursor_pos(&current_cursor_pos);
    
    wcstring transient_commandline;
    if (get_top_transient(&transient_commandline))
    {
        current_buffer = transient_commandline.c_str();
        current_cursor_pos = transient_commandline.size();
    }
    else
    {
        current_buffer = reader_get_buffer();
        current_cursor_pos = reader_get_cursor_pos();
    }

    if (!get_buffer())
    {
        if (is_interactive_session)
        {
            /*
              Prompt change requested while we don't have
              a prompt, most probably while reading the
              init files. Just ignore it.
            */
            return 1;
        }

        streams.err.append(argv[0]);
        streams.err.append(L": Can not set commandline in non-interactive mode\n");
        builtin_print_help(parser, streams, argv[0], streams.err);
        return 1;
    }

    w.woptind=0;

    while (1)
    {
        static const struct woption
                long_options[] =
        {
            { L"append", no_argument, 0, 'a' },
            { L"insert", no_argument, 0, 'i' },
            { L"replace", no_argument, 0, 'r' },
            { L"current-job", no_argument, 0, 'j' },
            { L"current-process", no_argument, 0, 'p' },
            { L"current-token", no_argument, 0, 't' },
            { L"current-buffer", no_argument, 0, 'b' },
            { L"cut-at-cursor", no_argument, 0, 'c' },
            { L"function", no_argument, 0, 'f' },
            { L"tokenize", no_argument, 0, 'o' },
            { L"help", no_argument, 0, 'h' },
            { L"input", required_argument, 0, 'I' },
            { L"cursor", no_argument, 0, 'C' },
            { L"line", no_argument, 0, 'L' },
            { L"search-mode", no_argument, 0, 'S' },
            { L"selection", no_argument, 0, 's' },
            { L"paging-mode", no_argument, 0, 'P' },
            { 0, 0, 0, 0 }
        };

        int opt_index = 0;

        int opt = w.wgetopt_long(argc,
                                 argv,
                                 L"abijpctwforhI:CLSsP",
                                 long_options,
                                 &opt_index);
        if (opt == -1)
            break;

        switch (opt)
        {
            case 0:
                if (long_options[opt_index].flag != 0)
                    break;
                streams.err.append_format(BUILTIN_ERR_UNKNOWN,
                              argv[0],
                              long_options[opt_index].name);
                builtin_print_help(parser, streams, argv[0], streams.err);

                return 1;

            case L'a':
                append_mode = APPEND_MODE;
                break;

            case L'b':
                buffer_part = STRING_MODE;
                break;


            case L'i':
                append_mode = INSERT_MODE;
                break;

            case L'r':
                append_mode = REPLACE_MODE;
                break;

            case 'c':
                cut_at_cursor=1;
                break;

            case 't':
                buffer_part = TOKEN_MODE;
                break;

            case 'j':
                buffer_part = JOB_MODE;
                break;

            case 'p':
                buffer_part = PROCESS_MODE;
                break;

            case 'f':
                function_mode=1;
                break;

            case 'o':
                tokenize=1;
                break;

            case 'I':
                current_buffer = w.woptarg;
                current_cursor_pos = wcslen(w.woptarg);
                break;

            case 'C':
                cursor_mode = 1;
                break;

            case 'L':
                line_mode = 1;
                break;

            case 'S':
                search_mode = 1;
                break;

            case 's':
                selection_mode = 1;
                break;

            case 'P':
                paging_mode = 1;
                break;

            case 'h':
                builtin_print_help(parser, streams, argv[0], streams.out);
                return 0;

            case L'?':
                builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
                return 1;
        }
    }

    if (function_mode)
    {
        int i;

        /*
          Check for invalid switch combinations
        */
        if (buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode || paging_mode)
        {
            streams.err.append_format(BUILTIN_ERR_COMBO,
                          argv[0]);

            builtin_print_help(parser, streams, argv[0], streams.err);
            return 1;
        }


        if (argc == w.woptind)
        {
            streams.err.append_format(BUILTIN_ERR_MISSING,
                          argv[0]);

            builtin_print_help(parser, streams, argv[0], streams.err);
            return 1;
        }
        for (i=w.woptind; i<argc; i++)
        {
            wchar_t c = input_function_get_code(argv[i]);
            if (c != INPUT_CODE_NONE)
            {
                /*
                  input_unreadch inserts the specified keypress or
                  readline function at the back of the queue of unused
                  keypresses
                */
                input_queue_ch(c);
            }
            else
            {
                streams.err.append_format(_(L"%ls: Unknown input function '%ls'\n"),
                              argv[0],
                              argv[i]);
                builtin_print_help(parser, streams, argv[0], streams.err);
                return 1;
            }
        }

        return 0;
    }

    if (selection_mode)
    {
        size_t start, len;
        const wchar_t *buffer = reader_get_buffer();
        if (reader_get_selection(&start, &len))
        {
            streams.out.append(buffer + start, len);
        }
        return 0;
    }

    /*
      Check for invalid switch combinations
    */
    if ((search_mode || line_mode || cursor_mode || paging_mode) && (argc-w.woptind > 1))
    {

        streams.err.append_format(argv[0],
                      L": Too many arguments\n",
                      NULL);
        builtin_print_help(parser, streams, argv[0], streams.err);
        return 1;
    }

    if ((buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode || paging_mode))
    {
        streams.err.append_format(BUILTIN_ERR_COMBO,
                      argv[0]);

        builtin_print_help(parser, streams, argv[0], streams.err);
        return 1;
    }


    if ((tokenize || cut_at_cursor) && (argc-w.woptind))
    {
        streams.err.append_format(BUILTIN_ERR_COMBO2,
                      argv[0],
                      L"--cut-at-cursor and --tokenize can not be used when setting the commandline");


        builtin_print_help(parser, streams, argv[0], streams.err);
        return 1;
    }

    if (append_mode && !(argc-w.woptind))
    {
        streams.err.append_format(BUILTIN_ERR_COMBO2,
                      argv[0],
                      L"insertion mode switches can not be used when not in insertion mode");

        builtin_print_help(parser, streams, argv[0], streams.err);
        return 1;
    }

    /*
      Set default modes
    */
    if (!append_mode)
    {
        append_mode = REPLACE_MODE;
    }

    if (!buffer_part)
    {
        buffer_part = STRING_MODE;
    }

    if (cursor_mode)
    {
        if (argc-w.woptind)
        {
            wchar_t *endptr;
            long new_pos;
            errno = 0;

            new_pos = wcstol(argv[w.woptind], &endptr, 10);
            if (*endptr || errno)
            {
                streams.err.append_format(BUILTIN_ERR_NOT_NUMBER,
                              argv[0],
                              argv[w.woptind]);
                builtin_print_help(parser, streams, argv[0], streams.err);
            }

            current_buffer = reader_get_buffer();
            new_pos = maxi(0L, mini(new_pos, (long)wcslen(current_buffer)));
            reader_set_buffer(current_buffer, (size_t)new_pos);
            return 0;
        }
        else
        {
            streams.out.append_format( L"%lu\n", (unsigned long)reader_get_cursor_pos());
            return 0;
        }

    }

    if (line_mode)
    {
        size_t pos = reader_get_cursor_pos();
        const wchar_t *buff = reader_get_buffer();
        streams.out.append_format( L"%lu\n", (unsigned long)parse_util_lineno(buff, pos));
        return 0;

    }

    if (search_mode)
    {
        return ! reader_search_mode();
    }

    if (paging_mode)
    {
        return ! reader_has_pager_contents();
    }


    switch (buffer_part)
    {
        case STRING_MODE:
        {
            begin = get_buffer();
            end = begin+wcslen(begin);
            break;
        }

        case PROCESS_MODE:
        {
            parse_util_process_extent(get_buffer(),
                                      get_cursor_pos(),
                                      &begin,
                                      &end);
            break;
        }

        case JOB_MODE:
        {
            parse_util_job_extent(get_buffer(),
                                  get_cursor_pos(),
                                  &begin,
                                  &end);
            break;
        }

        case TOKEN_MODE:
        {
            parse_util_token_extent(get_buffer(),
                                    get_cursor_pos(),
                                    &begin,
                                    &end,
                                    0, 0);
            break;
        }

    }

    switch (argc-w.woptind)
    {
        case 0:
        {
            write_part(begin, end, cut_at_cursor, tokenize, streams);
            break;
        }

        case 1:
        {
            replace_part(begin, end, argv[w.woptind], append_mode);
            break;
        }

        default:
        {
            wcstring sb = argv[w.woptind];
            int i;

            for (i=w.woptind+1; i<argc; i++)
            {
                sb.push_back(L'\n');
                sb.append(argv[i]);
            }

            replace_part(begin, end, sb.c_str(), append_mode);

            break;
        }
    }

    return 0;
}
예제 #5
0
/// The commandline builtin. It is used for specifying a new value for the commandline.
int builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
    // Pointer to what the commandline builtin considers to be the current contents of the command
    // line buffer.
    const wchar_t *current_buffer = 0;

    // What the commandline builtin considers to be the current cursor position.
    size_t current_cursor_pos = (size_t)(-1);

    wchar_t *cmd = argv[0];
    int buffer_part = 0;
    int cut_at_cursor = 0;

    int argc = builtin_count_args(argv);
    int append_mode = 0;

    int function_mode = 0;
    int selection_mode = 0;

    int tokenize = 0;

    int cursor_mode = 0;
    int line_mode = 0;
    int search_mode = 0;
    int paging_mode = 0;
    const wchar_t *begin = NULL, *end = NULL;

    wcstring transient_commandline;
    if (get_top_transient(&transient_commandline)) {
        current_buffer = transient_commandline.c_str();
        current_cursor_pos = transient_commandline.size();
    } else {
        current_buffer = reader_get_buffer();
        current_cursor_pos = reader_get_cursor_pos();
    }

    if (!current_buffer) {
        if (is_interactive_session) {
            // Prompt change requested while we don't have a prompt, most probably while reading the
            // init files. Just ignore it.
            return STATUS_CMD_ERROR;
        }

        streams.err.append(argv[0]);
        streams.err.append(L": Can not set commandline in non-interactive mode\n");
        builtin_print_help(parser, streams, cmd, streams.err);
        return STATUS_CMD_ERROR;
    }

    static const wchar_t *const short_options = L":abijpctwforhI:CLSsP";
    static const struct woption long_options[] = {{L"append", no_argument, NULL, 'a'},
                                                  {L"insert", no_argument, NULL, 'i'},
                                                  {L"replace", no_argument, NULL, 'r'},
                                                  {L"current-buffer", no_argument, NULL, 'b'},
                                                  {L"current-job", no_argument, NULL, 'j'},
                                                  {L"current-process", no_argument, NULL, 'p'},
                                                  {L"current-selection", no_argument, NULL, 's'},
                                                  {L"current-token", no_argument, NULL, 't'},
                                                  {L"cut-at-cursor", no_argument, NULL, 'c'},
                                                  {L"function", no_argument, NULL, 'f'},
                                                  {L"tokenize", no_argument, NULL, 'o'},
                                                  {L"help", no_argument, NULL, 'h'},
                                                  {L"input", required_argument, NULL, 'I'},
                                                  {L"cursor", no_argument, NULL, 'C'},
                                                  {L"line", no_argument, NULL, 'L'},
                                                  {L"search-mode", no_argument, NULL, 'S'},
                                                  {L"paging-mode", no_argument, NULL, 'P'},
                                                  {NULL, 0, NULL, 0}};

    int opt;
    wgetopter_t w;
    while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
        switch (opt) {
            case L'a': {
                append_mode = APPEND_MODE;
                break;
            }
            case L'b': {
                buffer_part = STRING_MODE;
                break;
            }
            case L'i': {
                append_mode = INSERT_MODE;
                break;
            }
            case L'r': {
                append_mode = REPLACE_MODE;
                break;
            }
            case 'c': {
                cut_at_cursor = 1;
                break;
            }
            case 't': {
                buffer_part = TOKEN_MODE;
                break;
            }
            case 'j': {
                buffer_part = JOB_MODE;
                break;
            }
            case 'p': {
                buffer_part = PROCESS_MODE;
                break;
            }
            case 'f': {
                function_mode = 1;
                break;
            }
            case 'o': {
                tokenize = 1;
                break;
            }
            case 'I': {
                current_buffer = w.woptarg;
                current_cursor_pos = wcslen(w.woptarg);
                break;
            }
            case 'C': {
                cursor_mode = 1;
                break;
            }
            case 'L': {
                line_mode = 1;
                break;
            }
            case 'S': {
                search_mode = 1;
                break;
            }
            case 's': {
                selection_mode = 1;
                break;
            }
            case 'P': {
                paging_mode = 1;
                break;
            }
            case 'h': {
                builtin_print_help(parser, streams, cmd, streams.out);
                return STATUS_CMD_OK;
            }
            case ':': {
                builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]);
                return STATUS_INVALID_ARGS;
            }
            case L'?': {
                builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]);
                return STATUS_INVALID_ARGS;
            }
            default: {
                DIE("unexpected retval from wgetopt_long");
                break;
            }
        }
    }

    if (function_mode) {
        int i;

        // Check for invalid switch combinations.
        if (buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode ||
            search_mode || paging_mode) {
            streams.err.append_format(BUILTIN_ERR_COMBO, argv[0]);
            builtin_print_help(parser, streams, cmd, streams.err);
            return STATUS_INVALID_ARGS;
        }

        if (argc == w.woptind) {
            builtin_missing_argument(parser, streams, cmd, argv[0]);
            return STATUS_INVALID_ARGS;
        }

        for (i = w.woptind; i < argc; i++) {
            wchar_t c = input_function_get_code(argv[i]);
            if (c != INPUT_CODE_NONE) {
                // input_unreadch inserts the specified keypress or readline function at the back of
                // the queue of unused keypresses.
                input_queue_ch(c);
            } else {
                streams.err.append_format(_(L"%ls: Unknown input function '%ls'"), cmd, argv[i]);
                builtin_print_help(parser, streams, cmd, streams.err);
                return STATUS_INVALID_ARGS;
            }
        }

        return STATUS_CMD_OK;
    }

    if (selection_mode) {
        size_t start, len;
        const wchar_t *buffer = reader_get_buffer();
        if (reader_get_selection(&start, &len)) {
            streams.out.append(buffer + start, len);
        }
        return STATUS_CMD_OK;
    }

    // Check for invalid switch combinations.
    if ((search_mode || line_mode || cursor_mode || paging_mode) && (argc - w.woptind > 1)) {
        streams.err.append_format(L"%ls: Too many arguments", argv[0]);
        builtin_print_help(parser, streams, cmd, streams.err);
        return STATUS_INVALID_ARGS;
    }

    if ((buffer_part || tokenize || cut_at_cursor) &&
        (cursor_mode || line_mode || search_mode || paging_mode)) {
        streams.err.append_format(BUILTIN_ERR_COMBO, argv[0]);
        builtin_print_help(parser, streams, cmd, streams.err);
        return STATUS_INVALID_ARGS;
    }

    if ((tokenize || cut_at_cursor) && (argc - w.woptind)) {
        streams.err.append_format(
            BUILTIN_ERR_COMBO2, cmd,
            L"--cut-at-cursor and --tokenize can not be used when setting the commandline");
        builtin_print_help(parser, streams, cmd, streams.err);
        return STATUS_INVALID_ARGS;
    }

    if (append_mode && !(argc - w.woptind)) {
        streams.err.append_format(
            BUILTIN_ERR_COMBO2, cmd,
            L"insertion mode switches can not be used when not in insertion mode");
        builtin_print_help(parser, streams, cmd, streams.err);
        return STATUS_INVALID_ARGS;
    }

    // Set default modes.
    if (!append_mode) {
        append_mode = REPLACE_MODE;
    }

    if (!buffer_part) {
        buffer_part = STRING_MODE;
    }

    if (cursor_mode) {
        if (argc - w.woptind) {
            long new_pos = fish_wcstol(argv[w.woptind]);
            if (errno) {
                streams.err.append_format(BUILTIN_ERR_NOT_NUMBER, cmd, argv[w.woptind]);
                builtin_print_help(parser, streams, cmd, streams.err);
            }

            current_buffer = reader_get_buffer();
            new_pos = maxi(0L, mini(new_pos, (long)wcslen(current_buffer)));
            reader_set_buffer(current_buffer, (size_t)new_pos);
        } else {
            streams.out.append_format(L"%lu\n", (unsigned long)reader_get_cursor_pos());
        }
        return STATUS_CMD_OK;
    }

    if (line_mode) {
        size_t pos = reader_get_cursor_pos();
        const wchar_t *buff = reader_get_buffer();
        streams.out.append_format(L"%lu\n", (unsigned long)parse_util_lineno(buff, pos));
        return STATUS_CMD_OK;
    }

    if (search_mode) {
        return reader_is_in_search_mode() ? 0 : 1;
    }

    if (paging_mode) {
        return reader_has_pager_contents() ? 0 : 1;
    }

    switch (buffer_part) {
        case STRING_MODE: {
            begin = current_buffer;
            end = begin + wcslen(begin);
            break;
        }
        case PROCESS_MODE: {
            parse_util_process_extent(current_buffer, current_cursor_pos, &begin, &end);
            break;
        }
        case JOB_MODE: {
            parse_util_job_extent(current_buffer, current_cursor_pos, &begin, &end);
            break;
        }
        case TOKEN_MODE: {
            parse_util_token_extent(current_buffer, current_cursor_pos, &begin, &end, 0, 0);
            break;
        }
        default: {
            DIE("unexpected buffer_part");
            break;
        }
    }

    int arg_count = argc - w.woptind;
    if (arg_count == 0) {
        write_part(begin, end, cut_at_cursor, tokenize, current_buffer, current_cursor_pos,
                   streams);
    } else if (arg_count == 1) {
        replace_part(begin, end, argv[w.woptind], append_mode, current_buffer, current_cursor_pos);
    } else {
        wcstring sb = argv[w.woptind];
        for (int i = w.woptind + 1; i < argc; i++) {
            sb.push_back(L'\n');
            sb.append(argv[i]);
        }
        replace_part(begin, end, sb.c_str(), append_mode, current_buffer, current_cursor_pos);
    }

    return STATUS_CMD_OK;
}
예제 #6
0
/**
   The commandline builtin. It is used for specifying a new value for
   the commandline.
*/
static int builtin_commandline( wchar_t **argv )
{

	int buffer_part=0;
	int cut_at_cursor=0;

	int argc = builtin_count_args( argv );
	int append_mode=0;

	int function_mode = 0;

	int tokenize = 0;

	int cursor_mode = 0;
	int line_mode = 0;
	int search_mode = 0;
	wchar_t *begin, *end;

	current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
	if( current_buffer )
	{
		current_cursor_pos = wcslen( current_buffer );
	}
	else
	{
		current_buffer = reader_get_buffer();
		current_cursor_pos = reader_get_cursor_pos();
	}

	if( !get_buffer() )
	{
		if (is_interactive_session)
		{
			/*
			  Prompt change requested while we don't have
			  a prompt, most probably while reading the
			  init files. Just ignore it.
			*/
			return 1;
		}

		sb_append( sb_err,
			    argv[0],
			    L": Can not set commandline in non-interactive mode\n",
			    (void *)0 );
		builtin_print_help( argv[0], sb_err );
		return 1;
	}

	woptind=0;

	while( 1 )
	{
		static const struct woption
			long_options[] =
			{
				{
					L"append", no_argument, 0, 'a'
				}
				,
				{
					L"insert", no_argument, 0, 'i'
				}
				,
				{
					L"replace", no_argument, 0, 'r'
				}
				,
				{
					L"current-job", no_argument, 0, 'j'
				}
				,
				{
					L"current-process", no_argument, 0, 'p'
				}
				,
				{
					L"current-token", no_argument, 0, 't'
				}
				,
				{
					L"current-buffer", no_argument, 0, 'b'
				}
				,
				{
					L"cut-at-cursor", no_argument, 0, 'c'
				}
				,
				{
					L"function", no_argument, 0, 'f'
				}
				,
				{
					L"tokenize", no_argument, 0, 'o'
				}
				,
				{
					L"help", no_argument, 0, 'h'
				}
				,
				{
					L"input", required_argument, 0, 'I'
				}
				,
				{
					L"cursor", no_argument, 0, 'C'
				}
				,
				{
					L"line", no_argument, 0, 'L'
				}
				,
				{
					L"search-mode", no_argument, 0, 'S'
				}
				,
				{
					0, 0, 0, 0
				}
			}
		;

		int opt_index = 0;

		int opt = wgetopt_long( argc,
								argv,
								L"abijpctwforhI:CLS",
								long_options,
								&opt_index );
		if( opt == -1 )
			break;

		switch( opt )
		{
			case 0:
				if(long_options[opt_index].flag != 0)
					break;
                sb_printf( sb_err,
                           BUILTIN_ERR_UNKNOWN,
                           argv[0],
                           long_options[opt_index].name );
				builtin_print_help( argv[0], sb_err );

				return 1;

			case L'a':
				append_mode = APPEND_MODE;
				break;

			case L'b':
				buffer_part = STRING_MODE;
				break;


			case L'i':
				append_mode = INSERT_MODE;
				break;

			case L'r':
				append_mode = REPLACE_MODE;
				break;

			case 'c':
				cut_at_cursor=1;
				break;

			case 't':
				buffer_part = TOKEN_MODE;
				break;

			case 'j':
				buffer_part = JOB_MODE;
				break;

			case 'p':
				buffer_part = PROCESS_MODE;
				break;

			case 'f':
				function_mode=1;
				break;

			case 'o':
				tokenize=1;
				break;

			case 'I':
				current_buffer = woptarg;
				current_cursor_pos = wcslen( woptarg );
				break;

			case 'C':
				cursor_mode = 1;
				break;

			case 'L':
				line_mode = 1;
				break;

			case 'S':
				search_mode = 1;
				break;

			case 'h':
				builtin_print_help( argv[0], sb_out );
				return 0;

			case L'?':
				builtin_unknown_option( argv[0], argv[woptind-1] );
				return 1;
		}
	}

	if( function_mode )
	{
		int i;

		/*
		  Check for invalid switch combinations
		*/
		if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode )
		{
			sb_printf(sb_err,
					  BUILTIN_ERR_COMBO,
					  argv[0] );

			builtin_print_help( argv[0], sb_err );
			return 1;
		}


		if( argc == woptind )
		{
			sb_printf( sb_err,
					   BUILTIN_ERR_MISSING,
					   argv[0] );

			builtin_print_help( argv[0], sb_err );
			return 1;
 		}
		for( i=woptind; i<argc; i++ )
		{
			wint_t c = input_function_get_code( argv[i] );
			if( c != -1 )
			{
				/*
				  input_unreadch inserts the specified keypress or
				  readline function at the top of the stack of unused
				  keypresses
				*/
				input_unreadch(c);
			}
			else
			{
				sb_printf( sb_err,
					   _(L"%ls: Unknown input function '%ls'\n"),
					   argv[0],
					   argv[i] );
				builtin_print_help( argv[0], sb_err );
				return 1;
			}
		}

		return 0;
	}

	/*
	  Check for invalid switch combinations
	*/
	if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) )
	{

		sb_append( sb_err,
					argv[0],
					L": Too many arguments\n",
					(void *)0 );
		builtin_print_help( argv[0], sb_err );
		return 1;
	}

	if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) )
	{
		sb_printf( sb_err,
				   BUILTIN_ERR_COMBO,
				   argv[0] );

		builtin_print_help( argv[0], sb_err );
		return 1;
	}


	if( (tokenize || cut_at_cursor) && (argc-woptind) )
	{
		sb_printf( sb_err,
				   BUILTIN_ERR_COMBO2,
				   argv[0],
				   L"--cut-at-cursor and --tokenize can not be used when setting the commandline" );


		builtin_print_help( argv[0], sb_err );
		return 1;
	}

	if( append_mode && !(argc-woptind) )
	{
		sb_printf( sb_err,
                    BUILTIN_ERR_COMBO2,
                    argv[0],
				   L"insertion mode switches can not be used when not in insertion mode" );

        builtin_print_help( argv[0], sb_err );
        return 1;
	}

	/*
	  Set default modes
	*/
	if( !append_mode )
	{
		append_mode = REPLACE_MODE;
	}

	if( !buffer_part )
	{
		buffer_part = STRING_MODE;
	}

	if( cursor_mode )
	{
		if( argc-woptind )
		{
			wchar_t *endptr;
			int new_pos;
			errno = 0;

			new_pos = wcstol( argv[woptind], &endptr, 10 );
			if( *endptr || errno )
			{
				sb_printf( sb_err,
					   BUILTIN_ERR_NOT_NUMBER,
					   argv[0],
					   argv[woptind] );
				builtin_print_help( argv[0], sb_err );
			}

			current_buffer = reader_get_buffer();
			new_pos = maxi( 0, mini( new_pos, wcslen( current_buffer ) ) );
			reader_set_buffer( current_buffer, new_pos );
			return 0;
		}
		else
		{
			sb_printf( sb_out, L"%d\n", reader_get_cursor_pos() );
			return 0;
		}

	}

	if( line_mode )
	{
		int pos = reader_get_cursor_pos();
		wchar_t *buff = reader_get_buffer();
		sb_printf( sb_out, L"%d\n", parse_util_lineno( buff, pos ) );
		return 0;

	}

	if( search_mode )
	{
		return !reader_search_mode();
	}


	switch( buffer_part )
	{
		case STRING_MODE:
		{
			begin = get_buffer();
			end = begin+wcslen(begin);
			break;
		}

		case PROCESS_MODE:
		{
			parse_util_process_extent( get_buffer(),
									   get_cursor_pos(),
									   &begin,
									   &end );
			break;
		}

		case JOB_MODE:
		{
			parse_util_job_extent( get_buffer(),
								   get_cursor_pos(),
								   &begin,
								   &end );
			break;
		}

		case TOKEN_MODE:
		{
			parse_util_token_extent( get_buffer(),
									 get_cursor_pos(),
									 &begin,
									 &end,
									 0, 0 );
			break;
		}

	}

	switch(argc-woptind)
	{
		case 0:
		{
			write_part( begin, end, cut_at_cursor, tokenize );
			break;
		}

		case 1:
		{
			replace_part( begin, end, argv[woptind], append_mode );
			break;
		}

		default:
		{
			string_buffer_t sb;
			int i;

			sb_init( &sb );

			sb_append( &sb, argv[woptind] );

			for( i=woptind+1; i<argc; i++ )
			{
				sb_append( &sb, L"\n" );
				sb_append( &sb, argv[i] );
			}

			replace_part( begin, end, (wchar_t *)sb.buff, append_mode );
			sb_destroy( &sb );

			break;
		}
	}

	return 0;
}
예제 #7
0
파일: fish_tests.c 프로젝트: CodeMonk/fish
/**
   Test speed of completion calculations
*/
void perf_complete()
{
	wchar_t c;
	array_list_t out;
	long long t1, t2;
	int matches=0;
	double t;
	wchar_t str[3]=
	{
		0, 0, 0 
	}
	;
	int i;
	
	
	say( L"Testing completion performance" );
	al_init( &out );
	
	reader_push(L"");
	say( L"Here we go" );
	 	
	t1 = get_time();
	
	
	for( c=L'a'; c<=L'z'; c++ )
	{
		str[0]=c;
		reader_set_buffer( str, 0 );
		
		complete( str, &out );
	
		matches += al_get_count( &out );
		
		al_foreach( &out, &free );
		al_truncate( &out, 0 );
	}
	t2=get_time();
	
	t = (double)(t2-t1)/(1000000*26);
	
	say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
	
	matches=0;
	t1 = get_time();
	for( i=0; i<LAPS; i++ )
	{
		str[0]='a'+(rand()%26);
		str[1]='a'+(rand()%26);
		
		reader_set_buffer( str, 0 );
		
		complete( str, &out );
	
		matches += al_get_count( &out );
		
		al_foreach( &out, &free );
		al_truncate( &out, 0 );
	}
	t2=get_time();
	
	t = (double)(t2-t1)/(1000000*LAPS);
	
	say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
	
	al_destroy( &out );

	reader_pop();
	
}