brndnmtthws / conky

Light-weight system monitor for X, Wayland (sort of), and other things, too
https://conky.cc
GNU General Public License v3.0
7.16k stars 614 forks source link

Default bar enhancements #503

Closed lasers closed 6 years ago

lasers commented 6 years ago

Greetings. Conky supports the following default_bar options:

default_bar_height
    Specify a default height for bars. If not specified,
    the default value is 6.
default_bar_width
    Specify a default width for bars. If not  specified,
    the  default value is 0, which causes the bar to ex‐
    pand to fit the width of your Conky window.  If  you
    set  out_to_console  = true, the text version of the
    bar will actually have no width and you will need to
    set  a  sensible default or set the height and width
    of each bar individually.

I see that users can't configure strings like default_bar_full (default is #) and default_bar_empty (default is _) preventing users from getting ◼◼◼◼◼◼◼◽◽◽ instead of #######___.

Additionally, I wonder if it is a good idea to support default_bar_header and default_bar_footer too for brackets or such, eg [#######___] but it could be stupid and/or pointless in the long run.

All of this would be for out_to_console=true.

lasers commented 6 years ago

I wonder if it is better to make ${bar ...} instead too.

${bar ${percent} [height] [width] [fill_string] [empty_string]} [min] [max]`

${bar ${volume} 0 10 _ #}  --> _____#####

[${bar ${volume} 0 10 _ #}]  --> [_____#####]

${bar ${volume} 0 10 ◽ ◼}  --> ◼◼◼◼◼◼◼◽◽◽

${bar ${volume} 0 10 ● ○}  --> ○○○○○●●●●●

Colors?

${bar ${volume} 0 10 "${color red}●" "${color green}○"}  --> ○○○○○●●●●●

Remove code issues and inconsistencies around bar variables. Any percent should be okay here.

What about percents that goes beyond 100%, eg volume 120%?

lasers commented 6 years ago

Similar suggestion https://github.com/brndnmtthws/conky/issues/246#issuecomment-244614837

lasers commented 6 years ago

@su8 Work on something else? default_bar_fill and default_bar_unfill or default_bar_full and default_bar_empty?

diff --git a/src/specials.cc b/src/specials.cc
index bb19b13e..3ed4b4df 100644
--- a/src/specials.cc
+++ b/src/specials.cc
@@ -697,11 +697,11 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,
   scaledusage = round_to_int(usage * width / b->scale);

   for (i = 0; i < scaledusage; i++) {
-    buffer[i] = '#';
+    buffer[i] = '#';  /* fill */
   }

   for (; i < width; i++) {
-    buffer[i] = '_';
+    buffer[i] = '_';  /* unfill */
   }

   buffer[i] = 0;
su8 commented 6 years ago

Not sure if you want this:

diff --git a/src/core.cc b/src/core.cc
index 7a438b2e..b4125122 100644
--- a/src/core.cc
+++ b/src/core.cc
@@ -836,6 +836,9 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
   END OBJ(password, 0) obj->data.s = STRNDUP_ARG;
   obj->callbacks.print = &print_password;
   obj->callbacks.free = &gen_free_opaque;
+  END OBJ(bar, 0) obj->data.s = STRNDUP_ARG;
+  obj->callbacks.print = &print_bar;
+  obj->callbacks.free = &gen_free_opaque;

 #ifdef __x86_64__
   END OBJ(freq2, 0) obj->callbacks.print = &print_freq2;
diff --git a/src/misc.cc b/src/misc.cc
index f8046ca8..e4b970e4 100644
--- a/src/misc.cc
+++ b/src/misc.cc
@@ -122,3 +122,29 @@ long long int apply_base_multiplier(const char *s, long long int num) {
   }
   return (num * base);
 }
+
+void print_bar(struct text_object *obj, char *p, unsigned int p_max_size) {
+  unsigned int start = 0;
+  unsigned int end = 0;
+  unsigned int x = 0;
+  char c1 = '\0';
+  char c2 = '\0';
+
+  if (4 != sscanf(obj->data.s, "%u %u %c %c", &start, &end, &c1, &c2)) {
+    NORM_ERR("Not enough arguments to print_bar()");
+    return;
+  }
+
+  if (end < start || p_max_size - 1 < end) {
+    NORM_ERR("End should be lesser than start in print_bar()");
+    return;
+  }
+
+  for (; x < start; x++) {
+    p[x] = c1;
+  }
+  for (; x < end; x++) {
+    p[x] = c2;
+  }
+  p[x] = '\0';
+}
diff --git a/src/misc.h b/src/misc.h
index a1cd7770..ad3f3483 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -37,4 +37,5 @@ void print_cat(struct text_object *, char *, unsigned int);
 void print_catp(struct text_object *, char *, unsigned int);
 void print_cap(struct text_object *, char *, unsigned int);
 long long apply_base_multiplier(const char *, long long int);
+void print_bar(struct text_object *, char *, unsigned int);
 #endif /* _MISC_H */

In your config - ${bar 10 20 _ #}

lasers commented 6 years ago

We'll work the kinks out.

eg... ${bar "shuf -i 0-100 -n1" "X" "O"} Maybe...eg... ${bar "shuf -i 0-100 -n1" "X" "O" (height,width)"} conky's style is ${bar (height,width) "shuf -i 0-100 -n1" "X" "O"}

lasers commented 6 years ago

@su8 This might be too much. I'll be okay with... ${bar (height,weight) command} along with two fill/unfill options.

su8 commented 6 years ago
diff --git a/src/conky.cc b/src/conky.cc
index 73a8f34f..1c03b4d9 100644
--- a/src/conky.cc
+++ b/src/conky.cc
@@ -863,6 +863,8 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) {
       }
     } else if (obj->callbacks.barval != nullptr) {
       new_bar(obj, p, p_max_size, (*obj->callbacks.barval)(obj));
+    } else if (obj->callbacks.barval2 != nullptr) {
+      new_bar2(obj, p, p_max_size, (*obj->callbacks.barval2)(obj));
     } else if (obj->callbacks.gaugeval != nullptr) {
       new_gauge(obj, p, p_max_size, (*obj->callbacks.gaugeval)(obj));
 #ifdef BUILD_X11
diff --git a/src/core.cc b/src/core.cc
index 7a438b2e..365ae21a 100644
--- a/src/core.cc
+++ b/src/core.cc
@@ -882,6 +882,12 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
   register_exec(obj);
   obj->callbacks.barval = &execbarval;
   obj->callbacks.free = &free_exec;
+  END OBJ_ARG(bar, nullptr,
+              "bar needs arguments: [height],[width] <command>")
+      scan_exec_arg(obj, arg, EF_EXEC | EF_BAR2);
+  register_exec(obj);
+  obj->callbacks.barval2 = &execbar;
+  obj->callbacks.free = &free_exec;
   END OBJ_ARG(execibar, nullptr,
               "execibar needs arguments: <interval> [height],[width] <command>")
       scan_exec_arg(obj, arg, EF_EXECI | EF_BAR);
diff --git a/src/exec.cc b/src/exec.cc
index bc6bf47b..165e5264 100644
--- a/src/exec.cc
+++ b/src/exec.cc
@@ -268,6 +268,8 @@ void scan_exec_arg(struct text_object *obj, const char *arg,
   /* parse any special options for the graphical exec types */
   if ((execflag & EF_BAR) != 0u) {
     cmd = scan_bar(obj, cmd, 100);
+  } else if (execflag & EF_BAR2) {
+    cmd = scan_bar2(obj, cmd, 100);
 #ifdef BUILD_X11
   } else if ((execflag & EF_GAUGE) != 0u) {
     cmd = scan_gauge(obj, cmd, 100);
@@ -354,6 +356,13 @@ double execbarval(struct text_object *obj) {
   return 0.0;
 }

+double execbar(struct text_object *obj) {
+  if (obj->exec_handle != nullptr) {
+    return get_barnum((*obj->exec_handle)->get_result_copy().c_str());
+  }
+  return 0.0;
+}
+
 /**
  * Free up any dynamically allocated data
  *
diff --git a/src/exec.h b/src/exec.h
index e1cdf7b8..9b2e03ba 100644
--- a/src/exec.h
+++ b/src/exec.h
@@ -69,7 +69,8 @@ enum {
   EF_EXECI = (1 << 1),
   EF_BAR = (1 << 2),
   EF_GRAPH = (1 << 3),
-  EF_GAUGE = (1 << 4)
+  EF_GAUGE = (1 << 4),
+  EF_BAR2 = (1 << 5)
 };

 void scan_exec_arg(struct text_object *, const char *, unsigned int);
@@ -77,6 +78,7 @@ void register_exec(struct text_object *);
 void register_execi(struct text_object *);
 void print_exec(struct text_object *, char *, unsigned int);
 double execbarval(struct text_object *);
+double execbar(struct text_object *);
 void free_exec(struct text_object *);
 void free_execi(struct text_object *);

diff --git a/src/specials.cc b/src/specials.cc
index bb19b13e..e7bac7e6 100644
--- a/src/specials.cc
+++ b/src/specials.cc
@@ -79,6 +79,8 @@ struct bar {
   char flags;
   int width, height;
   double scale;
+  char c1;
+  char c2;
 };

 struct gauge {
@@ -172,6 +174,36 @@ const char *scan_bar(struct text_object *obj, const char *args, double scale) {
   return args;
 }

+const char *scan_bar2(struct text_object *obj, const char *args, double scale) {
+  struct bar *b;
+
+  b = static_cast<struct bar *>(malloc(sizeof(struct bar)));
+  memset(b, 0, sizeof(struct bar));
+
+  /* zero width means all space that is available */
+  b->width = default_bar_width.get(*state);
+  b->height = default_bar_height.get(*state);
+
+  if (scale != 0.0) {
+    b->scale = scale;
+  } else {
+    b->flags |= SF_SCALED;
+  }
+
+  /* bar's argument is either height or height,width */
+  if (args != nullptr) {
+    int n = 0;
+
+    if (sscanf(args, "%d,%d %c,%c %n", &b->height, &b->width, &b->c1, &b->c2, &n) <= 1) {
+      sscanf(args, "%d %c,%c %n", &b->height, &b->c1, &b->c2, &n);
+    }
+    args += n;
+  }
+
+  obj->special_data = b;
+  return args;
+}
+
 #ifdef BUILD_X11
 void scan_font(struct text_object *obj, const char *args) {
   if ((args != nullptr) && (*args != 0)) {
@@ -707,6 +739,37 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,
   buffer[i] = 0;
 }

+static void new_bar_in_shell2(struct text_object *obj, char *buffer,
+                             unsigned int buf_max_size, double usage) {
+  auto *b = static_cast<struct bar *>(obj->special_data);
+  unsigned int width, i, scaledusage;
+
+  if (b == nullptr) {
+    return;
+  }
+
+  width = b->width;
+  if (width == 0) {
+    width = DEFAULT_BAR_WIDTH_NO_X;
+  }
+
+  if (width > buf_max_size) {
+    width = buf_max_size;
+  }
+
+  scaledusage = round_to_int(usage * width / b->scale);
+
+  for (i = 0; i < scaledusage; i++) {
+    buffer[i] = b->c1;
+  }
+
+  for (; i < width; i++) {
+    buffer[i] = b->c2;
+  }
+
+  buffer[i] = 0;
+}
+
 #ifdef BUILD_X11
 static void new_bar_in_x11(struct text_object *obj, char *buf, double usage) {
   struct special_t *s = nullptr;
@@ -754,6 +817,31 @@ void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, double u
 #endif /* BUILD_X11 */
 }

+
+void new_bar2(struct text_object *obj, char *p, unsigned int p_max_size, double usage) {
+  auto *b = static_cast<struct bar *>(obj->special_data);
+
+  if ((p_max_size == 0) || (b == nullptr)) {
+    return;
+  }
+
+  if ((b->flags & SF_SCALED) != 0) {
+    b->scale = MAX(b->scale, usage);
+  } else {
+    usage = MIN(b->scale, usage);
+  }
+
+#ifdef BUILD_X11
+  if (out_to_x.get(*state)) {
+    new_bar_in_x11(obj, p, usage);
+  } else {
+    new_bar_in_shell2(obj, p, p_max_size, usage);
+  }
+#else /* BUILD_X11 */
+  new_bar_in_shell2(obj, p, p_max_size, usage);
+#endif /* BUILD_X11 */
+}
+
 void new_outline(struct text_object *obj, char *p, unsigned int p_max_size) {
   if (p_max_size == 0) {
     return;
diff --git a/src/specials.h b/src/specials.h
index d396d4f2..159dc810 100644
--- a/src/specials.h
+++ b/src/specials.h
@@ -84,6 +84,7 @@ struct text_object;

 /* scanning special arguments */
 const char *scan_bar(struct text_object *, const char *, double);
+const char *scan_bar2(struct text_object *, const char *, double);
 const char *scan_gauge(struct text_object *, const char *, double);
 #ifdef BUILD_X11
 void scan_font(struct text_object *, const char *);
@@ -99,6 +100,7 @@ void new_stippled_hr(struct text_object *, char *, unsigned int);
 #endif /* BUILD_X11 */
 void new_gauge(struct text_object *, char *, unsigned int, double);
 void new_bar(struct text_object *, char *, unsigned int, double);
+void new_bar2(struct text_object *, char *, unsigned int, double);
 void new_fg(struct text_object *, char *, unsigned int);
 void new_bg(struct text_object *, char *, unsigned int);
 void new_outline(struct text_object *, char *, unsigned int);
diff --git a/src/text_object.h b/src/text_object.h
index 01dc3276..b7c9ac53 100644
--- a/src/text_object.h
+++ b/src/text_object.h
@@ -49,6 +49,7 @@ struct obj_cb {
    * a value of 0, make use of auto-scaling (i.e., scaling to the
    * maximum value seen so far). */
   double (*barval)(struct text_object *obj);
+  double (*barval2)(struct text_object *obj);
   double (*gaugeval)(struct text_object *obj);
   double (*graphval)(struct text_object *obj);

In your conf ${bar 30,50 X,0 shuf -i 10-100 -n 1}

edit: depending on whether you use out_to_x and out_to_console it will print different status, on x it will be a real bar, console will print X and 0

su8 commented 6 years ago

Here's a simplified patch, @lasers open up a RP with this patch ?

diff --git a/src/conky.cc b/src/conky.cc
index 73a8f34f..98ffc637 100644
--- a/src/conky.cc
+++ b/src/conky.cc
@@ -862,7 +862,9 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) {
         if (obj->ifblock_next != nullptr) { obj = obj->ifblock_next; }
       }
     } else if (obj->callbacks.barval != nullptr) {
-      new_bar(obj, p, p_max_size, (*obj->callbacks.barval)(obj));
+      new_bar(0, obj, p, p_max_size, (*obj->callbacks.barval)(obj));
+    } else if (obj->callbacks.barval2 != nullptr) {
+      new_bar(1, obj, p, p_max_size, (*obj->callbacks.barval2)(obj));
     } else if (obj->callbacks.gaugeval != nullptr) {
       new_gauge(obj, p, p_max_size, (*obj->callbacks.gaugeval)(obj));
 #ifdef BUILD_X11
diff --git a/src/core.cc b/src/core.cc
index 7a438b2e..e9590d99 100644
--- a/src/core.cc
+++ b/src/core.cc
@@ -882,6 +882,12 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
   register_exec(obj);
   obj->callbacks.barval = &execbarval;
   obj->callbacks.free = &free_exec;
+  END OBJ_ARG(bar, nullptr,
+              "bar needs arguments: [height],[width] <command>")
+      scan_exec_arg(obj, arg, EF_EXEC | EF_BAR2);
+  register_exec(obj);
+  obj->callbacks.barval2 = &execbarval;
+  obj->callbacks.free = &free_exec;
   END OBJ_ARG(execibar, nullptr,
               "execibar needs arguments: <interval> [height],[width] <command>")
       scan_exec_arg(obj, arg, EF_EXECI | EF_BAR);
diff --git a/src/exec.cc b/src/exec.cc
index bc6bf47b..f0528c5f 100644
--- a/src/exec.cc
+++ b/src/exec.cc
@@ -268,6 +268,8 @@ void scan_exec_arg(struct text_object *obj, const char *arg,
   /* parse any special options for the graphical exec types */
   if ((execflag & EF_BAR) != 0u) {
     cmd = scan_bar(obj, cmd, 100);
+  } else if (execflag & EF_BAR2) {
+    cmd = scan_bar2(obj, cmd, 100);
 #ifdef BUILD_X11
   } else if ((execflag & EF_GAUGE) != 0u) {
     cmd = scan_gauge(obj, cmd, 100);
diff --git a/src/exec.h b/src/exec.h
index e1cdf7b8..9b2e03ba 100644
--- a/src/exec.h
+++ b/src/exec.h
@@ -69,7 +69,8 @@ enum {
   EF_EXECI = (1 << 1),
   EF_BAR = (1 << 2),
   EF_GRAPH = (1 << 3),
-  EF_GAUGE = (1 << 4)
+  EF_GAUGE = (1 << 4),
+  EF_BAR2 = (1 << 5)
 };

 void scan_exec_arg(struct text_object *, const char *, unsigned int);
@@ -77,6 +78,7 @@ void register_exec(struct text_object *);
 void register_execi(struct text_object *);
 void print_exec(struct text_object *, char *, unsigned int);
 double execbarval(struct text_object *);
+double execbar(struct text_object *);
 void free_exec(struct text_object *);
 void free_execi(struct text_object *);

diff --git a/src/specials.cc b/src/specials.cc
index bb19b13e..c29cae6c 100644
--- a/src/specials.cc
+++ b/src/specials.cc
@@ -79,6 +79,8 @@ struct bar {
   char flags;
   int width, height;
   double scale;
+  char c1;
+  char c2;
 };

 struct gauge {
@@ -172,6 +174,36 @@ const char *scan_bar(struct text_object *obj, const char *args, double scale) {
   return args;
 }

+const char *scan_bar2(struct text_object *obj, const char *args, double scale) {
+  struct bar *b;
+
+  b = static_cast<struct bar *>(malloc(sizeof(struct bar)));
+  memset(b, 0, sizeof(struct bar));
+
+  /* zero width means all space that is available */
+  b->width = default_bar_width.get(*state);
+  b->height = default_bar_height.get(*state);
+
+  if (scale != 0.0) {
+    b->scale = scale;
+  } else {
+    b->flags |= SF_SCALED;
+  }
+
+  /* bar's argument is either height or height,width */
+  if (args != nullptr) {
+    int n = 0;
+
+    if (sscanf(args, "%d,%d %c,%c %n", &b->height, &b->width, &b->c1, &b->c2, &n) <= 1) {
+      sscanf(args, "%d %c,%c %n", &b->height, &b->c1, &b->c2, &n);
+    }
+    args += n;
+  }
+
+  obj->special_data = b;
+  return args;
+}
+
 #ifdef BUILD_X11
 void scan_font(struct text_object *obj, const char *args) {
   if ((args != nullptr) && (*args != 0)) {
@@ -676,8 +708,8 @@ void new_bg(struct text_object *obj, char *p, unsigned int p_max_size) {
 }
 #endif /* BUILD_X11 */

-static void new_bar_in_shell(struct text_object *obj, char *buffer,
-                             unsigned int buf_max_size, double usage) {
+static void new_bar_in_shell(unsigned int custom_chars, struct text_object *obj,
+                              char *buffer, unsigned int buf_max_size, double usage) {
   auto *b = static_cast<struct bar *>(obj->special_data);
   unsigned int width, i, scaledusage;

@@ -696,12 +728,22 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,

   scaledusage = round_to_int(usage * width / b->scale);

-  for (i = 0; i < scaledusage; i++) {
-    buffer[i] = '#';
-  }
+  if (1 == custom_chars) {
+    for (i = 0; i < scaledusage; i++) {
+      buffer[i] = b->c1;
+    }
+
+    for (; i < width; i++) {
+      buffer[i] = b->c2;
+    }
+  } else {
+    for (i = 0; i < scaledusage; i++) {
+      buffer[i] = '#';
+    }

-  for (; i < width; i++) {
-    buffer[i] = '_';
+    for (; i < width; i++) {
+      buffer[i] = '_';
+    }
   }

   buffer[i] = 0;
@@ -730,7 +772,7 @@ static void new_bar_in_x11(struct text_object *obj, char *buf, double usage) {
 #endif /* BUILD_X11 */

 /* usage is in range [0,255] */
-void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, double usage) {
+void new_bar(unsigned int custom_chars, struct text_object *obj, char *p, unsigned int p_max_size, double usage) {
   auto *b = static_cast<struct bar *>(obj->special_data);

   if ((p_max_size == 0) || (b == nullptr)) {
@@ -747,10 +789,10 @@ void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, double u
   if (out_to_x.get(*state)) {
     new_bar_in_x11(obj, p, usage);
   } else {
-    new_bar_in_shell(obj, p, p_max_size, usage);
+    new_bar_in_shell(custom_chars, obj, p, p_max_size, usage);
   }
 #else /* BUILD_X11 */
-  new_bar_in_shell(obj, p, p_max_size, usage);
+  new_bar_in_shell(custom_chars, obj, p, p_max_size, usage);
 #endif /* BUILD_X11 */
 }

diff --git a/src/specials.h b/src/specials.h
index d396d4f2..e70e99ea 100644
--- a/src/specials.h
+++ b/src/specials.h
@@ -84,6 +84,7 @@ struct text_object;

 /* scanning special arguments */
 const char *scan_bar(struct text_object *, const char *, double);
+const char *scan_bar2(struct text_object *, const char *, double);
 const char *scan_gauge(struct text_object *, const char *, double);
 #ifdef BUILD_X11
 void scan_font(struct text_object *, const char *);
@@ -98,7 +99,7 @@ void new_hr(struct text_object *, char *, unsigned int);
 void new_stippled_hr(struct text_object *, char *, unsigned int);
 #endif /* BUILD_X11 */
 void new_gauge(struct text_object *, char *, unsigned int, double);
-void new_bar(struct text_object *, char *, unsigned int, double);
+void new_bar(unsigned int, struct text_object *, char *, unsigned int, double);
 void new_fg(struct text_object *, char *, unsigned int);
 void new_bg(struct text_object *, char *, unsigned int);
 void new_outline(struct text_object *, char *, unsigned int);
diff --git a/src/text_object.h b/src/text_object.h
index 01dc3276..b7c9ac53 100644
--- a/src/text_object.h
+++ b/src/text_object.h
@@ -49,6 +49,7 @@ struct obj_cb {
    * a value of 0, make use of auto-scaling (i.e., scaling to the
    * maximum value seen so far). */
   double (*barval)(struct text_object *obj);
+  double (*barval2)(struct text_object *obj);
   double (*gaugeval)(struct text_object *obj);
   double (*graphval)(struct text_object *obj);
lasers commented 6 years ago

I think it sucks, but we should use this for consistency with other bars.

    ${bar (height,width) "command" (fill,unfill)} 
    ${bar "command"}  # minimal
    ${bar 30,100 "shuf -i 4-100 -n 1" #,_}  # override everything
    ${bar 30,100 "shuf -i 4-100 -n 1"}  # custom bar height/width
    ${bar "shuf -i 4-100 -n 1" #,_}  # override icons

Because we can't do ${bar #,_ "shuf -i 4-100 -n 1"}.

su8 commented 6 years ago

Okay sir, try this:

diff --git a/src/conky.cc b/src/conky.cc
index 73a8f34f..98ffc637 100644
--- a/src/conky.cc
+++ b/src/conky.cc
@@ -862,7 +862,9 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) {
         if (obj->ifblock_next != nullptr) { obj = obj->ifblock_next; }
       }
     } else if (obj->callbacks.barval != nullptr) {
-      new_bar(obj, p, p_max_size, (*obj->callbacks.barval)(obj));
+      new_bar(0, obj, p, p_max_size, (*obj->callbacks.barval)(obj));
+    } else if (obj->callbacks.barval2 != nullptr) {
+      new_bar(1, obj, p, p_max_size, (*obj->callbacks.barval2)(obj));
     } else if (obj->callbacks.gaugeval != nullptr) {
       new_gauge(obj, p, p_max_size, (*obj->callbacks.gaugeval)(obj));
 #ifdef BUILD_X11
diff --git a/src/core.cc b/src/core.cc
index 7a438b2e..e9590d99 100644
--- a/src/core.cc
+++ b/src/core.cc
@@ -882,6 +882,12 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
   register_exec(obj);
   obj->callbacks.barval = &execbarval;
   obj->callbacks.free = &free_exec;
+  END OBJ_ARG(bar, nullptr,
+              "bar needs arguments: [height],[width] <command>")
+      scan_exec_arg(obj, arg, EF_EXEC | EF_BAR2);
+  register_exec(obj);
+  obj->callbacks.barval2 = &execbarval;
+  obj->callbacks.free = &free_exec;
   END OBJ_ARG(execibar, nullptr,
               "execibar needs arguments: <interval> [height],[width] <command>")
       scan_exec_arg(obj, arg, EF_EXECI | EF_BAR);
diff --git a/src/exec.cc b/src/exec.cc
index bc6bf47b..f0528c5f 100644
--- a/src/exec.cc
+++ b/src/exec.cc
@@ -268,6 +268,8 @@ void scan_exec_arg(struct text_object *obj, const char *arg,
   /* parse any special options for the graphical exec types */
   if ((execflag & EF_BAR) != 0u) {
     cmd = scan_bar(obj, cmd, 100);
+  } else if (execflag & EF_BAR2) {
+    cmd = scan_bar2(obj, cmd, 100);
 #ifdef BUILD_X11
   } else if ((execflag & EF_GAUGE) != 0u) {
     cmd = scan_gauge(obj, cmd, 100);
diff --git a/src/exec.h b/src/exec.h
index e1cdf7b8..9b2e03ba 100644
--- a/src/exec.h
+++ b/src/exec.h
@@ -69,7 +69,8 @@ enum {
   EF_EXECI = (1 << 1),
   EF_BAR = (1 << 2),
   EF_GRAPH = (1 << 3),
-  EF_GAUGE = (1 << 4)
+  EF_GAUGE = (1 << 4),
+  EF_BAR2 = (1 << 5)
 };

 void scan_exec_arg(struct text_object *, const char *, unsigned int);
@@ -77,6 +78,7 @@ void register_exec(struct text_object *);
 void register_execi(struct text_object *);
 void print_exec(struct text_object *, char *, unsigned int);
 double execbarval(struct text_object *);
+double execbar(struct text_object *);
 void free_exec(struct text_object *);
 void free_execi(struct text_object *);

diff --git a/src/specials.cc b/src/specials.cc
index bb19b13e..c04e9a94 100644
--- a/src/specials.cc
+++ b/src/specials.cc
@@ -79,6 +79,8 @@ struct bar {
   char flags;
   int width, height;
   double scale;
+  char c1;
+  char c2;
 };

 struct gauge {
@@ -172,6 +174,36 @@ const char *scan_bar(struct text_object *obj, const char *args, double scale) {
   return args;
 }

+const char *scan_bar2(struct text_object *obj, const char *args, double scale) {
+  struct bar *b;
+
+  b = static_cast<struct bar *>(malloc(sizeof(struct bar)));
+  memset(b, 0, sizeof(struct bar));
+
+  /* zero width means all space that is available */
+  b->width = default_bar_width.get(*state);
+  b->height = default_bar_height.get(*state);
+
+  if (scale != 0.0) {
+    b->scale = scale;
+  } else {
+    b->flags |= SF_SCALED;
+  }
+
+  /* bar's argument is either height or height,width */
+  if (args != nullptr) {
+    int n = 0;
+
+    if (sscanf(args, "%d,%d %c,%c %n", &b->height, &b->width, &b->c1, &b->c2, &n) <= 1) {
+      sscanf(args, "%c,%c %n", &b->c1, &b->c2, &n);
+    }
+    args += n;
+  }
+
+  obj->special_data = b;
+  return args;
+}
+
 #ifdef BUILD_X11
 void scan_font(struct text_object *obj, const char *args) {
   if ((args != nullptr) && (*args != 0)) {
@@ -676,8 +708,8 @@ void new_bg(struct text_object *obj, char *p, unsigned int p_max_size) {
 }
 #endif /* BUILD_X11 */

-static void new_bar_in_shell(struct text_object *obj, char *buffer,
-                             unsigned int buf_max_size, double usage) {
+static void new_bar_in_shell(unsigned int custom_chars, struct text_object *obj,
+                              char *buffer, unsigned int buf_max_size, double usage) {
   auto *b = static_cast<struct bar *>(obj->special_data);
   unsigned int width, i, scaledusage;

@@ -696,12 +728,22 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,

   scaledusage = round_to_int(usage * width / b->scale);

-  for (i = 0; i < scaledusage; i++) {
-    buffer[i] = '#';
-  }
+  if (1 == custom_chars) {
+    for (i = 0; i < scaledusage; i++) {
+      buffer[i] = b->c1;
+    }
+
+    for (; i < width; i++) {
+      buffer[i] = b->c2;
+    }
+  } else {
+    for (i = 0; i < scaledusage; i++) {
+      buffer[i] = '#';
+    }

-  for (; i < width; i++) {
-    buffer[i] = '_';
+    for (; i < width; i++) {
+      buffer[i] = '_';
+    }
   }

   buffer[i] = 0;
@@ -730,7 +772,7 @@ static void new_bar_in_x11(struct text_object *obj, char *buf, double usage) {
 #endif /* BUILD_X11 */

 /* usage is in range [0,255] */
-void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, double usage) {
+void new_bar(unsigned int custom_chars, struct text_object *obj, char *p, unsigned int p_max_size, double usage) {
   auto *b = static_cast<struct bar *>(obj->special_data);

   if ((p_max_size == 0) || (b == nullptr)) {
@@ -747,10 +789,10 @@ void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, double u
   if (out_to_x.get(*state)) {
     new_bar_in_x11(obj, p, usage);
   } else {
-    new_bar_in_shell(obj, p, p_max_size, usage);
+    new_bar_in_shell(custom_chars, obj, p, p_max_size, usage);
   }
 #else /* BUILD_X11 */
-  new_bar_in_shell(obj, p, p_max_size, usage);
+  new_bar_in_shell(custom_chars, obj, p, p_max_size, usage);
 #endif /* BUILD_X11 */
 }

diff --git a/src/specials.h b/src/specials.h
index d396d4f2..e70e99ea 100644
--- a/src/specials.h
+++ b/src/specials.h
@@ -84,6 +84,7 @@ struct text_object;

 /* scanning special arguments */
 const char *scan_bar(struct text_object *, const char *, double);
+const char *scan_bar2(struct text_object *, const char *, double);
 const char *scan_gauge(struct text_object *, const char *, double);
 #ifdef BUILD_X11
 void scan_font(struct text_object *, const char *);
@@ -98,7 +99,7 @@ void new_hr(struct text_object *, char *, unsigned int);
 void new_stippled_hr(struct text_object *, char *, unsigned int);
 #endif /* BUILD_X11 */
 void new_gauge(struct text_object *, char *, unsigned int, double);
-void new_bar(struct text_object *, char *, unsigned int, double);
+void new_bar(unsigned int, struct text_object *, char *, unsigned int, double);
 void new_fg(struct text_object *, char *, unsigned int);
 void new_bg(struct text_object *, char *, unsigned int);
 void new_outline(struct text_object *, char *, unsigned int);
diff --git a/src/text_object.h b/src/text_object.h
index 01dc3276..b7c9ac53 100644
--- a/src/text_object.h
+++ b/src/text_object.h
@@ -49,6 +49,7 @@ struct obj_cb {
    * a value of 0, make use of auto-scaling (i.e., scaling to the
    * maximum value seen so far). */
   double (*barval)(struct text_object *obj);
+  double (*barval2)(struct text_object *obj);
   double (*gaugeval)(struct text_object *obj);
   double (*graphval)(struct text_object *obj);

Now ${bar #,_ "shuf -i 4-100 -n 1"} works.

lasers commented 6 years ago

error: corrupt patch. no more diff. push it up. :heart:

su8 commented 6 years ago

Do I have to open up a PR or you'll pull this commit - https://github.com/su8/conky/commit/579a2ce013dbc357c98ab299179a53876844a7c9 :question:

lasers commented 6 years ago

I pulled it to test it., You can open if you want... More contribution credits. :wink:

lasers commented 6 years ago

Bad at ...

    ${bar "shuf -i 4-100 -n 1"}
    ${bar shuf -i 4-100 -n 1}
su8 commented 6 years ago

My bad, out_toconsole didn't initialize the c1 and c2 to # and . Try now.

lasers commented 6 years ago

Same thing.

conky.config = {
    out_to_x=false,
    out_to_console=true,
    update_interval=1,
    default_bar_width=100,
}
conky.text = [[
    ${bar 30,100 #,_ "shuf -i 4-100 -n 1"}
    ${bar x,o "shuf -i 4-100 -n 1"}
    ${bar "shuf -i 4-100 -n 1"}
    ${bar shuf -i 4-100 -n 1}
    -----
]]

#################################################___________________________________________________
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxooooooooooooooooooooooooooooooooooooooooooooooooooo
    """""""""""""""""""""""""""""""""""""""""""""""""
    ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
    -----
lasers commented 6 years ago

Let's simplify it with ${bar (height,width) "command"} and two fill/unfill options. We don't hurt the users this way.

su8 commented 6 years ago

Can you try https://github.com/su8/conky/commit/84845fd5f064450c7fa97ee05d879136b00233c0

lasers commented 6 years ago

Nice. Can we accept strings instead of character? eg, '0,'1' to print 0000000000001111. EDIT: "[\?color=pink&show s]","[\?color=blue&show u]" --> sssssssssuuuuuuuuuuuuuuuuuuuu

[\?color=pink&show s][\?color=pink&show s][\?color=pink&show s][\?color=pink&show s][\?color=blue&show u][\?color=blue&show u][\?color=blue&show u]

lasers commented 6 years ago

@su8 You know what? This is good enough. Make a PR? :-)

lasers commented 6 years ago

Also, we need default_bar_fill and default_bar_unfill to override all (console) bars.

su8 commented 6 years ago

Pull the commits from my repo as I'm 2 commits behind the master branch and will override the changes we did yesterday.

lasers commented 6 years ago

git pull --rebase upstream master should do it.

Replace upstream with whatever you have in git remote -v. Might be upstream, origin or su8.

su8 commented 6 years ago

git pull --rebase https://github.com/brndnmtthws/conky.git master and git push -f thanks.

lasers commented 6 years ago

@su8 Let's think for a bit... and not rushing.

Why don't we just use execbar instead? All we need to do is to add default_bar_fill and default_bar_unfill.... right?

       execbar (height),(width) command
              Same  as  exec, except if the first value returned is a value between 0-100, it will use that number
              to draw a horizontal bar. The height and width parameters are  optional,  and  default  to  the  de‐
              fault_bar_height and default_bar_width config settings, respectively.
    BAR1: ############################______________________
    BAR2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxoooooooooooooooooooooo
    BAR3: ############################______________________
    BAR4: jjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkk
    -----
    BAR1: ##############################____________________
    BAR2: #############_____________________________________
    BAR3: ###########_______________________________________
    BAR4: #######################################___________
su8 commented 6 years ago

Done, execbar now takes the bar function.

lasers commented 6 years ago

Nice enhancement for {execbar} (only in console).

We still need default_bar_fill and default_bar_unfill to change other bars though.. like {battery_bar}, {volume_bar}, {cmus_progress}, {cpubar}, etc.

su8 commented 6 years ago

@lasers Can you test my latest commit ?

conky.config = {
    out_to_x=false,
    out_to_console=true,
    update_interval=1,
    default_bar_width=100,
}
conky.text = [[
    ${execbar 30,50 "shuf -i 3-100 -n 1"}
    ${execbar x,o "shuf -i 4-100 -n 1"}
    ${execbar 30,100 #,_ "shuf -i 5-100 -n 1"}
    ${execbar "shuf -i 6-100 -n 1"}
    -----
]]
lasers commented 6 years ago

@su8 Sure. Can you tell me why we can't have default_bar_fill and default_bar_unfill to override bars? I'm not sure if you tried or it's not possible or you don't want to.

su8 commented 6 years ago

What's expected from default_bar_fill to do ?

lasers commented 6 years ago

default_bar_fill replaces hardcoded #. default_bar_unfill replaces hardcoded _.

For all bars. Leave execbar alone as-is.

su8 commented 6 years ago

For some reason the c1 and c2 are not updated, so passing x and 0 doesn't work anymore :rofl:

su8 commented 6 years ago

Here we are again, lone ${execbar x,o "shuf -i 4-100 -n 1"} works fine, lone ${execbar 30,100 x,0 "shuf -i 5-100 -n 1"} works fine, but when used in combination with other ${execbar "shuf -i 6-100 -n 1"} things get overridden. Same bugs as yesterdays one and the day before that :lollipop:

lasers commented 6 years ago

@su8 Trying this again...

What about config option inside conky.config?

conky.config = {
    out_to_true=false,
    out_to_console=false.
    default_bar_fill='#',    # string
    default_bar_unfill='_',   # string
}

I don't know if fs_root is a good name.

su8 commented 6 years ago

Didn't reset my branch, so it contains traces of the incorrect disk usage issue:

diff --git a/src/common.cc b/src/common.cc
index d9e29114..4bb9b5dd 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -273,6 +273,9 @@ void format_seconds_short(char *buf, unsigned int n, long seconds) {
 }

 conky::simple_config_setting<bool> no_buffers("no_buffers", true, true);
+conky::simple_config_setting<bool> fs_avail("fs_avail", true, true);
+conky::simple_config_setting<std::string> bar_fill("default_bar_fill", "#", false);
+conky::simple_config_setting<std::string> bar_unfill("default_bar_unfill", "_", false);

 void update_stuff() {
   /* clear speeds, addresses and up status in case device was removed and
diff --git a/src/common.h b/src/common.h
index 5b23e356..065e5a1d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -74,6 +74,9 @@ int round_to_int_temp(float);
 unsigned int round_to_int(float);

 extern conky::simple_config_setting<bool> no_buffers;
+extern conky::simple_config_setting<bool> fs_avail;
+extern conky::simple_config_setting<std::string> bar_fill;
+extern conky::simple_config_setting<std::string> bar_unfill;

 int open_acpi_temperature(const char *name);
 double get_acpi_temperature(int fd);
diff --git a/src/fs.cc b/src/fs.cc
index 463d650e..790330b0 100644
--- a/src/fs.cc
+++ b/src/fs.cc
@@ -37,6 +37,7 @@
 #include "logging.h"
 #include "specials.h"
 #include "text_object.h"
+#include "common.h"

 #ifdef HAVE_SYS_STATFS_H
 #include <sys/statfs.h>
@@ -225,6 +226,8 @@ static double get_fs_perc(struct text_object *obj, bool get_free) {
   if ((fs != nullptr) && (fs->size != 0)) {
     if (get_free) {
       ret = fs->avail;
+    } else if (fs_avail.get(*state)) {
+      ret = fs->size - fs->avail;
     } else {
       ret = fs->size - fs->free;
     }
diff --git a/src/specials.cc b/src/specials.cc
index bb19b13e..912ed967 100644
--- a/src/specials.cc
+++ b/src/specials.cc
@@ -40,6 +40,7 @@
 #include "colours.h"
 #include <algorithm>
 #include <sstream>
+#include "common.h"

 struct special_t *specials = nullptr;

@@ -697,11 +698,11 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,
   scaledusage = round_to_int(usage * width / b->scale);

   for (i = 0; i < scaledusage; i++) {
-    buffer[i] = '#';
+    buffer[i] = *(bar_fill.get(*state).c_str());
   }

   for (; i < width; i++) {
-    buffer[i] = '_';
+    buffer[i] = *(bar_unfill.get(*state).c_str());
   }

   buffer[i] = 0;

edit: config

conky.config = {
    out_to_x=false,
    out_to_console=true,
    update_interval=1,
    default_bar_width=100,
    fs_avail=true,
    default_bar_fill='x',
    default_bar_unfill='0',
}
conky.text = [[
    ${fs_used_perc /}
    ${execbar "shuf -i 6-100 -n 1"}
]]
lasers commented 6 years ago

I tried to edit the diff. Came out fatal. Push it to your daddy master so I can test it. Today, we close this one. No need for crazy ${8ball bars} with tricky configs.

EDIT: I got it...

lasers commented 6 years ago

Closed via https://github.com/brndnmtthws/conky/pull/624.

lasers commented 6 years ago

@su8 Is it possible to accept strings instead of characters?

console_bar_fill = '[\?color=pink&show #]',
console_bar_unfill = '[\?color=blue&show .]',

As you can see here, I want to ab(use) the new options.

lasers commented 6 years ago
conky.config = {console_bar_unfill=-,out_to_x=false,out_to_console=true}
conky.text = [[
    ${cpubar cpu0} ${cpubar cpu1} ${cpubar cpu2} ${cpubar cpu3}
    ${cpu cpu0} ${cpu cpu1} ${cpu cpu2} ${cpu cpu3}
]]

This does not work because of unquoted -. Is it my problem, Lua problem or Conky problem? EDIT: Seems like it's my shitty json->lua parser. I used json_dumps(config, separators=(',', '=')).replace('"', '') but can't find anything decent.

json str: {"console_bar_unfill": "-", "out_to_x": false, "out_to_console": true}