about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/config.md14
-rw-r--r--res/config.toml1
-rw-r--r--src/buffer/container.nim4
-rw-r--r--src/config/config.nim1
-rw-r--r--src/display/pager.nim5
-rw-r--r--src/display/term.nim48
6 files changed, 41 insertions, 32 deletions
diff --git a/doc/config.md b/doc/config.md
index 6b6d5dd2..2cf0a02d 100644
--- a/doc/config.md
+++ b/doc/config.md
@@ -15,9 +15,11 @@ omnirule = [] # note: this must be placed at the beginning of the file.
 [[omnirule]] # this is legal. all default omni-rules are now disabled.
 ```
 
-Chawan will look for a config file in the ~/.config/chawan/ directory called
-`config.toml`. See the default configuration file in the res/ folder, and
-bonus configuration files in the bonus/ folder for further examples.
+Chawan will look for a config file in the $XDG_CONFIG_HOME/chawan/ (or
+directory called `config.toml`. (Chawan defaults to ~/.config if the
+XDG_CONFIG_HOME environment variable is not set.) See the default configuration
+file in the res/ folder, and bonus configuration files in the bonus/ folder
+for further examples.
 
 **Table of contents**
 
@@ -263,6 +265,12 @@ black background, etc).</td>
 <td>Force the screen to be completely cleared every time it is redrawn.</td>
 </tr>
 
+<tr>
+<td>set-title</td>
+<td>boolean</td>
+<td>Set the terminal emulator's window title to that of the current page.</td>
+</tr>
+
 </table>
 
 ## Omnirule
diff --git a/res/config.toml b/res/config.toml
index 32e390e5..ae1d5984 100644
--- a/res/config.toml
+++ b/res/config.toml
@@ -29,6 +29,7 @@ highlight-color = "cyan"
 double-width-ambiguous = false
 minimum-contrast = 100
 force-clear = false
+set-title = true
 
 [[omnirule]]
 match = '^ddg:'
diff --git a/src/buffer/container.nim b/src/buffer/container.nim
index 7ee40f22..e301e05c 100644
--- a/src/buffer/container.nim
+++ b/src/buffer/container.nim
@@ -36,7 +36,7 @@ type
 
   ContainerEventType* = enum
     NO_EVENT, FAIL, SUCCESS, NEEDS_AUTH, REDIRECT, ANCHOR, NO_ANCHOR, UPDATE,
-    READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT, LOADED
+    READ_LINE, READ_AREA, OPEN, INVALID_COMMAND, STATUS, ALERT, LOADED, TITLE
 
   ContainerEvent* = object
     case t*: ContainerEventType
@@ -679,7 +679,7 @@ proc onload(container: Container, res: LoadResult) =
       container.iface.getTitle().then(proc(title: string): auto =
         if title != "":
           container.title = title
-          container.triggerEvent(STATUS)
+          container.triggerEvent(TITLE)
         return container.iface.render()
       ).then(proc(lines: int): auto =
         container.setNumLines(lines, true)
diff --git a/src/config/config.nim b/src/config/config.nim
index 90402149..d242c37d 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -88,6 +88,7 @@ type
     double_width_ambiguous*: bool
     minimum_contrast*: int32
     force_clear*: bool
+    set_title*: bool
 
   #TODO: add JS wrappers for objects
   Config* = ref ConfigObj
diff --git a/src/display/pager.nim b/src/display/pager.nim
index 85381c48..fde58c92 100644
--- a/src/display/pager.nim
+++ b/src/display/pager.nim
@@ -93,6 +93,7 @@ iterator containers*(pager: Pager): Container {.inline.} =
 proc setContainer*(pager: Pager, c: Container) {.jsfunc.} =
   pager.container = c
   pager.redraw = true
+  pager.term.setTitle(c.getTitle())
 
 proc hasprop(pager: Pager, s: string): bool {.jshasprop.} =
   if pager.container != nil:
@@ -854,6 +855,10 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo
   of STATUS:
     if pager.container == container:
       pager.refreshStatusMsg()
+  of TITLE:
+    if pager.container == container:
+      pager.refreshStatusMsg()
+      pager.term.setTitle(container.getTitle())
   of ALERT:
     if pager.container == container:
       pager.alert(event.msg)
diff --git a/src/display/term.nim b/src/display/term.nim
index e665faee..4f33ee1a 100644
--- a/src/display/term.nim
+++ b/src/display/term.nim
@@ -61,35 +61,24 @@ func hascap(term: Terminal, c: TermcapCap): bool = term.tc.caps[c] != nil
 func cap(term: Terminal, c: TermcapCap): string = $term.tc.caps[c]
 func ccap(term: Terminal, c: TermcapCap): cstring = term.tc.caps[c]
 
-template CSI*(s: varargs[string, `$`]): string =
-  var r = "\e["
-  var first = true
-  for x in s:
-    if not first:
-      r &= ";"
-    first = false
-    r &= x
-  r
+# control sequence introducer
+template CSI(s: varargs[string, `$`]): string =
+  "\e[" & s.join(';')
+
+# OS command
+template OSC(s: varargs[string, `$`]): string =
+  "\e]" & s.join(';') & '\a'
+
+template XTERM_TITLE(s: string): string =
+  OSC(0, s)
 
 when not termcap_found:
+  # DEC set
   template DECSET(s: varargs[string, `$`]): string =
-    var r = "\e[?"
-    var first = true
-    for x in s:
-      if not first:
-        r &= ";"
-      first = false
-      r &= x
-    r & "h"
+    "\e[?" & s.join(';') & 'h'
+  # DEC reset
   template DECRST(s: varargs[string, `$`]): string =
-    var r = "\e[?"
-    var first = true
-    for x in s:
-      if not first:
-        r &= ";"
-      first = false
-      r &= x
-    r & "l"
+    "\e[?" & s.join(';') & 'l'
   template SMCUP(): string = DECSET(1049)
   template RMCUP(): string = DECRST(1049)
   template HVP(s: varargs[string, `$`]): string =
@@ -324,6 +313,10 @@ proc windowChange*(term: Terminal, attrs: WindowAttributes) =
   term.canvas = newFixedGrid(attrs.width, attrs.height)
   term.cleared = false
 
+proc setTitle*(term: Terminal, title: string) =
+  if term.config.display.set_title:
+    term.outfile.write(XTERM_TITLE(title))
+
 proc processOutputString*(term: Terminal, str: string, w: var int): string =
   if str.validateUtf8() != -1:
     return "?"
@@ -447,8 +440,9 @@ proc applyConfig(term: Terminal) =
   for fm in FormatFlags:
     if fm in term.config.display.no_format_mode:
       term.formatmode.excl(fm)
-  if term.isatty() and term.config.display.alt_screen.isSome:
-    term.smcup = term.config.display.alt_screen.get
+  if term.isatty():
+    if term.config.display.alt_screen.isSome:
+      term.smcup = term.config.display.alt_screen.get
   term.mincontrast = term.config.display.minimum_contrast
   if term.config.encoding.display_charset.isSome:
     term.cs = term.config.encoding.display_charset.get