Commit Diff


commit - 6da988820b4410d7a4a735cd78a33135d806942f
commit + 8758854a52c5835c27c024b4020cb953152a7f14
blob - 7f09237cd9c8f5fdde0beafb622649617859876e
blob + 47f25307e58c9bb40597a65b432f864f93fd59bc
--- Xexample
+++ Xexample
@@ -1,5 +1,6 @@
-MyMenu.font: -misc-tamsyn-medium-r-normal--15-108-100-100-c-80-iso8859-1
+MyMenu.font: fixed
 MyMenu.layout: horizontal
+MyMenu.prompt: "$ "
 
 MyMenu.width: 100%
 MyMenu.height: 30
blob - 8572eb423a8ba658eaf5e7b7b4260727c10626ae
blob + 36cff68847fa11f57e6de4a6cb7762c3979a2ada
--- mymenu.1
+++ mymenu.1
@@ -27,16 +27,18 @@ The layout of the menu. The possible values are "horiz
 "vertical", with the default being "horizontal". Every other value
 than "horizontal" is treated like "vertical", but this is kinda an
 implementation detail and not something to be relied on, since in the
-future other layout could be added as well
+future other layout could be added as well.
+.It Mymenu.prompt
+A string that is rendered before the user input. Default to "$ ".
 .It MyMenu.width
 The width of the menu. If a numeric value is given (e.g. 400) is
 interpreted as pixel, if it ends with a percentage symbol `%'
 (e.g. 40%) the relative percentage will be computed (relative to the
-monitor width)
+monitor width).
 .It MyMenu.height
 The height of the menu. Like MyMenu.width if a numeric value is given
 is interpreted as pixel, if it ends with a percentage symbol `%' the
-relative percentage will be computed (relative to the monitor height)
+relative percentage will be computed (relative to the monitor height).
 .It MyMenu.x
 The X coordinate of the topmost left corner of the window. Much like
 MyMenu.height and MyMenu.width both a pixel dimension and percentage
@@ -47,17 +49,17 @@ The Y coordinate of the topmost left corner of the win
 coordinate, pixel dimension, percentage dimension and the special
 value "middle" could be supplied.
 .It MyMenu.prompt.background
-The background of the prompt
+The background of the prompt.
 .It MyMenu.prompt.foreground
-The text color (foreground) of the prompt
+The text color (foreground) of the prompt.
 .It MyMenu.completion.background
-The background of the completions
+The background of the completions.
 .It MyMenu.completion.foreground
-The text color of the completions
+The text color of the completions.
 .It MyMenu.completion_highlighted.background
-The background of the selected completion
+The background of the selected completion.
 .It MyMenu.completion_highlighted.foreground
-The foreground of the selected completion
+The foreground of the selected completion.
 .El
 
 .Sh KEYS
blob - 75404a9f488ac60c33402ba2faa2076ea7ca4b3b
blob + ace8989513debf93c111b8e42f36472347566019
--- mymenu.c
+++ mymenu.c
@@ -83,6 +83,8 @@ struct rendering {
   int height;
   XFontSet *font;
   bool horizontal_layout;
+  char *ps1;
+  int ps1len;
 };
 
 struct completions {
@@ -230,6 +232,39 @@ void popc(char *p, int maxlen) {
   }
 }
 
+// If the string is surrounded by quotes (`"`) remove them and replace
+// every `\"` in the string with `"`
+char *normalize_str(const char *str) {
+  int len = strlen(str);
+  if (len == 0)
+    return nil;
+
+  char *s = calloc(len, sizeof(char));
+  check_allocation(s);
+  int p = 0;
+  while (*str) {
+    char c = *str;
+    if (*str == '\\') {
+      if (*(str + 1)) {
+        s[p] = *(str + 1);
+        p++;
+        str += 2; // skip this and the next char
+        continue;
+      } else {
+        break;
+      }
+    }
+    if (c == '"') {
+      str++; // skip only this char
+      continue;
+    }
+    s[p] = c;
+    p++;
+    str++;
+  }
+  return s;
+}
+
 // read an arbitrary long line from stdin and return a pointer to it
 // TODO: resize the allocated memory to exactly fit the string once
 // read?
