veyron/lib/textutil: Add textutil package, including LineWriter.
LineWriter implements an io.Writer filter that formats input text
into output lines with a given target width in runes. It
performs word-wrapping.
In order to implement this as an io.Writer filter, I also added
UTF8ChunkDecoder which decodes a stream of UTF-8 encoded runes
that may be arbitrarily chunked. There's also a RuneChunkDecoder
interface to allow us to easily add UTF-16 support in the future.
I've updated the cmdline package to use this new support, and
updated the vdl tool docs with the new formatting to give an idea
of the changes. I'll re-generate all docs in a subsequent CL.
Change-Id: Ia83cffe71d6fd43a0806fe028ff92d0d4ff079c3
diff --git a/lib/textutil/util.go b/lib/textutil/util.go
new file mode 100644
index 0000000..85402de
--- /dev/null
+++ b/lib/textutil/util.go
@@ -0,0 +1,40 @@
+package textutil
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// TerminalSize returns the dimensions of the terminal, if it's available from
+// the OS, otherwise returns an error.
+func TerminalSize() (row, col int, _ error) {
+ // Try getting the terminal size from stdout, stderr and stdin respectively.
+ // We try each of these in turn because the mechanism we're using fails if any
+ // of the fds is redirected on the command line. E.g. "tool | less" redirects
+ // the stdout of tool to the stdin of less, and will mean tool cannot retrieve
+ // the terminal size from stdout.
+ //
+ // TODO(toddw): This probably only works on some linux / unix variants; add
+ // build tags and support different platforms.
+ if row, col, err := terminalSize(syscall.Stdout); err == nil {
+ return row, col, err
+ }
+ if row, col, err := terminalSize(syscall.Stderr); err == nil {
+ return row, col, err
+ }
+ return terminalSize(syscall.Stdin)
+}
+
+func terminalSize(fd int) (int, int, error) {
+ var ws winsize
+ if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&ws))); err != 0 {
+ return 0, 0, err
+ }
+ return int(ws.row), int(ws.col), nil
+}
+
+// winsize must correspond to the struct defined in "sys/ioctl.h". Do not
+// export this struct; it's a platform-specific implementation detail.
+type winsize struct {
+ row, col, xpixel, ypixel uint16
+}