diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pacman/sync.c | 3 | ||||
| -rw-r--r-- | src/pacman/util.c | 108 | ||||
| -rw-r--r-- | src/pacman/util.h | 1 | 
3 files changed, 110 insertions, 2 deletions
diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 63e5766e..1e622d37 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -636,9 +636,8 @@ static int process_group(alpm_list_t *dbs, char *group)  	printf(_(":: There are %d members in group %s:\n"), count,  			group);  	select_display(pkgs); -	select_question(count);  	char *array = malloc(count); -	memset(array, 1, count); +	multiselect_question(array, count);  	int n = 0;  	for(i = pkgs; i; i = alpm_list_next(i)) {  		if(array[n++] == 0) diff --git a/src/pacman/util.c b/src/pacman/util.c index 133dccc2..51abbf4d 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -694,6 +694,114 @@ void select_display(const alpm_list_t *pkglist)  	FREELIST(list);  } +static int parseindex(char *s, int *val, int min, int max) +{ +	char *endptr = NULL; +	int n = strtol(s, &endptr, 10); +	if(*endptr == '\0') { +		if(n < min || n > max) { +			fprintf(stderr, _("Invalid value: %d is not between %d and %d\n"), +					n, min, max); +			return(-1); +		} +		*val = n; +		return(0); +	} else { +		fprintf(stderr, _("Invalid number: %s\n"), s); +		return(-1); +	} +} + +static int multiselect_parse(char *array, int count, char *response) +{ +	char *str, *saveptr; + +	for (str = response; ; str = NULL) { +		int include = 1; +		int start, end; +		char *ends = NULL; +		char *starts = strtok_r(str, " ", &saveptr); + +		if (starts == NULL) +			break; +		strtrim(starts); +		int len = strlen(starts); +		if(len == 0) +			continue; + +		if (*starts == '^') { +			starts++; +			len--; +			include = 0; +		} else if(str) { +			/* if first token is including, we unselect all targets */ +			memset(array, 0, count); +		} + +		if(len > 1) { +			/* check for range */ +			char *p; +			if((p = strchr(starts+1, '-'))) { +				*p = 0; +				ends = p+1; +			} +		} + +		if(parseindex(starts, &start, 1, count) != 0) +			return(-1); + +		if(!ends) { +			array[start-1] = include; +		} else { +			if(parseindex(ends, &end, start, count) != 0) +				return(-1); +			for(int d = start; d <= end; d++) { +				array[d-1] = include; +			} +		} +	} + +	return(0); +} + +int multiselect_question(char *array, int count) +{ +	char response[64]; +	FILE *stream; + +	if(config->noconfirm) { +		stream = stdout; +	} else { +		/* Use stderr so questions are always displayed when redirecting output */ +		stream = stderr; +	} + +	while(1) { +		memset(array, 1, count); + +		fprintf(stream, "\n"); +		fprintf(stream, _("Enter a selection (default=all)")); +		fprintf(stream,	": "); + +		if(config->noconfirm) { +			fprintf(stream, "\n"); +			break; +		} + +		if(fgets(response, sizeof(response), stdin)) { +			strtrim(response); +			if(strlen(response) > 0) { +				if(multiselect_parse(array, count, response) == -1) { +					/* only loop if user gave an invalid answer */ +					continue; +				} +			} +		} +		break; +	} +	return(0); +} +  int select_question(int count)  {  	char response[32]; diff --git a/src/pacman/util.h b/src/pacman/util.h index 399f9bc8..234a631d 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -61,6 +61,7 @@ void display_optdepends(pmpkg_t *pkg);  void print_packages(const alpm_list_t *packages);  void select_display(const alpm_list_t *pkglist);  int select_question(int count); +int multiselect_question(char *array, int count);  int yesno(char *fmt, ...);  int noyes(char *fmt, ...);  int pm_printf(pmloglevel_t level, const char *format, ...) __attribute__((format(printf,2,3)));  | 