@@ -298,7 +333,10 @@ void draw_horizontally(struct rendering *r, char *text
   /* int start_at = XTextWidth(r->font, " ", 1) * prompt_width + padding; */
 
   XRectangle rect;
-  int start_at = XmbTextExtents(*r->font, " ", 1, nil, &rect);
+  int ps1xlen = XmbTextExtents(*r->font, r->ps1, r->ps1len, nil, &rect);
+  int start_at = ps1xlen;
+
+  start_at += XmbTextExtents(*r->font, " ", 1, nil, &rect);
   start_at = start_at * prompt_width + padding;
 
   int texty = (rect.height + r->height) >>1;
@@ -309,7 +347,8 @@ void draw_horizontally(struct rendering *r, char *text
   if (text_len > prompt_width)
     text = text + (text_len - prompt_width);
   /* XDrawString(r->d, r->w, r->prompt, padding, texty, text, MIN(text_len, prompt_width)); */
-  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding, texty, text, MIN(text_len, prompt_width));
+  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding, texty, r->ps1, r->ps1len);
+  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding + ps1xlen, texty, text, MIN(text_len, prompt_width));
 
   XFillRectangle(r->d, r->w, r->completion_bg, start_at, 0, r->width, r->height);
 
@@ -356,7 +395,9 @@ void draw_vertically(struct rendering *r, char *text, 
 
   XFillRectangle(r->d, r->w, r->completion_bg, 0, 0, r->width, r->height);
   XFillRectangle(r->d, r->w, r->prompt_bg, 0, 0, r->width, start_at);
-  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding, padding*2, text, strlen(text));
+  int ps1xlen = XmbTextExtents(*r->font, r->ps1, r->ps1len, nil, nil);
+  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding, padding*2, r->ps1, r->ps1len);
+  Xutf8DrawString(r->d, r->w, *r->font, r->prompt, padding + ps1xlen, padding*2, text, strlen(text));
 
   while (cs != nil) {
     GC g = cs->selected ? r->completion_highlighted    : r->completion;
@@ -525,6 +566,9 @@ int main() {
   int x = 0;
   int y = 0;
 
+  char *ps1 = strdup("$ ");
+  check_allocation(ps1);
+
   char *fontname = strdup("fixed");
   check_allocation(fontname);
 
@@ -605,6 +649,12 @@ int main() {
     else
       fprintf(stderr, "no layout defined, using horizontal\n");
 
+    if (XrmGetResource(xdb, "MyMenu.prompt", "*", datatype, &value) == true) {
+      free(ps1);
+      ps1 = normalize_str(value.addr);
+    } else
+      fprintf(stderr, "no prompt defined, using \"%s\" as default\n", ps1);
+
     if (XrmGetResource(xdb, "MyMenu.width", "*", datatype, &value) == true)
       width = parse_integer(value.addr, width, d_width);
     else
@@ -743,7 +793,9 @@ int main() {
     .width                      = width,
     .height                     = height,
     .font                       = &font,
-    .horizontal_layout          = horizontal_layout
+    .horizontal_layout          = horizontal_layout,
+    .ps1                        = ps1,
+    .ps1len                     = strlen(ps1)
   };
 
   // load the colors in our GCs
@@ -924,12 +976,13 @@ int main() {
     free(lines[i]);
   }
 
+  free(ps1);
   free(fontname);
   free(text);
   free(lines);
   compl_delete(cs);
 
-  /* XDestroyWindow(d, w); */
+  XDestroyWindow(d, w);
   XCloseDisplay(d);
 
   return status == OK ? 0 : 1;