[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
06/10: syscalls: Add TIOCGWINSZ bindings.
From: |
Ludovic Courtès |
Subject: |
06/10: syscalls: Add TIOCGWINSZ bindings. |
Date: |
Thu, 14 Apr 2016 22:32:45 +0000 |
civodul pushed a commit to branch master
in repository guix.
commit 29ff6d9fcc05b283b6d797146330e950286028ed
Author: Ludovic Courtès <address@hidden>
Date: Thu Apr 14 23:35:03 2016 +0200
syscalls: Add TIOCGWINSZ bindings.
* guix/build/syscalls.scm (TIOCGWINSZ): New macro.
(<window-size>): New record type.
(winsize): New C struct.
(winsize-struct): New variable.
(terminal-window-size, terminal-columns): New procedures.
---
guix/build/syscalls.scm | 74 ++++++++++++++++++++++++++++++++++++++++++++++-
tests/syscalls.scm | 13 ++++++++
2 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index 69a507d..ed833c1 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -82,7 +82,15 @@
interface-address
interface-netmask
interface-broadcast-address
- network-interfaces))
+ network-interfaces
+
+ window-size?
+ window-size-rows
+ window-size-columns
+ window-size-x-pixels
+ window-size-y-pixels
+ terminal-window-size
+ terminal-columns))
;;; Commentary:
;;;
@@ -853,4 +861,68 @@ network interface. This is implemented using the
'getifaddrs' libc function."
(let ((ptr (dynamic-func "freeifaddrs" (dynamic-link))))
(pointer->procedure void ptr '(*))))
+
+;;;
+;;; Terminals.
+;;;
+
+(define-syntax TIOCGWINSZ ;<asm-generic/ioctls.h>
+ (identifier-syntax #x5413))
+
+(define-record-type <window-size>
+ (window-size rows columns x-pixels y-pixels)
+ window-size?
+ (rows window-size-rows)
+ (columns window-size-columns)
+ (x-pixels window-size-x-pixels)
+ (y-pixels window-size-y-pixels))
+
+(define-c-struct winsize ;<bits/ioctl-types.h>
+ window-size
+ read-winsize
+ write-winsize!
+ (rows unsigned-short)
+ (columns unsigned-short)
+ (x-pixels unsigned-short)
+ (y-pixels unsigned-short))
+
+(define winsize-struct
+ (list unsigned-short unsigned-short unsigned-short unsigned-short))
+
+(define* (terminal-window-size #:optional (port (current-output-port)))
+ "Return a <window-size> structure describing the terminal at PORT, or raise
+a 'system-error' if PORT is not backed by a terminal. This procedure
+corresponds to the TIOCGWINSZ ioctl."
+ (let* ((size (make-c-struct winsize-struct '(0 0 0 0)))
+ (ret (%ioctl (fileno port) TIOCGWINSZ size))
+ (err (errno)))
+ (if (zero? ret)
+ (read-winsize (pointer->bytevector size (sizeof winsize-struct))
+ 0)
+ (throw 'system-error "terminal-window-size" "~A"
+ (list (strerror err))
+ (list err)))))
+
+(define* (terminal-columns #:optional (port (current-output-port)))
+ "Return the best approximation of the number of columns of the terminal at
+PORT, trying to guess a reasonable value if all else fails. The result is
+always a positive integer."
+ (define (fall-back)
+ (match (and=> (getenv "COLUMNS") string->number)
+ (#f 80)
+ ((? number? columns)
+ (if (> columns 0) columns 80))))
+
+ (catch 'system-error
+ (lambda ()
+ (match (window-size-columns (terminal-window-size port))
+ ;; Things like Emacs shell-mode return 0, which is unreasonable.
+ (0 (fall-back))
+ ((? number? columns) columns)))
+ (lambda args
+ (let ((errno (system-error-errno args)))
+ (if (= errno ENOTTY)
+ (fall-back)
+ (apply throw args))))))
+
;;; syscalls.scm ends here
diff --git a/tests/syscalls.scm b/tests/syscalls.scm
index 8e24184..1b443be 100644
--- a/tests/syscalls.scm
+++ b/tests/syscalls.scm
@@ -244,4 +244,17 @@
(#f #f)
(lo (interface-address lo)))))))
+(test-equal "terminal-window-size ENOTTY"
+ ENOTTY
+ (call-with-input-file "/dev/null"
+ (lambda (port)
+ (catch 'system-error
+ (lambda ()
+ (terminal-window-size port))
+ (lambda args
+ (system-error-errno args))))))
+
+(test-assert "terminal-columns"
+ (> (terminal-columns) 0))
+
(test-end)
- branch master updated (85c7e8e -> b0a6a97), Ludovic Courtès, 2016/04/14
- 04/10: download: Send an ANSI erase-in-line sequence in addition to CR., Ludovic Courtès, 2016/04/14
- 02/10: gnu-maintenance: Recognize source tarball with "-src" in their name., Ludovic Courtès, 2016/04/14
- 09/10: guix download: Honor the number of columns of the terminal., Ludovic Courtès, 2016/04/14
- 08/10: ui: Use 'terminal-columns'., Ludovic Courtès, 2016/04/14
- 05/10: download: Add 'current-terminal-columns' parameter., Ludovic Courtès, 2016/04/14
- 10/10: substitute: Honor the number of columns of the client terminal., Ludovic Courtès, 2016/04/14
- 07/10: ui: 'package->recutils' accurately honors the number of columns., Ludovic Courtès, 2016/04/14
- 03/10: gnu-maintenance: Move FTP directory info to 'properties' fields., Ludovic Courtès, 2016/04/14
- 06/10: syscalls: Add TIOCGWINSZ bindings.,
Ludovic Courtès <=
- 01/10: upstream: Pass a package object to updaters., Ludovic Courtès, 2016/04/14