summarylogtreecommitdiffstats
path: root/0001-Make-progress-bar-characters-customizable.patch
blob: 32cb5215f078e284e084c458b1d8f20d9c567cb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
From 0875fd42889e88ddcfe410e5646c1e203e4b5578 Mon Sep 17 00:00:00 2001
From: Jan Bidler <janbidler00@protonmail.com>
Date: Tue, 29 Nov 2022 20:12:30 +0100
Subject: [PATCH] Make progress bar characters customizable

Backported to 6.0.2 instead of master
---
 src/pacman/callback.c | 55 +++++++++++++++++-----------------
 src/pacman/conf.c     | 68 +++++++++++++++++++++++++++++++++++++++++++
 src/pacman/conf.h     |  5 ++++
 3 files changed, 102 insertions(+), 26 deletions(-)

diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 75c74f8b..198177e4 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -153,17 +153,18 @@ static int64_t get_update_timediff(int first_call)
 static void fill_progress(const int bar_percent, const int disp_percent,
 		const int proglen)
 {
+	const size_t char_done_len = config->progress_char_done ? strlen(config->progress_char_done) : 1;
+	// Current falls back to missing if it does not exist
+	const size_t char_curr_len = config->progress_char_current ? strlen(config->progress_char_current) : (config->progress_char_missing ? strlen(config->progress_char_missing) : 1);
+	const size_t char_miss_len = config->progress_char_missing ? strlen(config->progress_char_missing) : 1;
+	/* gets the smallest bytes from the 3 lengths above */
+	const size_t smallest_char_bytes = char_done_len < char_curr_len ? (char_done_len < char_miss_len ? char_done_len : char_miss_len) : char_curr_len;
+	const size_t char_width = config->progress_char_width ? config->progress_char_width : smallest_char_bytes;
 	/* 8 = 1 space + 1 [ + 1 ] + 5 for percent */
-	const int hashlen = proglen > 8 ? proglen - 8 : 0;
+	const int hashlen = proglen > 8 ? (proglen - 8) / char_width : 0;
 	const int hash = bar_percent * hashlen / 100;
-	static int lasthash = 0, mouth = 0;
 	int i;
 
-	if(bar_percent == 0) {
-		lasthash = 0;
-		mouth = 0;
-	}
-
 	if(hashlen > 0) {
 		fputs(" [", stdout);
 		for(i = hashlen; i > 0; --i) {
@@ -172,31 +173,33 @@ static void fill_progress(const int bar_percent, const int disp_percent,
 				if(i > hashlen - hash) {
 					putchar('-');
 				} else if(i == hashlen - hash) {
-					if(lasthash == hash) {
-						if(mouth) {
-							fputs("\033[1;33mC\033[m", stdout);
-						} else {
-							fputs("\033[1;33mc\033[m", stdout);
-						}
+					if(bar_percent % 2 == 0) {
+						fputs("\033[1;33mC\033[m", stdout);
 					} else {
-						lasthash = hash;
-						mouth = mouth == 1 ? 0 : 1;
-						if(mouth) {
-							fputs("\033[1;33mC\033[m", stdout);
-						} else {
-							fputs("\033[1;33mc\033[m", stdout);
-						}
+						fputs("\033[1;33mc\033[m", stdout);
 					}
 				} else if(i % 3 == 0) {
 					fputs("\033[0;37mo\033[m", stdout);
 				} else {
 					fputs("\033[0;37m \033[m", stdout);
 				}
-			} /* else regular progress bar */
-			else if(i > hashlen - hash) {
-				putchar('#');
-			} else {
-				putchar('-');
+			} /* else regular progress bar (with optional custom characters) */
+			else {
+				if(i > hashlen - hash) {
+					if (config->progress_char_done) {
+						fputs(config->progress_char_done, stdout);
+					} else {
+						putchar('#');
+					}
+				} else if(i == hashlen - hash && config->progress_char_current) {
+					fputs(config->progress_char_current, stdout);
+				} else {
+					if (config->progress_char_missing) {
+						fputs(config->progress_char_missing, stdout);
+					} else {
+						putchar('-');
+					}
+				}
 			}
 		}
 		putchar(']');
@@ -252,7 +255,7 @@ void cb_event(void *ctx, alpm_event_t *event)
 				alpm_event_hook_run_t *e = &event->hook_run;
 				int digits = number_length(e->total);
 				printf("(%*zu/%*zu) %s\n", digits, e->position,
-						digits, e->total, 
+						digits, e->total,
 						e->desc ? e->desc : e->name);
 			}
 			break;
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 12fee64c..dce6e974 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -744,6 +744,74 @@ static int _parse_options(const char *key, char *value,
 			}
 
 			config->parallel_downloads = number;
+		} else if(strcmp(key, "ProgressCharDone") == 0) {
+			size_t length = strlen(value);
+
+			if(length == 0) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: value for '%s' has to be non-empty : '%s'\n"),
+						file, linenum, "ProgressCharDone", value);
+				return 1;
+			}
+
+			config->progress_char_done = strdup(value);
+			/* disable chomp as they're incompatible */
+			config->chomp = 0;
+			pm_printf(ALPM_LOG_DEBUG, "config: progress_char_done: %s\n", value);
+		} else if(strcmp(key, "ProgressCharCurrent") == 0) {
+			size_t length = strlen(value);
+
+			if(length == 0) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: value for '%s' has to be non-empty : '%s'\n"),
+						file, linenum, "ProgressCharDone", value);
+				return 1;
+			}
+			config->progress_char_current = strdup(value);
+			/* disable chomp as they're incompatible */
+			config->chomp = 0;
+			pm_printf(ALPM_LOG_DEBUG, "config: progress_char_current: %s\n", value);
+		} else if(strcmp(key, "ProgressCharMissing") == 0) {
+			size_t length = strlen(value);
+
+			if(length == 0) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: value for '%s' has to be non-empty : '%s'\n"),
+						file, linenum, "ProgressCharMissing", value);
+				return 1;
+			}
+			config->progress_char_missing = strdup(value);
+			/* disable chomp as they're incompatible */
+			config->chomp = 0;
+			pm_printf(ALPM_LOG_DEBUG, "config: progress_char_current: %s\n", value);
+		} else if(strcmp(key, "ProgressCharWidth") == 0) {
+			long number;
+			int err;
+
+			err = parse_number(value, &number);
+			if(err) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: invalid value for '%s' : '%s'\n"),
+						file, linenum, "ProgressCharWidth", value);
+				return 1;
+			}
+
+			/* A value of zero means automatic detection */
+			if(number < 0) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: value for '%s' has to be non-negative : '%s'\n"),
+						file, linenum, "ProgressCharWidth", value);
+				return 1;
+			}
+
+			if(number > INT_MAX) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: value for '%s' is too large : '%s'\n"),
+						file, linenum, "ProgressCharWidth", value);
+				return 1;
+			}
+
+			config->progress_char_width = number;
 		} else {
 			pm_printf(ALPM_LOG_WARNING,
 					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 04350d39..74e1ca2f 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -115,6 +115,11 @@ typedef struct __config_t {
 	unsigned short verbosepkglists;
 	/* number of parallel download streams */
 	unsigned int parallel_downloads;
+	/* custom characters to display on progress bar */
+	char *progress_char_done;
+	char *progress_char_current;
+	char *progress_char_missing;
+	unsigned int progress_char_width;
 	/* select -Sc behavior */
 	unsigned short cleanmethod;
 	alpm_list_t *holdpkg;
-- 
2.38.1