on 3cb9cfc help sign in
CHANGELOG.md+420−726
since splitsnapshots
unifiedsplit
@@ -1,861 +1,555 @@
1
1
2−5.35.1
3−------
4−
5−Bug fixes:
6− * Fixed a build issue with a test program.
7−
8−5.35
9−----
10−
11−New features:
12− * Add support for 24-bit color (thanks @u-quark). This change
13− updates Vty to look at the `COLORTERM` environment variable that is
14− conventionally used to advertise support for truecolor escape
15− sequences. The change also updates the Vty demo to demonstrate
16− 24-bit colors. This change also adds a new data type, `ColorMode`,
17− to represent the color mode in use, as well as an `Output` interface
18− field, `outputColorMode`, to track the active color mode and use it
19− to clamp emitted color escape sequences to the active color range.
20−
21−API changes:
22− * All types in `Graphics.Vty.Input.Events` now have strict constructor
23− fields.
24− * Internal events are now wrapped in a new `InternalEvent` type to
25− improve how signal handling is done. This change modifies the `Input`
26− type's event channel API to produce `InternalEvents`, not `Events`.
27− The new `InternalEvent` either wraps `Event` with the `InputEvent`
28− constructor (the previous behavior) or indicates that Vty resumed
29− after handling a signal using the `ResumeAfterSignal` constructor.
30− This change avoids the previous use of `EvResize` with lazy exception
31− arguments as a sentinel value for `ResumeAfterSignal`.
32−
33−Other enhancements:
34− * Bracketed paste parsing performance has been greatly improved thanks
35− to benchmarking and optimization work by @iphydf. As part of that
36− work, Vty now uses bytestrings rather than Strings internally when
37− parsing input to look for events.
38− * The `\b` value is now interpreted as `KBS` (thanks @vglfr)
39−
40−5.34
41−----
42−
43−API changes:
44− * Added an `NFData` instance for `Event` (thanks Mario Lang)
45− * Removed `Monoid` and `Semigroup` instances for `Attr` and
46− `MaybeDefault`. This change removed the instances because they were
47− misbehaved; merging `Attr` and `MaybeDefault` values with these
48− instances resulted in field value losses. For example, before this
49− change,
50−```
51−(defAttr `withForeColor` blue) <> (defAttr `withBackColor` green)
52−```
53− would result in just
54−```
55− (defAttr `withBackColor` green)
56−```
57− because the instances were designed to favor the right-hand
58− arguments' fields even if they had not been explicitly set
59− (a consequence of the `MaybeDefault` `Semigroup` instance).
60− While that behavior was sensible specifically in the context of
61− `Graphics.Vty.Inline`, it wasn't a useful user-facing API and it made
62− for surprising instance behavior. Since there is actually no good way
63− to handle this in a `Semigroup` instance for `Attr` -- some choices
64− have to be made about how to merge two attributes' foreground colors,
65− and that won't be much better than what we had -- the instance was
66− just removed.
67−
68−
69−5.33
70−----
71−
72−API changes:
73−* The `Cursor` type got a new `PositionOnly` constructor for cursor
74− placement without visibility.
75−
76−Package changes:
77−* Relaxed upper bound for `random`
78−* Updated `microlens` bounds to allow 0.4.12
79−
80−Other improvements:
81−* Various hlint-driven improvements (thanks Willem Van Onsem)
82−* The implementation of `color240` was improved (thanks (Willem Van
83− Onsem)
84−
85−5.32
86−----
87−
88−New features:
89− * Meta-PageUp and Meta-PageDown are now supported (#193)
90− * Added `supportsItalics` and `supportsStrikethrough` functions to
91− check for feature support in terminfo
92−
93−Bug fixes:
94− * Detect utf-8 mode in `LANG` regardless of case (thanks Emeka
95− Nkurumeh)
96−
97−5.31
98−----
99−
100−New features and API changes:
101− * Added support for strikethrough mode. This change adds a new
102− `strikethrough` `Style` value and uses the `smxx` and `rmxx`
103− Terminfo capabilities to activate and deactivate strikethrough mode,
104− respectively. If the terminfo does not report those capabilities,
105− this style is ignored.
106− * `Output`: added the `setDisplayBounds` field to set the output
107− dimensions of the output handle; added an implementation of this for
108− the `TerminfoBased` backend.
109−
110−Other changes:
111− * The C prototype for `vty_c_get_window_size` in `gwinsz.h` was fixed.
112−
113−5.30
114−----
115−
116−New features:
117− * Added `Graphics.Vty.setWindowTitle` to emit an escape
118− sequence to set the window title, provide the terminal emulator
119− accepts Xterm-style title sequences. For details, see:
120− https://tldp.org/HOWTO/Xterm-Title-3.html
121−
122−5.29
123−----
124−
125−API changes:
126− * The Input type got a new field, 'restoreInputState'. This field
127− allows the end user to have direct access to the logic needed to
128− restore the terminal's input state flags. Prior to having this field,
129− this state restoration logic could only be invoked as part of calling
130− 'shutdownInput', but since that function does other things (like
131− killing threads) it is not advisable to call it repeatedly (which is
132− necessary in the use case this change is intended to support). This
133− can be called directly to restore the input state flags as needed,
134− although this is not required if 'shutdown' (or 'shutdownInput') is
135− called.
136−
137−Other changes:
138− * attributeControl: explicitly enable the ICRNL terminal mode flag (see
139− #187 and c572ad).
140−
141−5.28.2
142−------
143−
144−Bug fixes:
145− * Added a package dependency on `semigroups` for the
146− `vty-build-width-table` tool on older GHCs (#185)
147−
148−5.28.1
149−------
150−
151−Bug fixes:
152− * `installUnicodeWidthTable`: use `throwIO`, not `throw`
153−
154−5.28
155−----
156−
157−This release improves Vty's support for multi-column Unicode characters
158−and provides greater compatibility with a wider array of terminal
159−emulators. The following sections summarize the relevant changes, but an
160−overview of the new functionality is motivated and detailed in the new
161−"Multi-Column Character Support" README section. For
162−historical context, please also consider reading over
163−[#175](https://github.com/jtdaugherty/vty/issues/175).
164−
165−API changes:
166− * New modules were added:
167− * `Graphics.Vty.UnicodeWidthTable.Types`
168− * `Graphics.Vty.UnicodeWidthTable.IO`
169− * `Graphics.Vty.UnicodeWidthTable.Query`
170− * `Graphics.Vty.UnicodeWidthTable.Install`
171− * The `Config` type got a new field, `allowCustomUnicodeWidthTables`,
172− that controls whether `mkVty` will attempt to load a Unicode width
173− table if specified in the configuration.
174−
175−Configuration file changes:
176− * A new syntax was added to support specifying Unicode width tables on
177− a per-`TERM` basis. The syntax is `widthMap <TERM> <PATH>`. See the
178− documentation for `Graphics.Vty.Config` for details. Since prior
179− versions of this library will silently ignore any configuration file
180− lines they cannot parse, this change to user configuration files is
181− at least non-breaking for older versions of Vty.
182−
183−Other changes:
184− * The `mkVty` function now automatically attempts to load a custom
185− Unicode width table if one is specified in the configuration,
186− provided `allowCustomUnicodeWidthTables` is not set to `Just False`.
187− See the documentation for `Graphics.Vty.mkVty` for details.
188− * Vty now includes a command line tool, `vty-build-width-table`, that
189− queries the terminal emulator to construct a custom Unicode width
190− table and optionally update the Vty configuration file to use it.
191− Programs that want to use that tool's functionality may also do so
192− via the API exposed in the various modules listed above.
193−
1945.27
25.27
195−----
196−
197−* Added `Graphics.Vty.Config.getTtyEraseChar` to support querying the
3+ - Added Graphics.Vty.Config.getTtyEraseChar to support querying the
198− kernel for the current terminal's settings to obtain the character
4+ kernel for the current terminal's settings to obtain the character
199− assigned by the `stty erase` command. That can then be added to the
5+ assigned by the "stty erase" command. That can then be added to the
200− Vty configuration's input map to map to `KBS` (backspace) if desired.
6+ Vty configuration's input map to map to KBS (backspace) if desired.
201
7
2025.26
85.26
203−----
204−
205−* Resolved various import warnings (thanks @glguy)
9+ - Resolved various import warnings (thanks @glguy)
206−* Removed the `MonadIO` constraint from the Output type's fields and
10+ - Removed the MonadIO constraint from the Output type's fields and
207− removed `MonadFail` uses (PR #177, thanks @glguy)
11+ removed MonadFail uses (PR #177, thanks @glguy)
208−* Clarified documentation for ANSI colors (thanks Colby Jenn)
12+ - Clarified documentation for ANSI colors (thanks Colby Jenn)
209−* `Graphics.Vty.Attributes` no longer re-exports
13+ - Graphics.Vty.Attributes no longer re-exports
210− `Graphics.Vty.Attributes.Color`
14+ Graphics.Vty.Attributes.Color
211−* The `Graphics.Vty.Attributes.Color` module is now exposed (thanks
15+ - The Graphics.Vty.Attributes.Color module is now exposed (thanks Colby
212− Colby Jenn)
16+ Jenn)
213−* Raised upper bound for `microlens` to 0.4.12 (thanks Artyom Kazak)
17+ - Raised upper bound for microlens to 0.4.12 (thanks Artyom Kazak)
214−* Changed from using `System.Posix.Env.getEnv` to
18+ - Changed from using System.Posix.Env.getEnv to
215− `System.Environment.lookupEnv` (thanks Jonathan Osser)
19+ System.Environment.lookupEnv (thanks Jonathan Osser)
216−* Added `Graphics.Vty.Image` functions for dealing with character width
20+ - Added Graphics.Vty.Image functions for dealing with character width
217− computations on `Text` values instead of `Strings`:
21+ computations on Text values instead of Strings:
218− * `safeWctwidth`
22+ - safeWctwidth
219− * `safeWctlwidth`
23+ - safeWctlwidth
220− * `wctwidth`
24+ - wctwidth
221− * `wctlwidth`
25+ - wctlwidth
222
26
2235.25.1
275.25.1
224−------
225−
226−* Avoided a conflict with a Microlens 0.4.10 operator and added an
28+ - Avoided a conflict with a Microlens 0.4.10 operator and added an
227− upper bound on Microlens of 0.4.11.
29+ upper bound on Microlens of 0.4.11.
228
30
2295.25
315.25
230−----
231−
232−* The Vty type got a new field, isShutdown, that returns whether the
32+ - The Vty type got a new field, isShutdown, that returns whether the
233− Vty handle has had its 'shutdown' function called (thanks Ian
33+ Vty handle has had its 'shutdown' function called (thanks Ian
234− Jeffries)
34+ Jeffries)
235−* Vty's shutdown function is now thread-safe.
35+ - Vty's shutdown function is now thread-safe.
236
36
2375.24.1
375.24.1
238−------
239−
240−* The "shutdown" method of Vty handles is now idempotent (#159)
38+ - The "shutdown" method of Vty handles is now idempotent (#159)
241
39
2425.24
405.24
243−----
244−
245−* Add Generic and NFData instances for some types
41+ - Add Generic and NFData instances for some types
246−* Image: remove custom Show instance, add derived Show and Read
42+ - Image: remove custom Show instance, add derived Show and Read instances
247− instances
248−* Updated Travis build settings (thanks Eric Mertens)
43+ - Updated Travis build settings (thanks Eric Mertens)
249
44
2505.23.1
455.23.1
251−------
252−
253−* Fixed a bug where italics did not combine properly with other display
46+ - Fixed a bug where italics did not combine properly with other
254− modes (#155, thanks Eric Mertens)
47+ display modes (#155, thanks Eric Mertens)
255
48
2565.23
495.23
257−----
258−
259−* Added support for italicized output when terminfo supports it. This
50+ - Added support for italicized output when terminfo supports it. This
260− takes the form of a new Style, "italic". Note that most terminfo
51+ takes the form of a new Style, "italic". Note that most terminfo
261− descriptors do not report capabilities for italics, so support for
52+ descriptors do not report capabilities for italics, so support for
262− this will be very spotty.
53+ this will be very spotty.
263−* Updateed text/string function documentation to indicate that escapes
54+ - Updateed text/string function documentation to indicate that escapes
264− are not permitted in their inputs.
55+ are not permitted in their inputs.
265
56
2665.22
575.22
267−----
268−
269−* Added Graphics.Vty.Attributes.Color240.color240CodeToRGB function
58+ - Added Graphics.Vty.Attributes.Color240.color240CodeToRGB function
270− (thanks Brent Carmer)
59+ (thanks Brent Carmer)
271−* Added nextEventNonblocking function (field) to Vty type (#87)
60+ - Added nextEventNonblocking function (field) to Vty type (#87)
272
61
2735.21
625.21
274−----
275−
276−* Picture and Background now provide Eq instances (thanks Jaro Reinders)
63+ - Picture and Background now provide Eq instances (thanks Jaro Reinders)
277−* #145: vty builds with microlens 0.4.9 (thanks Daniel Wagner)
64+ - #145: vty builds with microlens 0.4.9 (thanks Daniel Wagner)
278−* #142: note requirement of threaded RTS
65+ - #142: note requirement of threaded RTS
279
66
2805.20
675.20
281−----
282−
283API changes:
68API changes:
284−* Split up Monoid instances into Monoid and Semigroup for newer GHCs
69+ - Split up Monoid instances into Monoid and Semigroup for newer GHCs
285− (thanks Ryan Scott)
70+ (thanks Ryan Scott)
286
71
2875.19.1
725.19.1
288−------
289−
290API changes:
73API changes:
291−* Cursor now provides an Eq instance (thanks Jaro Reinders)
74+ * Cursor now provides an Eq instance (thanks Jaro Reinders)
292
75
2935.19
765.19
294−----
295−
296API changes:
77API changes:
297−* URL hyperlinking (via 'withURL') is now optional and disabled by
78+ - URL hyperlinking (via 'withURL') is now optional and disabled by
298− default due to poor support on some common terminals. A new 'Mode'
79+ default due to poor support on some common terminals. A new 'Mode'
299− constructor, 'Hyperlink', has been added to enable this feature. To
80+ constructor, 'Hyperlink', has been added to enable this feature. To
300− change the hyperlinking mode, use 'setMode' on the 'outputIface' of a
81+ change the hyperlinking mode, use 'setMode' on the 'outputIface' of a
301− Vty handle.
82+ Vty handle.
302
83
3035.18.1
845.18.1
304−------
305−
306Bug fixes:
85Bug fixes:
307−* Reset the hyperlink state on line endings to avoid run-on hyperlinks
86+ - Reset the hyperlink state on line endings to avoid run-on hyperlinks
308
87
3095.18
885.18
310−----
311−
312API changes:
89API changes:
313−* Added support for hyperlinking attributes (thanks Getty Ritter). This
90+ - Added support for hyperlinking attributes (thanks Getty Ritter). This
314− change adds a new Attr field for containing the hyperlink to apply,
91+ change adds a new Attr field for containing the hyperlink to apply,
315− as per https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
92+ as per https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
316
93
3175.17.1
945.17.1
318−------
319−
320−* withStyle now ignores zero arguments, leaving attribute styles
95+ - withStyle now ignores zero arguments, leaving attribute styles
321− untouched if the input style is the null style
96+ untouched if the input style is the null style
322
97
3235.17
985.17
324−----
325−
326API changes:
99API changes:
327−* Add support for terminal focus events. This change adds a new mode
100+ - Add support for terminal focus events. This change adds a new mode
328− usable with setMode, Focus, that requests that the terminal send
101+ usable with setMode, Focus, that requests that the terminal send
329− events on focus lose/gain. This change also adds two new Event
102+ events on focus lose/gain. This change also adds two new Event
330− constructors, EvLostFocus and EvGainedFocus.
103+ constructors, EvLostFocus and EvGainedFocus.
331−* No longer enable UTF8 mouse event encoding. This encoding was not
104+ - No longer enable UTF8 mouse event encoding. This encoding was not
332− working properly with Terminal.app, and using the other modes (SGR,
105+ working properly with Terminal.app, and using the other modes (SGR,
333− etc.) work.
106+ etc.) work.
334−* Graphics.Vty.Attributes: escape backticks in Haddock comment (fixes
107+ - Graphics.Vty.Attributes: escape backticks in Haddock comment (fixes
335− #131)
108+ #131)
336
109
3375.16
1105.16
338−----
339−
340API changes:
111API changes:
341−* Added support for mouse wheel events while in mouse mode. The Button
112+ - Added support for mouse wheel events while in mouse mode. The Button
342− type got two new constructors as a result: BScrollUp and BScrollDown.
113+ type got two new constructors as a result: BScrollUp and BScrollDown.
343− Thanks to doublescale@tutanota.com for this contribution!
114+ Thanks to doublescale@tutanota.com for this contribution!
344
115
345Bug fixes:
116Bug fixes:
346−* charFill now clamps negative arguments to zero (thanks Eric Mertens!)
117+ - charFill now clamps negative arguments to zero (thanks Eric
118+ Mertens!)
347
119
3485.15.1
1205.15.1
349−------
350−
351Package changes:
121Package changes:
352−* Documentation files are now marked accordingly (thanks Michal
122+ - Documentation files are now marked accordingly (thanks Michal
353− Suchánek)
123+ Suchánek)
354
124
355Bug fixes:
125Bug fixes:
356−* translateX/Y: fix negative translations
126+ - translateX/Y: fix negative translations
357
127
3585.15
1285.15
359−----
360−
361Package changes:
129Package changes:
362−* Discontinued support for GHC versions prior to 7.10.1.
130+ - Discontinued support for GHC versions prior to 7.10.1.
363−* Removed instructions and configuration for Stack builds since they
131+ - Removed instructions and configuration for Stack builds since they
364− are no longer supported.
132+ are no longer supported.
365−* Clarified README mention of (lack of) Windows support (contributors
133+ - Clarified README mention of (lack of) Windows support (contributors
366− wanted, though!)
134+ wanted, though!)
367−* Removed dependency on data-default (see below).
135+ - Removed dependency on data-default (see below).
368
136
369API changes:
137API changes:
370−* Moved color definitions from Attributes to Color module.
138+ - Moved color definitions from Attributes to Color module.
371−* In lieu of data-default (Default) instances for Attr and Config, use
139+ - In lieu of data-default (Default) instances for Attr and Config, use
372− 'defAttr' and the new 'defaultConfig' (or 'mempty') instead of 'def'.
140+ 'defAttr' and the new 'defaultConfig' (or 'mempty') instead of 'def'.
373−* Graphics.Vty.Output no longer re-exports
141+ - Graphics.Vty.Output no longer re-exports
374− Graphics.Vty.Output.Interface.
142+ Graphics.Vty.Output.Interface.
375−* Removed Graphics.Vty.Prelude module and moved DisplayRegion and its
143+ - Removed Graphics.Vty.Prelude module and moved DisplayRegion and its
376− accessors to Graphics.Vty.Image.
144+ accessors to Graphics.Vty.Image.
377−* Graphics.Vty.Image no longer re-exports Graphics.Vty.Attributes.
145+ - Graphics.Vty.Image no longer re-exports Graphics.Vty.Attributes.
378−* Graphics.Vty.Picture no longer re-exports Graphics.Vty.Image.
146+ - Graphics.Vty.Picture no longer re-exports Graphics.Vty.Image.
379
147
3805.14
1485.14
381−----
382−
383−* addMaybeClippedJoin: instead of raising an exception when the join
149+ - addMaybeClippedJoin: instead of raising an exception when the join
384− is totally clipped, just reduce the clip amount and continue
150+ is totally clipped, just reduce the clip amount and continue
385−* addMaybeClipped: skip blit of joins when their primary dimension is
151+ - addMaybeClipped: skip blit of joins when their primary dimension is
386− zero
152+ zero
387−* 'string' and related text functions no longer treat an empty string
153+ - 'string' and related text functions no longer treat an empty string
388− as an empty image (thanks Chris Penner). This means that now it is
154+ as an empty image (thanks Chris Penner). This means that now it is
389− possible to use 'str ""' as a non-empty image with height 1.
155+ possible to use 'str ""' as a non-empty image with height 1.
390
156
3915.13
1575.13
392−----
393−
394−* Reverted changes in 5.12 due to disagreements between terminal
158+ - Reverted changes in 5.12 due to disagreements between terminal
395− emulators and utf8proc; for more details, please see the ticket
159+ emulators and utf8proc; for more details, please see the ticket
396− discussion at
160+ discussion at
397− https://github.com/coreyoconnor/vty/issues/115
161+ https://github.com/coreyoconnor/vty/issues/115
398
162
3995.12
1635.12
400−----
401−
402−* Replaced 'wcwidth' with a call to the utf8proc library's character
164+ - Replaced 'wcwidth' with a call to the utf8proc library's character
403− width function, which is much more up to date (by several Unicode
165+ width function, which is much more up to date (by several Unicode
404− versions) and returns the right width for a much larger set of
166+ versions) and returns the right width for a much larger set of
405− characters.
167+ characters.
406−* Added a bundled version of the utf8proc C library.
168+ - Added a bundled version of the utf8proc C library.
407
169
4085.11.3
1705.11.3
409−------
410−
411−* Fix mouse event offsets in mouse-up events
171+ - Fix mouse event offsets in mouse-up events
412
172
4135.11.2
1735.11.2
414−------
415−
416−* Mouse events were modified so that the upper-left corner of the window
174+ - Mouse events were modified so that the upper-left corner of the
417− is (0,0) rather than (1,1).
175+ window is (0,0) rather than (1,1).
418
176
4195.11.1
1775.11.1
420−------
421−
422−* Add Generic instance for Image
178+ - Add Generic instance for Image
423−* nextEvent: stop trying to refresh on a resize event (fixes segfault
179+ - nextEvent: stop trying to refresh on a resize event (fixes segfault
424− on refresh with normal cursor positioning mode)
180+ on refresh with normal cursor positioning mode)
425−* Remove redundant clause from clipForCharWidth (thanks Eric Mertens)
181+ - Remove redundant clause from clipForCharWidth (thanks Eric Mertens)
426−* Update maintainer
182+ - Update maintainer
427
183
4285.11
1845.11
429−----
430−
431−* Vty now raises a VtyConfigurationError exception when the TERM
185+ - Vty now raises a VtyConfigurationError exception when the TERM
432− evironment variable is missing (thanks Eric Mertens)
186+ evironment variable is missing (thanks Eric Mertens)
433−* Graphics.Vty.Config got an explicit export list to avoid accidentally
187+ - Graphics.Vty.Config got an explicit export list to avoid accidentally
434− exporting internal types (thanks Eric Mertens)
188+ exporting internal types (thanks Eric Mertens)
435
189
4365.10
1905.10
437−----
438−
439−* Add absolute cursor positioning mode AbsoluteCursor to Cursor. This
191+ - Add absolute cursor positioning mode AbsoluteCursor to Cursor. This
440− mode provides greater control over cursor positioning by bypassing
192+ mode provides greater control over cursor positioning by bypassing
441− the logical positioning provided by default. Rather than positioning
193+ the logical positioning provided by default. Rather than positioning
442− the cursor by looking at the widths of characters involved, this
194+ the cursor by looking at the widths of characters involved, this
443− constructor lets you provide a physical row and column instead. This
195+ constructor lets you provide a physical row and column instead. This
444− is useful in more sophisticated programs. (thanks Eric Mertens)
196+ is useful in more sophisticated programs. (thanks Eric Mertens)
445−* Added a new Generic-derived config parser (thanks Eric Mertens)
197+ - Added a new Generic-derived config parser (thanks Eric Mertens)
446−* Fixed the MShift case in the configuration file parser (thanks Eric
198+ - Fixed the MShift case in the configuration file parser (thanks Eric
447− Mertens)
199+ Mertens)
448−* Fixed wcwidth import and matched safeWcswidth to its documented
200+ - Fixed wcwidth import and matched safeWcswidth to its documented
449− behavior. Previously vty_mk_wcwidth was being imported with the
201+ behavior. Previously vty_mk_wcwidth was being imported with
450− wrong type causing the -1 return value to be mapped to the wrong Int
202+ the wrong type causing the -1 return value to be mapped to the
451− value. Additionally safeWcswidth was using the unsafe character width
203+ wrong Int value. Additionally safeWcswidth was using the unsafe
452− function and only ensuring that the final result was non-negative.
204+ character width function and only ensuring that the final result was
453− (thanks Eric Mertens)
205+ non-negative. (thanks Eric Mertens)
454
206
4555.9.1
2075.9.1
456−-----
457−
458−* Vty now only emits UTF8 charset sequences in terminals without a
208+ - Vty now only emits UTF8 charset sequences in terminals without a
459− preexisting UTF8 declaration to avoid emitting garbage sequences
209+ preexisting UTF8 declaration to avoid emitting garbage sequences
460− (fixes #89)
210+ (fixes #89)
461
211
4625.9
2125.9
463−---
464−
465−* Added new Output methods supportsBell and ringTerminalBell to find out
213+ - Added new Output methods supportsBell and ringTerminalBell to find
466− whether the output device has an audio bell and to ring it (see #102)
214+ out whether the output device has an audio bell and to ring it (see
215+ #102)
467
216
4685.8.1
2175.8.1
469−-----
470−
471−* Fixed "refresh" to work as advertised (see #104)
218+ - Fixed "refresh" to work as advertised (see #104)
472
219
4735.8
2205.8
474−---
475−
476−* API change: EvPaste input event now provides paste data as a raw
221+ - API change: EvPaste input event now provides paste data as a raw
477− ByteString rather than a String to allow the application to decode how
222+ ByteString rather than a String to allow the application to decode
478− best to decode it
223+ how best to decode it
479
224
4805.7.1
2255.7.1
481−-----
482−
483−* ModeDemo: added an explicit Control.Applicative import for older GHCs
226+ - ModeDemo: added an explicit Control.Applicative import for older
227+ GHCs
484
228
4855.7
2295.7
486−---
487−
488−* Mouse and paste modes are now off by default.
230+ - Mouse and paste modes are now off by default.
489−* The Config type got new fields: mouseMode and bracketedPasteMode.
231+ - The Config type got new fields: mouseMode and bracketedPasteMode.
490− These determine whether these modes are enabled initially (for
232+ These determine whether these modes are enabled initially (for
491− terminals that support them).
233+ terminals that support them).
492−* Added a Mode type for modal terminal features (mouse events,
234+ - Added a Mode type for modal terminal features (mouse events,
493− bracketed paste mode) that is used with new Output interface
235+ bracketed paste mode) that is used with new Output interface
494− functions:
236+ functions:
495− * supportsMode :: Mode -> Bool tells whether the device supports a
237+ * supportsMode :: Mode -> Bool tells whether the device supports a
496− mode
238+ mode
497− * setMode :: Mode -> Bool -> IO () turns a mode on or off
239+ * setMode :: Mode -> Bool -> IO () turns a mode on or off
498− * getModeStatus :: Mode -> IO Bool tells you whether a mode is on or
240+ * getModeStatus :: Mode -> IO Bool tells you whether a mode is on or
499− off
241+ off
500−* Added a new demo program, ModeDemo.hs, to demonstrate usage of modes
242+ - Added a new demo program, ModeDemo.hs, to demonstrate usage of modes
501
243
5025.6
2445.6
503−---
504−
505−* Added support for normal and extended mouse modes in Xterm-like
245+ - Added support for normal and extended mouse modes in Xterm-like
506− terminals via the MouseDown and MouseUp Event constructors
246+ terminals via the MouseDown and MouseUp Event constructors
507−* Added support for bracketed paste mode in Xterm-like terminals via
247+ - Added support for bracketed paste mode in Xterm-like terminals via
508− the EvPaste event constructor
248+ the EvPaste event constructor
509−* Added derived Show instances for Event and Button (thanks Felix
249+ - Added derived Show instances for Event and Button (thanks Felix
510− Hirn)
250+ Hirn)
511−* Now TERM values containing "screen" will automatically use the
251+ - Now TERM values containing "screen" will automatically use the
512− XtermColor driver rather than just TerminfoBased
252+ XtermColor driver rather than just TerminfoBased
513
253
5145.5.0
2545.5.0
515−-----
516−
517−* Replaced lens dependency with microlens, microlens-mtl, microlens-th
255+ - Replaced lens dependency with microlens, microlens-mtl, microlens-th
518− dependencies. Issue #90
256+ dependencies. Issue #90
519− * Thanks Jonathan Daugherty
257+ - Thanks Jonathan Daugherty
520−* Cabal corrections.
258+ - Cabal corrections.
521− * Thanks Lennart Spitzner
259+ - Thanks Lennart Spitzner
522
260
5235.4.0
2615.4.0
524−-----
525−
526−* Changed eventChannel of Graphics.Vty.Input from Chan to
262+ - Changed eventChannel of Graphics.Vty.Input from Chan to TChan.
527− TChan. This enables clients to query if there are no pending
263+ This enables clients to query if there are no pending events. The
528− events. The Graphics.Vty interface nextEvent is unchanged.
264+ Graphics.Vty interface nextEvent is unchanged. Clients that use
529− Clients that use eventChannel directly will require updating.
265+ eventChannel directly will require updating.
530− https://github.com/coreyoconnor/vty/issues/60
266+ https://github.com/coreyoconnor/vty/issues/60
531−
5325.3.1
2675.3.1
533−-----
534−
535−* Reverted cabal file to depend on Cabal >= 1.18 instead of 1.20 due to
268+ - Reverted cabal file to depend on Cabal >= 1.18 instead of 1.20 due
536− possibly breaking this on reasonable GHC versions
269+ to possibly breaking this on reasonable GHC versions
537
270
5385.3
2715.3
539−---
540−
541−* Upgraded QuickCheck dependency to 2.7
272+ - Upgraded QuickCheck dependency to 2.7
542−* The standard IO Config (standardIOConfig) was overriding any provided
273+ - The standard IO Config (standardIOConfig) was overriding any
543− application config. In addition, the inputFd and outputFd could not be
274+ provided application config. In addition, the inputFd and outputFd
544− changed if mkVty was used. Fixed.
275+ could not be changed if mkVty was used. Fixed.
545−* Correct handling of display attributes at end of line. The output
276+ - Correct handling of display attributes at end of line. The output
546− attributes are set to default at the end of content for the line and
277+ attributes are set to default at the end of content for the line and
547− at the start of a new line. Previously the current attribute would
278+ at the start of a new line. Previously the current attribute would
548− extend to the next start of content. This was odd to reason about and
279+ extend to the next start of content. This was odd to reason about
549− was the cause of https://github.com/coreyoconnor/vty/issues/76 IIRC Yi
280+ and was the cause of https://github.com/coreyoconnor/vty/issues/76
550− requires the old behavior to display the selection region correctly.
281+ IIRC Yi requires the old behavior to display the selection region
282+ correctly.
551−* shutdown of the input thread is now performed using killThread and
283+ - shutdown of the input thread is now performed using killThread and
552− synchronization on an MVar. For correct handling of the terminal read
284+ synchronization on an MVar. For correct handling of the terminal
553− vmin and vtime the read must be a blocking read on an OS thread.
285+ read vmin and vtime the read must be a blocking read on an OS
554− This places a threadWaitRead, which will be interrupted by the
286+ thread. This places a threadWaitRead, which will be interrupted by
555− killThread, prior to the uninterruptable read. An alternative would be
287+ the killThread, prior to the uninterruptable read. An alternative
556− to re-import the read foreign call as interruptable.
288+ would be to re-import the read foreign call as interruptable.
557
289
5585.2.11
2905.2.11
559−------
560−
561−* deepseq bounds increased for tests.
291+ - deepseq bounds increased for tests.
562−* Clean up warnings when compiling on 7.10
292+ - Clean up warnings when compiling on 7.10
563− * Thanks Eric Mertens
293+ - Thanks Eric Mertens
564−* Avoid discarding input bytes after multi-byte encoded codepoint
294+ - Avoid discarding input bytes after multi-byte encoded codepoint
565− * Thanks Eric Mertens
295+ - Thanks Eric Mertens
566
296
5675.2.10
2975.2.10
568−------
569−
570−* "str" now returns EmptyImage for empty strings to match behavior of
298+ - "str" now returns EmptyImage for empty strings to match behavior of
571− other string-like Image constructors (fixes #74)
299+ other string-like Image constructors (fixes #74)
572− * Thanks Jonathan Daugherty
300+ - Thanks Jonathan Daugherty
573
301
5745.2.9
3025.2.9
575−-----
576−
577−* dependency version bumps
303+ - dependency version bumps
578− * https://github.com/coreyoconnor/vty/pull/71
304+ - https://github.com/coreyoconnor/vty/pull/71
579− * https://github.com/coreyoconnor/vty/pull/70
305+ - https://github.com/coreyoconnor/vty/pull/70
580−* Correct/Simplify the example code
306+ - Correct/Simplify the example code
581− * Thanks glguy
307+ - Thanks glguy
582− * https://github.com/coreyoconnor/vty/pull/69
308+ - https://github.com/coreyoconnor/vty/pull/69
583
309
5845.2.8
3105.2.8
585−-----
586−
587−* blaze-builder, lens, utf8-string version constraint bump
311+ - blaze-builder, lens, utf8-string version constraint bump
588− * Thanks glguy
312+ - Thanks glguy
589− * https://github.com/coreyoconnor/vty/pull/67
313+ - https://github.com/coreyoconnor/vty/pull/67
590−* Do not differentiate based on TERM_PROGRAM
314+ - Do not differentiate based on TERM_PROGRAM
591− * https://github.com/coreyoconnor/vty/issues/68
315+ - https://github.com/coreyoconnor/vty/issues/68
592
316
5935.2.7
3175.2.7
594−-----
595−
596−* lens and deepseq constraint bump + misc
318+ - lens and deepseq constraint bump + misc
597− * Thanks ethercrow
319+ - Thanks ethercrow
598− * https://github.com/coreyoconnor/vty/pull/66
320+ - https://github.com/coreyoconnor/vty/pull/66
599
321
6005.2.6
3225.2.6
601−-----
602−
603−* lens constraint bump
323+ - lens constraint bump
604− * Thanks alexander-b!
324+ - Thanks alexander-b!
605− * https://github.com/coreyoconnor/vty/pull/64
325+ - https://github.com/coreyoconnor/vty/pull/64
606
326
6075.2.5
3275.2.5
608−-----
609−
610−* lens and random version constraint bump.
328+ - lens and random version constraint bump.
611− * Thanks RyanGlScott!
329+ - Thanks RyanGlScott!
612− * https://github.com/coreyoconnor/vty/pull/62
330+ - https://github.com/coreyoconnor/vty/pull/62
613
331
6145.2.4
3325.2.4
615−-----
616−
617−* removed -fpic from cc-options. No longer required.
333+ - removed -fpic from cc-options. No longer required.
618− * https://github.com/coreyoconnor/vty/issues/61
334+ - https://github.com/coreyoconnor/vty/issues/61
619− * https://ghc.haskell.org/trac/ghc/ticket/9657
335+ - https://ghc.haskell.org/trac/ghc/ticket/9657
620− * Thanks Fuuzetsu!
336+ - Thanks Fuuzetsu!
621
337
6225.2.3
3385.2.3
623−-----
624−
625−* evaluate/compile the input parsing table once instead of each
339+ - evaluate/compile the input parsing table once instead of each
626− keystroke.
340+ keystroke.
627− * https://github.com/coreyoconnor/vty/pull/59
341+ - https://github.com/coreyoconnor/vty/pull/59
628− * Thanks ethercrow!
342+ - Thanks ethercrow!
629
343
6305.2.2
3445.2.2
631−-----
632−
633−* When looking at input for an event, don't look too deep.
345+ - When looking at input for an event, don't look too deep.
634− * https://github.com/coreyoconnor/vty/pull/57
346+ - https://github.com/coreyoconnor/vty/pull/57
635− * Thanks ethercrow!
347+ - Thanks ethercrow!
636
348
6375.2.1
3495.2.1
638−-----
639−
640−* Bump upper version bound for lens to 4.5. Thanks markus1189!
350+ - Bump upper version bound for lens to 4.5. Thanks markus1189!
641
351
6425.2.0
3525.2.0
643−-----
644−
645−* Config structure now specifies file descriptor to use. The default
353+ - Config structure now specifies file descriptor to use. The default
646− is stdInput and stdOutput file descriptors. Previously Vty used
354+ is stdInput and stdOutput file descriptors. Previously Vty used
647− stdInput for input and the follow code for output:
355+ stdInput for input and the follow code for output:
648− * hDuplicate stdout >>= handleToFd >>= (`hSetBuffering`
356+ - hDuplicate stdout >>= handleToFd >>= (`hSetBuffering`
649− NoBuffering)
357+ NoBuffering)
650− * the difference was required by Vty.Inline. Now, Vty.Inline uses
358+ - the difference was required by Vty.Inline. Now, Vty.Inline uses
651− the Config structure options to acheive the same effect.
359+ the Config structure options to acheive the same effect.
652−* removed: derivedVtime, derivedVmin, inputForCurrentTerminal,
360+ - removed: derivedVtime, derivedVmin, inputForCurrentTerminal,
653− inputForNameAndIO, outputForCurrentTerminal, outputForNameAndIO
361+ inputForNameAndIO, outputForCurrentTerminal, outputForNameAndIO
654−* added: inputForConfig, outputForConfig
362+ - added: inputForConfig, outputForConfig
655−* updates to vty-rogue from jtdaugherty. Thanks!
363+ - updates to vty-rogue from jtdaugherty. Thanks!
656−* the oldest version of GHC tested to support vty is 7.6.2.
364+ - the oldest version of GHC tested to support vty is 7.6.2.
657−* the oldest version of GHC that vty compiles under is 7.4.2
365+ - the oldest version of GHC that vty compiles under is 7.4.2
658
366
6595.1.4
3675.1.4
660−-----
661−
662−* merged https://github.com/coreyoconnor/vty/pull/51 thanks trofi!
368+ - merged https://github.com/coreyoconnor/vty/pull/51 thanks trofi!
663
369
6645.1.1
3705.1.1
665−-----
666−
667−* merged https://github.com/coreyoconnor/vty/pull/48 thanks sjmielke!
371+ - merged https://github.com/coreyoconnor/vty/pull/48 thanks sjmielke!
668−* jtdaugherty resolved a number of compiler warnings. Thanks!
372+ - jtdaugherty resolved a number of compiler warnings. Thanks!
669
373
6705.1.0
3745.1.0
671−-----
672−
673−* vmin and vtime can be specified however the application requires.
375+ - vmin and vtime can be specified however the application requires.
674− See Graphics.Vty.Config.
376+ See Graphics.Vty.Config.
675−* fixed the processing of input when vmin is set > 1.
377+ - fixed the processing of input when vmin is set > 1.
676
378
6775.0.0
3795.0.0
678−-----
679−
680−* The naming convention now matches:
380+ - The naming convention now matches:
681− * http://www.haskell.org/haskellwiki/Programming_guidelines#Naming_Conventions
381+ - http://www.haskell.org/haskellwiki/Programming_guidelines#Naming_Conventions
682−* all projects using vty for input must be compiled with -threaded.
382+ - all projects using vty for input must be compiled with -threaded.
683− Please notify vty author if this is not acceptable.
383+ Please notify vty author if this is not acceptable.
684−* mkVtyEscDelay has been removed. Use "mkVty def". Which initialized
384+ - mkVtyEscDelay has been removed. Use "mkVty def". Which initialized
685− vty with the default configuration.
385+ vty with the default configuration.
686−* input handling changes
386+ - input handling changes
687− * KASCII is now KChar
387+ - KASCII is now KChar
688− * KPN5 is now KCenter
388+ - KPN5 is now KCenter
689− * tests exist.
389+ - tests exist.
690− * Applications can add to the input tables by setting inputMap of
390+ - Applications can add to the input tables by setting inputMap of
691− the Config. See Graphics.Vty.Config
391+ the Config. See Graphics.Vty.Config
692− * Users can define input table extensions that will apply to all vty
392+ - Users can define input table extensions that will apply to all vty
693− applications. See Graphics.Vty.Config
393+ applications. See Graphics.Vty.Config
694− * terminal timing is now handled by selecting an appropriate VTIME.
394+ - terminal timing is now handled by selecting an appropriate VTIME.
695− Previously this was implemented within Vty itself. This reduced
395+ Previously this was implemented within Vty itself. This reduced
696− complexity in vty but provides a different meta key behavior and
396+ complexity in vty but provides a different meta key behavior and
697− implies a requirement on -threaded.
397+ implies a requirement on -threaded.
698− * The time vty will wait to verify an ESC byte means a single ESC
398+ - The time vty will wait to verify an ESC byte means a single ESC
699− key is the singleEscPeriod of the Input Config structure.
399+ key is the singleEscPeriod of the Input Config structure.
700−* removed the typeclass based terminal and display context interface
400+ - removed the typeclass based terminal and display context interface
701− in favor of a data structure of properties interface.
401+ in favor of a data structure of properties interface.
702−* renamed the Terminal interface to Output
402+ - renamed the Terminal interface to Output
703−* The default picture for an image now uses the "clear" background.
403+ - The default picture for an image now uses the "clear" background.
704− This background fills background spans with spaces or just ends the
404+ This background fills background spans with spaces or just ends the
705− line.
405+ line.
706− * Previously the background defaulted to the space character. This
406+ - Previously the background defaulted to the space character. This
707− causes issues copying text from a text editor. The text would end
407+ causes issues copying text from a text editor. The text would end
708− up with extra spaces at the end of the line.
408+ up with extra spaces at the end of the line.
709−* Layer support
409+ - Layer support
710− * Each layer is an image.
410+ - Each layer is an image.
711− * The layers for a picture are a list of images.
411+ - The layers for a picture are a list of images.
712− * The first image is the top-most layer. The images are ordered from
412+ - The first image is the top-most layer. The images are ordered from
713− top to bottom.
413+ top to bottom.
714− * The transparent areas for a layer are the backgroundFill areas.
414+ - The transparent areas for a layer are the backgroundFill areas.
715− backgroundFill is added to pad images when images of different
415+ backgroundFill is added to pad images when images of different
716− sizes are joined.
416+ sizes are joined.
717− * If the background is clear there is no background layer.
417+ - If the background is clear there is no background layer.
718− * If there is a background character then the bottom layer is the
418+ - If there is a background character then the bottom layer is the
719− background layer.
419+ background layer.
720− * emptyPicture is a Picture with no layers and no cursor
420+ - emptyPicture is a Picture with no layers and no cursor
721− * addToTop and addToBottom add a layer to the top and bottom of the
421+ - addToTop and addToBottom add a layer to the top and bottom of the
722− given Picture.
422+ given Picture.
723−* compatibility improvements:
423+ - compatibility improvements:
724− * terminfo based terminals with no cursor support are silently
424+ - terminfo based terminals with no cursor support are silently
725− accepted. The cursor visibility changes in the Picture will have
425+ accepted. The cursor visibility changes in the Picture will have
726− no effect.
426+ no effect.
727− * alternate (setf/setb) color maps supported. Though colors beyond
427+ - alternate (setf/setb) color maps supported. Though colors beyond
728− the first 8 are just a guess.
428+ the first 8 are just a guess.
729− * added "rgbColor" for easy support of RGB specified colors.
429+ - added "rgbColor" for easy support of RGB specified colors.
730− * Both applications and users can add to the mapping used to
430+ - Both applications and users can add to the mapping used to
731− translate from input bytes to events.
431+ translate from input bytes to events.
732−* Additional information about input and output process can be
432+ - Additional information about input and output process can be
733− appended to a debug log
433+ appended to a debug log
734− * Set environment variable VTY_DEBUG_LOG to path of debug log
434+ - Set environment variable VTY_DEBUG_LOG to path of debug log
735− * Or use "debugLog <path>" config directive
435+ - Or use "debugLog <path>" config directive
736− * Or set 'debugLog' property of the Config provided to mkVty.
436+ - Or set 'debugLog' property of the Config provided to mkVty.
737−* examples moved to vty-examples package. See test directory for cabal
437+ - examples moved to vty-examples package. See test directory for cabal
738− file.
438+ file.
739− * vty-interactive-terminal-test
439+ - vty-interactive-terminal-test
740− * interactive test. Useful for building a bug report for vty's
440+ - interactive test. Useful for building a bug report for vty's
741− author.
441+ author.
742− * test/interactive_terminal_test.hs
442+ - test/interactive_terminal_test.hs
743− * vty-event-echo
443+ - vty-event-echo
744− * view a input event log for vty. Example of interacting with
444+ - view a input event log for vty. Example of interacting with
745− user.
445+ user.
746− * test/EventEcho.hs
446+ - test/EventEcho.hs
747− * vty-rogue
447+ - vty-rogue
748− * The start of a rogue-like game. Example of layers and image
448+ - The start of a rogue-like game. Example of layers and image
749− build operations.
449+ build operations.
750− * test/Rogue.hs
450+ - test/Rogue.hs
751− * vty-benchmark
451+ - vty-benchmark
752− * benchmarks vty. A series of tests that push random pictures to
452+ - benchmarks vty. A series of tests that push random pictures to
753− the terminal. The random pictures are generated using
453+ the terminal. The random pictures are generated using
754− QuickCheck. The same generators used in the automated tests.
454+ QuickCheck. The same generators used in the automated tests.
755− * test/benchmark.hs
455+ - test/benchmark.hs
756
456
7574.7.0.0
4574.7.0.0
758−-------
458+ - API changes:
459+ - Added Graphics.Vty.Image.crop: Ensure an image is no larger
460+ than the specified size.
461+ - Added Graphics.Vty.Image.pad: Ensure an image is no smaller
462+ than the specified size.
463+ - Added Graphics.Vty.Image.translate: Offset an image.
464+ - Thanks Ben Boeckel <MathStuf@gmail.com> for these features.
759
465
760−API changes:
466+4.3.0.0
761−* Added Graphics.Vty.Image.crop: Ensure an image is no larger
762− than the specified size.
763−* Added Graphics.Vty.Image.pad: Ensure an image is no smaller
764− than the specified size.
765−* Added Graphics.Vty.Image.translate: Offset an image.
766−* Thanks Ben Boeckel <MathStuf@gmail.com> for these features.
767
467
7684.2.1.0
4684.2.1.0
769−-------
770−
771−API changes:
469+ - API changes:
772−* Attr record accessor fore_color changed to attr_fore_color
470+ - Attr record accessor fore_color changed to attr_fore_color
773−* Attr record accessor back_color changed to attr_back_color
471+ - Attr record accessor back_color changed to attr_back_color
774−* Attr record accessor style changed to attr_style
472+ - Attr record accessor style changed to attr_style
775−* Added an "inline" display attribute changing DSL:
473+ - Added an "inline" display attribute changing DSL:
776− * put_attr_change applies a display attribute change
474+ - put_attr_change applies a display attribute change
777− immediately to a terminal
475+ immediately to a terminal
778− * For instance, can be used to change the display attrbiutes
476+ - For instance, can be used to change the display attrbiutes
779− of text output via putStrLn and putStr. EX:
477+ of text output via putStrLn and putStr. EX:
780− "put_attr_change $ back_color red" will set the background
478+ "put_attr_change $ back_color red" will set the background
781− color to red.
479+ color to red.
782− * Changes do not apply to a Picture output via output_picture.
480+ - Changes do not apply to a Picture output via output_picture.
783− * See Graphics.Vty.Inline
481+ - See Graphics.Vty.Inline
784−* Moved all IO actions into any monad an instance of MonadIO
482+ - Moved all IO actions into any monad an instance of MonadIO
785
483
7864.0.0.1
4844.0.0.1
787−-------
788−
789−* binding for mk_wcswidth was incorrect. Most platforms just
485+ - binding for mk_wcswidth was incorrect. Most platforms just
790− magically worked due to coincidence.
486+ magically worked due to coincidence.
791
487
7924.0.0
4884.0.0
793−-----
794−
795−API changes:
489+ - API changes:
796−* "getSize" has been removed. Use "terminal vty >>= display_bounds"
490+ - "getSize" has been removed. Use "terminal vty >>= display_bounds"
797− where "vty" is an instance of the Vty data structure.
491+ where "vty" is an instance of the Vty data structure.
798−* added a "terminal" field to the Vty data structure. Accesses the
492+ - added a "terminal" field to the Vty data structure. Accesses the
799− TerminalHandle associated with the Vty instance.
493+ TerminalHandle associated with the Vty instance.
800−* Graphics.Vty.Types has undergone a number of changes. Summary:
494+ - Graphics.Vty.Types has undergone a number of changes. Summary:
801− * Partitioned into Graphics.Vty.Attributes for display attributes.
495+ - Partitioned into Graphics.Vty.Attributes for display attributes.
802− Graphics.Vty.Image for image combinators. Graphics.Vty.Picture
496+ Graphics.Vty.Image for image combinators. Graphics.Vty.Picture
803− for final picture construction.
497+ for final picture construction.
804−* Graphics.Vty.Attributes:
498+ - Graphics.Vty.Attributes:
805− * "setFG" and "setBG" are now "with_fore_color" and
499+ - "setFG" and "setBG" are now "with_fore_color" and
806− "with_back_color"
500+ "with_back_color"
807− * All other "set.." equations similarly replaced.
501+ - All other "set.." equations similarly replaced.
808− * "attr" is now "def_attr", short for "default display attributes"
502+ - "attr" is now "def_attr", short for "default display attributes"
809− Also added a "current_attr" for "currently applied display
503+ Also added a "current_attr" for "currently applied display
810− attributes"
504+ attributes"
811−* Graphics.Vty.Image:
505+ - Graphics.Vty.Image:
812− * "horzcat" is now "horiz_cat"
506+ - "horzcat" is now "horiz_cat"
813− * "vertcat" is now "vert_cat"
507+ - "vertcat" is now "vert_cat"
814− * "renderBS" is now "utf8_bytestring"
508+ - "renderBS" is now "utf8_bytestring"
815− * "renderChar" is now "char"
509+ - "renderChar" is now "char"
816− * "renderFill" is now "char_fill"
510+ - "renderFill" is now "char_fill"
817− * added a "utf8_string" and "string" (AKA "iso_10464_string") for
511+ - added a "utf8_string" and "string" (AKA "iso_10464_string") for
818− UTF-8 encoded Strings and ISO-10464 encoded Strings. String
512+ UTF-8 encoded Strings and ISO-10464 encoded Strings. String
819− literals in GHC have an ISO-10464 runtime representation.
513+ literals in GHC have an ISO-10464 runtime representation.
820−* Graphics.Vty.Picture:
514+ - Graphics.Vty.Picture:
821− * exports Graphics.Vty.Image
515+ - exports Graphics.Vty.Image
822− * "pic" is now "pic_for_image"
516+ - "pic" is now "pic_for_image"
823− * added API for setting background fill pattern.
517+ - added API for setting background fill pattern.
824−* Completely rewritten output backend.
518+ - Completely rewritten output backend.
825− * Efficient, scanline style output span generator. Has not been
519+ - Efficient, scanline style output span generator. Has not been
826− fully optimized, but good enough.
520+ fully optimized, but good enough.
827− * The details required to display the desired picture on a
521+ - The details required to display the desired picture on a
828− terminal are well encapsulated.
522+ terminal are well encapsulated.
829− * Terminfo based display terminal implementation. With specialized
523+ - Terminfo based display terminal implementation. With specialized
830− derivitives for xterm, Terminal.app, and iTerm.app.
524+ derivitives for xterm, Terminal.app, and iTerm.app.
831− * Attempts to robustly handle even terminals that don't
525+ - Attempts to robustly handle even terminals that don't
832− support all display attributes.
526+ support all display attributes.
833− * I've tested the following terminals with success: iTerm.app,
527+ - I've tested the following terminals with success: iTerm.app,
834− Terminal.app, xterm, rxvt, mlterm, Eterm, gnome-terminal,
528+ Terminal.app, xterm, rxvt, mlterm, Eterm, gnome-terminal,
835− konsole, screen, linux vty. Hopefully you will be as
529+ konsole, screen, linux vty. Hopefully you will be as
836− successfull.
530+ successfull.
837− * Improved unicode support. Double wide characters will display as
531+ - Improved unicode support. Double wide characters will display as
838− expected.
532+ expected.
839−* 256 color support. See Graphics.Vty.Attributes.Color240. The actual
533+ - 256 color support. See Graphics.Vty.Attributes.Color240. The actual
840− output color is adjusted according to the number of colors the
534+ output color is adjusted according to the number of colors the
841− terminal supports.
535+ terminal supports.
842−* The Graphics.Vty.Image combinators no longer require matching
536+ - The Graphics.Vty.Image combinators no longer require matching
843− dimensions to arguments. Unspecified areas are filled in with a
537+ dimensions to arguments. Unspecified areas are filled in with a
844− user-customizable background pattern. See Graphics.Vty.Picture.
538+ user-customizable background pattern. See Graphics.Vty.Picture.
845−* output images are always cropped to display size.
539+ - output images are always cropped to display size.
846−* Significant code coverage by QuickCheck tests. An interactive test
540+ - Significant code coverage by QuickCheck tests. An interactive test
847− for those final properties that couldn't be automatically verified.
541+ for those final properties that couldn't be automatically verified.
848
542
849Issues resolved:
543Issues resolved:
850−* "gnome terminal displays non-basic attributes as strikethrough"
544+ - "gnome terminal displays non-basic attributes as strikethrough"
851− * http://trac.haskell.org/vty/ticket/14
545+ - http://trac.haskell.org/vty/ticket/14
852−* "Multi-byte characters are not displayed correctly on update"
546+ - "Multi-byte characters are not displayed correctly on update"
853− * http://trac.haskell.org/vty/ticket/10
547+ - http://trac.haskell.org/vty/ticket/10
854−* "Redraw does not handle rendering a line that extends beyond screen
548+ - "Redraw does not handle rendering a line that extends beyond screen
855− width characters"
549+ width characters"
856− * http://trac.haskell.org/vty/ticket/13
550+ - http://trac.haskell.org/vty/ticket/13
857−* "The <|> and <-> combinators should be more forgiving of mismatched
551+ - "The <|> and <-> combinators should be more forgiving of mismatched
858− dimensions"
552+ dimensions"
859− * http://trac.haskell.org/vty/ticket/9
553+ - http://trac.haskell.org/vty/ticket/9
860−* "256-color support"
554+ - "256-color support"
861− * http://trac.haskell.org/vty/ticket/19
555+ - http://trac.haskell.org/vty/ticket/19
LICENSE−2
@@ -1,5 +1,3 @@
1−BSD 3-Clause License
2−
3Copyright Stefan O'Rear 2006, Corey O'Connor 2008, Corey O'Connor 2009
1Copyright Stefan O'Rear 2006, Corey O'Connor 2008, Corey O'Connor 2009
4
2
5All rights reserved.
3All rights reserved.
cbits/gwinsz.c+5−14
@@ -1,18 +1,9 @@
1#include <sys/ioctl.h>
1#include <sys/ioctl.h>
2
2
3unsigned long vty_c_get_window_size(int fd) {
3unsigned long vty_c_get_window_size(int fd) {
4− struct winsize w;
4+ struct winsize w;
5− if (ioctl (fd, TIOCGWINSZ, &w) >= 0)
5+ if (ioctl (fd, TIOCGWINSZ, &w) >= 0)
6− return (w.ws_row << 16) + w.ws_col;
6+ return (w.ws_row << 16) + w.ws_col;
7− else
7+ else
8− return 0x190050;
8+ return 0x190050;
9−}
10−
11−void vty_c_set_window_size(int fd, unsigned long val) {
12− struct winsize w;
13− if (ioctl(fd, TIOCGWINSZ, &w) >= 0) {
14− w.ws_row = val >> 16;
15− w.ws_col = val & 0xFFFF;
16− ioctl(fd, TIOCSWINSZ, &w);
17− }
18}
9}
cbits/gwinsz.h+1−2
@@ -1,2 +1 @@
1−unsigned long vty_c_get_window_size(int fd);
1+unsigned long vty_c_get_window_size(void);
2−unsigned long vty_c_set_window_size(int fd, unsigned long val);
cbits/mk_wcwidth.c+10−15
@@ -77,10 +77,8 @@ static uint8_t* custom_table = NULL;
77// custom_table array.
77// custom_table array.
78static uint32_t custom_table_size = 0;
78static uint32_t custom_table_size = 0;
79
79
80−// A flag indicating whether the custom table is ready for
80+// A flag indicating whether the custom table is ready for use. This
81−// use. This should only be set once the table has been
81+// should only be set once the table has been allocated and initialized.
82−// allocated with vty_init_custom_table and initialized with
83−// vty_set_custom_table_range.
84static uint8_t custom_table_ready = 0;
82static uint8_t custom_table_ready = 0;
85
83
86struct interval {
84struct interval {
@@ -141,7 +139,7 @@ static int vty_bisearch(HsChar ucs, const struct interval *table, int max) {
141 * in ISO 10646.
139 * in ISO 10646.
142 */
140 */
143
141
144−static HsInt builtin_wcwidth(HsChar ucs)
142+HsInt builtin_wcwidth(HsChar ucs)
145{
143{
146 /* sorted list of non-overlapping intervals of non-spacing characters */
144 /* sorted list of non-overlapping intervals of non-spacing characters */
147 /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
145 /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
@@ -233,11 +231,11 @@ static HsInt builtin_wcwidth(HsChar ucs)
233// present, the built-in width table will be used.
231// present, the built-in width table will be used.
234HsInt vty_mk_wcwidth(HsChar ch)
232HsInt vty_mk_wcwidth(HsChar ch)
235{
233{
236− if (custom_table_ready) {
234+ if (custom_table != NULL) {
237 if ((ch >= 0) && (ch < custom_table_size)) {
235 if ((ch >= 0) && (ch < custom_table_size)) {
238 return custom_table[ch];
236 return custom_table[ch];
239 } else {
237 } else {
240− return -1;
238+ return 0;
241 }
239 }
242 } else {
240 } else {
243 return builtin_wcwidth(ch);
241 return builtin_wcwidth(ch);
@@ -249,7 +247,7 @@ HsInt vty_mk_wcwidth(HsChar ch)
249// This allocates a new character width table of the specified size
247// This allocates a new character width table of the specified size
250// (in characters). If a custom table has already been allocated, this
248// (in characters). If a custom table has already been allocated, this
251// returns 1. Otherwise it allocates a new table, initializes all of its
249// returns 1. Otherwise it allocates a new table, initializes all of its
252−// entries to 1, and returns zero.
250+// entries to zero, and returns zero.
253//
251//
254// Note that this does *not* mark the table as ready for use. Until the
252// Note that this does *not* mark the table as ready for use. Until the
255// table is marked ready, it will not be used by vty_mk_wcwidth. To mark
253// table is marked ready, it will not be used by vty_mk_wcwidth. To mark
@@ -261,7 +259,7 @@ int vty_init_custom_table(int size)
261 if (size > 0 && size <= MAX_CUSTOM_TABLE_SIZE) {
259 if (size > 0 && size <= MAX_CUSTOM_TABLE_SIZE) {
262 custom_table_ready = 0;
260 custom_table_ready = 0;
263 custom_table = malloc(size);
261 custom_table = malloc(size);
264− memset(custom_table, 1, size);
262+ bzero(custom_table, size);
265 custom_table_size = size;
263 custom_table_size = size;
266 return 0;
264 return 0;
267 } else {
265 } else {
@@ -286,13 +284,11 @@ int vty_init_custom_table(int size)
286int vty_set_custom_table_range(uint32_t start, uint32_t size, uint8_t width)
284int vty_set_custom_table_range(uint32_t start, uint32_t size, uint8_t width)
287{
285{
288 if ((custom_table == NULL) ||
286 if ((custom_table == NULL) ||
289− (size >= custom_table_size) ||
290− (start >= custom_table_size) ||
291− ((start + 1) >= (custom_table_size - size)) ||
287+ ((start + size - 1) >= custom_table_size) ||
292 custom_table_ready) {
288 custom_table_ready) {
293 return 1;
289 return 1;
294 } else {
290 } else {
295− memset(custom_table + start, width, size);
291+ memset(custom_table + start, (uint8_t) width, size);
296 return 0;
292 return 0;
297 }
293 }
298}
294}
@@ -318,7 +314,7 @@ int vty_activate_custom_table()
318// Returns whether a custom character width table has been marked ready.
314// Returns whether a custom character width table has been marked ready.
319int vty_custom_table_ready()
315int vty_custom_table_ready()
320{
316{
321− return custom_table_ready;
317+ return ((custom_table != NULL) && custom_table_ready);
322}
318}
323
319
324// Deallocate the custom width table.
320// Deallocate the custom width table.
@@ -333,6 +329,5 @@ void vty_deallocate_custom_table()
333 if ((custom_table != NULL) && (!custom_table_ready)) {
329 if ((custom_table != NULL) && (!custom_table_ready)) {
334 free(custom_table);
330 free(custom_table);
335 custom_table = NULL;
331 custom_table = NULL;
336− custom_table_size = 0;
337 }
332 }
338}
333}
demos/Demo.hs+4−12
@@ -31,8 +31,7 @@ introText = vertCat $ map (string defAttr)
31 [ "this line is hidden by the top layer"
31 [ "this line is hidden by the top layer"
32 , "The vty demo program will echo the events generated by the pressed keys."
32 , "The vty demo program will echo the events generated by the pressed keys."
33 , "Below there is a 240 color box."
33 , "Below there is a 240 color box."
34− , "Followed by a description of the 16 color palette."
34+ , "Followed by a description of the 16 color pallete."
35− , "Followed by tones of red using a 24-bit palette."
36 , "If the 240 color box is not visible then the terminal"
35 , "If the 240 color box is not visible then the terminal"
37 , "claims 240 colors are not supported."
36 , "claims 240 colors are not supported."
38 , "Try setting TERM to xterm-256color"
37 , "Try setting TERM to xterm-256color"
@@ -43,19 +42,12 @@ introText = vertCat $ map (string defAttr)
43 , "¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯"
42 , "¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯ ¯\\_(ツ)_/¯"
44 ]
43 ]
45
44
46−splitColorImages :: [Image] -> [[Image]]
47−splitColorImages [] = []
48−splitColorImages is = (take 20 is ++ [string defAttr " "]) : (splitColorImages (drop 20 is))
49−
50−fullcolorbox :: Image
51−fullcolorbox = vertCat $ map horizCat $ splitColorImages colorImages
52− where
53− colorImages = map (\i -> string (currentAttr `withBackColor` linearColor i 0 0) " ") [0..255]
54−
55colorbox_240 :: Image
45colorbox_240 :: Image
56colorbox_240 = vertCat $ map horizCat $ splitColorImages colorImages
46colorbox_240 = vertCat $ map horizCat $ splitColorImages colorImages
57 where
47 where
58 colorImages = map (\i -> string (currentAttr `withBackColor` Color240 i) " ") [0..239]
48 colorImages = map (\i -> string (currentAttr `withBackColor` Color240 i) " ") [0..239]
49+ splitColorImages [] = []
50+ splitColorImages is = (take 20 is ++ [string defAttr " "]) : (splitColorImages (drop 20 is))
59
51
60colorbox_16 :: Image
52colorbox_16 :: Image
61colorbox_16 = border <|> column0 <|> border <|> column1 <|> border <|> column2 <|> border
53colorbox_16 = border <|> column0 <|> border <|> column1 <|> border <|> column2 <|> border
@@ -78,7 +70,7 @@ updateDisplay = do
78 "Press ESC to exit. Events for keys below."
70 "Press ESC to exit. Events for keys below."
79 eventLog <- foldMap (string defAttr) <$> get
71 eventLog <- foldMap (string defAttr) <$> get
80 let pic = picForImage (info <-> eventLog)
72 let pic = picForImage (info <-> eventLog)
81− `addToBottom` (introText <-> colorbox_240 <|> colorbox_16 <|> fullcolorbox)
73+ `addToBottom` (introText <-> colorbox_240 <|> colorbox_16)
82 vty <- ask
74 vty <- ask
83 liftIO $ update vty pic
75 liftIO $ update vty pic
84
76
src/Codec/Binary/UTF8/Debug.hs+2−1
@@ -14,4 +14,5 @@ utf8FromIso :: [Int] -> [Word8]
14utf8FromIso = encode . map toEnum
14utf8FromIso = encode . map toEnum
15
15
16ppUtf8 :: [Int] -> IO ()
16ppUtf8 :: [Int] -> IO ()
17−ppUtf8 = print . map (`showHex` "") . utf8FromIso
17+ppUtf8 = print . map (\f -> f "") . map showHex . utf8FromIso
18+
src/Data/Sequence/Extra.hs+1−1
@@ -7,7 +7,7 @@ import Data.Sequence
7import Control.Parallel.Strategies
7import Control.Parallel.Strategies
8
8
9instance NFData a => NFData (Seq a) where
9instance NFData a => NFData (Seq a) where
10− rnf = rnf' . viewl
10+ rnf = \v -> rnf' (viewl v)
11 where
11 where
12 rnf' EmptyL = ()
12 rnf' EmptyL = ()
13 rnf' (a :< r) = rnf a >| rnf' (viewl r)
13 rnf' (a :< r) = rnf a >| rnf' (viewl r)
src/Data/Terminfo/Eval.hs+3−3
@@ -42,7 +42,7 @@ pop = do
42
42
43readParam :: Word -> Eval CapParam
43readParam :: Word -> Eval CapParam
44readParam pn = do
44readParam pn = do
45− !params <- evalParams <$> get
45+ !params <- get >>= return . evalParams
46 return $! genericIndex params pn
46 return $! genericIndex params pn
47
47
48push :: CapParam -> Eval ()
48push :: CapParam -> Eval ()
@@ -64,11 +64,11 @@ writeCapExpr cap params =
64 in snd $ runWriter (runStateT (writeCapOps (capOps cap)) s0)
64 in snd $ runWriter (runStateT (writeCapOps (capOps cap)) s0)
65
65
66writeCapOps :: CapOps -> Eval ()
66writeCapOps :: CapOps -> Eval ()
67−writeCapOps = mapM_ writeCapOp
67+writeCapOps ops = mapM_ writeCapOp ops
68
68
69writeCapOp :: CapOp -> Eval ()
69writeCapOp :: CapOp -> Eval ()
70writeCapOp (Bytes !offset !count) = do
70writeCapOp (Bytes !offset !count) = do
71− !cap <- evalExpression <$> get
71+ !cap <- get >>= return . evalExpression
72 let bytes = Vector.take count $ Vector.drop offset (capBytes cap)
72 let bytes = Vector.take count $ Vector.drop offset (capBytes cap)
73 Vector.forM_ bytes $ tell.writeWord8
73 Vector.forM_ bytes $ tell.writeWord8
74writeCapOp DecOut = do
74writeCapOp DecOut = do
src/Data/Terminfo/Parse.hs+10−10
@@ -1,9 +1,9 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
3+{-# OPTIONS_HADDOCK hide #-}
3{-# LANGUAGE NoMonomorphismRestriction #-}
4{-# LANGUAGE NoMonomorphismRestriction #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5+{-# LANGUAGE NamedFieldPuns #-}
5{-# OPTIONS_GHC -funbox-strict-fields -O #-}
6{-# OPTIONS_GHC -funbox-strict-fields -O #-}
6−{-# OPTIONS_HADDOCK hide #-}
7
7
8module Data.Terminfo.Parse
8module Data.Terminfo.Parse
9 ( module Data.Terminfo.Parse
9 ( module Data.Terminfo.Parse
@@ -39,7 +39,7 @@ instance Show CapExpression where
39 ++ " <= " ++ show (sourceString c)
39 ++ " <= " ++ show (sourceString c)
40 where
40 where
41 hexDump :: [Word8] -> String
41 hexDump :: [Word8] -> String
42− hexDump = foldr showHex ""
42+ hexDump = foldr (\b s -> showHex b s) ""
43
43
44instance NFData CapExpression where
44instance NFData CapExpression where
45 rnf (CapExpression ops !_bytes !str !c !pOps)
45 rnf (CapExpression ops !_bytes !str !c !pOps)
@@ -99,7 +99,7 @@ parseCapExpression capString =
99 Left e -> Left e
99 Left e -> Left e
100 Right buildResults -> Right $ constructCapExpression capString buildResults
100 Right buildResults -> Right $ constructCapExpression capString buildResults
101
101
102−constructCapExpression :: String -> BuildResults -> CapExpression
102+constructCapExpression :: [Char] -> BuildResults -> CapExpression
103constructCapExpression capString buildResults =
103constructCapExpression capString buildResults =
104 let expr = CapExpression
104 let expr = CapExpression
105 { capOps = outCapOps buildResults
105 { capOps = outCapOps buildResults
@@ -128,7 +128,7 @@ paramEscapeParser = do
128literalPercentParser :: CapParser BuildResults
128literalPercentParser :: CapParser BuildResults
129literalPercentParser = do
129literalPercentParser = do
130 _ <- char '%'
130 _ <- char '%'
131− startOffset <- nextOffset <$> getState
131+ startOffset <- getState >>= return . nextOffset
132 incOffset 1
132 incOffset 1
133 return $ BuildResults 0 [Bytes startOffset 1] []
133 return $ BuildResults 0 [Bytes startOffset 1] []
134
134
@@ -154,7 +154,7 @@ incrementOpParser = do
154pushOpParser :: CapParser BuildResults
154pushOpParser :: CapParser BuildResults
155pushOpParser = do
155pushOpParser = do
156 _ <- char 'p'
156 _ <- char 'p'
157− paramN <- read . pure <$> digit
157+ paramN <- digit >>= return . (\d -> read [d])
158 incOffset 2
158 incOffset 2
159 return $ BuildResults (fromEnum paramN) [PushParam $ paramN - 1] []
159 return $ BuildResults (fromEnum paramN) [PushParam $ paramN - 1] []
160
160
@@ -299,7 +299,7 @@ compareOpParser
299bytesOpParser :: CapParser BuildResults
299bytesOpParser :: CapParser BuildResults
300bytesOpParser = do
300bytesOpParser = do
301 bytes <- many1 $ satisfy (/= '%')
301 bytes <- many1 $ satisfy (/= '%')
302− startOffset <- nextOffset <$> getState
302+ startOffset <- getState >>= return . nextOffset
303 let !c = length bytes
303 let !c = length bytes
304 !s <- getState
304 !s <- getState
305 let s' = s { nextOffset = startOffset + c }
305 let s' = s { nextOffset = startOffset + c }
@@ -336,9 +336,9 @@ data BuildResults = BuildResults
336instance Semigroup BuildResults where
336instance Semigroup BuildResults where
337 v0 <> v1
337 v0 <> v1
338 = BuildResults
338 = BuildResults
339− { outParamCount = outParamCount v0 `max` outParamCount v1
339+ { outParamCount = (outParamCount v0) `max` (outParamCount v1)
340− , outCapOps = outCapOps v0 <> outCapOps v1
340+ , outCapOps = (outCapOps v0) <> (outCapOps v1)
341− , outParamOps = outParamOps v0 <> outParamOps v1
341+ , outParamOps = (outParamOps v0) <> (outParamOps v1)
342 }
342 }
343
343
344instance Monoid BuildResults where
344instance Monoid BuildResults where
src/Graphics/Text/Width.hs−9
@@ -1,15 +1,6 @@
1-- Copyright 2009 Corey O'Connor
1-- Copyright 2009 Corey O'Connor
2{-# OPTIONS_GHC -D_XOPEN_SOURCE #-}
2{-# OPTIONS_GHC -D_XOPEN_SOURCE #-}
3{-# LANGUAGE ForeignFunctionInterface #-}
3{-# LANGUAGE ForeignFunctionInterface #-}
4−-- | This module provides functions to measure the terminal column width
5−-- of characters and strings.
6−--
7−-- The functions provided in this module all ultimately make calls to
8−-- the C implementation in @cbits/mk_wcwidth.c@. That code manages some
9−-- global state that carries a table of Unicode character widths. For
10−-- more details, see 'Graphics.Vty.UnicodeWidthTable.Install', the C
11−-- code, and the "Multi-Column Character Support" section of the project
12−-- @README@.
13module Graphics.Text.Width
4module Graphics.Text.Width
14 ( wcwidth
5 ( wcwidth
15 , wcswidth
6 , wcswidth
src/Graphics/Vty.hs+19−39
@@ -1,5 +1,4 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3
2
4-- | Vty provides interfaces for both terminal input and terminal
3-- | Vty provides interfaces for both terminal input and terminal
5-- output.
4-- output.
@@ -34,7 +33,6 @@
34module Graphics.Vty
33module Graphics.Vty
35 ( Vty(..)
34 ( Vty(..)
36 , mkVty
35 , mkVty
37− , setWindowTitle
38 , Mode(..)
36 , Mode(..)
39 , module Graphics.Vty.Config
37 , module Graphics.Vty.Config
40 , module Graphics.Vty.Input
38 , module Graphics.Vty.Input
@@ -48,7 +46,6 @@ where
48
46
49import Graphics.Vty.Config
47import Graphics.Vty.Config
50import Graphics.Vty.Input
48import Graphics.Vty.Input
51−import Graphics.Vty.Input.Events
52import Graphics.Vty.Output
49import Graphics.Vty.Output
53import Graphics.Vty.Output.Interface
50import Graphics.Vty.Output.Interface
54import Graphics.Vty.Picture
51import Graphics.Vty.Picture
@@ -57,9 +54,6 @@ import Graphics.Vty.Attributes
57import Graphics.Vty.UnicodeWidthTable.IO
54import Graphics.Vty.UnicodeWidthTable.IO
58import Graphics.Vty.UnicodeWidthTable.Install
55import Graphics.Vty.UnicodeWidthTable.Install
59
56
60−import Data.Char (isPrint, showLitChar)
61−import qualified Data.ByteString.Char8 as BS8
62−
63import qualified Control.Exception as E
57import qualified Control.Exception as E
64import Control.Monad (when)
58import Control.Monad (when)
65import Control.Concurrent.STM
59import Control.Concurrent.STM
@@ -118,6 +112,15 @@ data Vty =
118-- precedence. See "Graphics.Vty.Config".
112-- precedence. See "Graphics.Vty.Config".
119--
113--
120-- For most applications @mkVty defaultConfig@ is sufficient.
114-- For most applications @mkVty defaultConfig@ is sufficient.
115+--
116+-- If the configuration's 'allowCustomUnicodeWidthTables' is set
117+-- to 'Nothing' or 'Just True', this will use the current value of
118+-- 'TERM' and the configuation's width table settings to attempt to
119+-- load a custom unicode character width table if one has not already
120+-- been loaded in this process. If the load is attempted and fails,
121+-- information about the failure will be logged to the debug log if the
122+-- configuration specifies one. If no custom table is loaded (or if a
123+-- load fails), the built-in character width table will be used.
121mkVty :: Config -> IO Vty
124mkVty :: Config -> IO Vty
122mkVty appConfig = do
125mkVty appConfig = do
123 config <- (<> appConfig) <$> userConfig
126 config <- (<> appConfig) <$> userConfig
@@ -168,7 +171,7 @@ internalMkVty :: Input -> Output -> IO Vty
168internalMkVty input out = do
171internalMkVty input out = do
169 reserveDisplay out
172 reserveDisplay out
170
173
171− shutdownVar <- newTVarIO False
174+ shutdownVar <- atomically $ newTVar False
172 let shutdownIo = do
175 let shutdownIo = do
173 alreadyShutdown <- atomically $ swapTVar shutdownVar True
176 alreadyShutdown <- atomically $ swapTVar shutdownVar True
174 when (not alreadyShutdown) $ do
177 when (not alreadyShutdown) $ do
@@ -176,7 +179,7 @@ internalMkVty input out = do
176 releaseDisplay out
179 releaseDisplay out
177 releaseTerminal out
180 releaseTerminal out
178
181
179− let shutdownStatus = readTVarIO shutdownVar
182+ let shutdownStatus = atomically $ readTVar shutdownVar
180
183
181 lastPicRef <- newIORef Nothing
184 lastPicRef <- newIORef Nothing
182 lastUpdateRef <- newIORef Nothing
185 lastUpdateRef <- newIORef Nothing
@@ -210,18 +213,16 @@ internalMkVty input out = do
210 maybe (return ()) innerUpdate mPic
213 maybe (return ()) innerUpdate mPic
211
214
212 let mkResize = uncurry EvResize <$> displayBounds out
215 let mkResize = uncurry EvResize <$> displayBounds out
213−
214− translateInternalEvent ResumeAfterSignal = mkResize
215− translateInternalEvent (InputEvent e) = return e
216−
217 gkey = do
216 gkey = do
218− e <- atomically $ readTChan $ _eventChannel input
217+ k <- atomically $ readTChan $ _eventChannel input
219− translateInternalEvent e
218+ case k of
219+ (EvResize _ _) -> mkResize
220+ _ -> return k
220 gkey' = do
221 gkey' = do
221− mEv <- atomically $ tryReadTChan $ _eventChannel input
222+ k <- atomically $ tryReadTChan $ _eventChannel input
222− case mEv of
223+ case k of
223− Just e -> Just <$> translateInternalEvent e
224+ (Just (EvResize _ _)) -> Just <$> mkResize
224− Nothing -> return Nothing
225+ _ -> return k
225
226
226 return $ Vty { update = innerUpdate
227 return $ Vty { update = innerUpdate
227 , nextEvent = gkey
228 , nextEvent = gkey
@@ -232,24 +233,3 @@ internalMkVty input out = do
232 , shutdown = shutdownIo
233 , shutdown = shutdownIo
233 , isShutdown = shutdownStatus
234 , isShutdown = shutdownStatus
234 }
235 }
235−
236−-- | Set the terminal window title string.
237−--
238−-- This function emits an Xterm-compatible escape sequence that we
239−-- anticipate will work for essentially all modern terminal emulators.
240−-- Ideally we'd use a terminal capability for this, but there does not
241−-- seem to exist a termcap for setting window titles. If you find that
242−-- this function does not work for a given terminal emulator, please
243−-- report the issue.
244−--
245−-- For details, see:
246−--
247−-- https://tldp.org/HOWTO/Xterm-Title-3.html
248−setWindowTitle :: Vty -> String -> IO ()
249−setWindowTitle vty title = do
250− let sanitize :: String -> String
251− sanitize = concatMap sanitizeChar
252− sanitizeChar c | not (isPrint c) = showLitChar c ""
253− | otherwise = [c]
254− let buf = BS8.pack $ "\ESC]2;" <> sanitize title <> "\007"
255− outputByteBuffer (outputIface vty) buf
src/Graphics/Vty/Attributes.hs+46−8
@@ -1,4 +1,7 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2+{-# LANGUAGE StandaloneDeriving #-}
3+{-# LANGUAGE GADTs #-}
4+{-# LANGUAGE RankNTypes #-}
2{-# LANGUAGE DeriveGeneric #-}
5{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE DeriveAnyClass #-}
6{-# LANGUAGE DeriveAnyClass #-}
4
7
@@ -40,7 +43,6 @@ module Graphics.Vty.Attributes
40 , withStyle
43 , withStyle
41 , standout
44 , standout
42 , italic
45 , italic
43− , strikethrough
44 , underline
46 , underline
45 , reverseVideo
47 , reverseVideo
46 , blink
48 , blink
@@ -61,6 +63,9 @@ where
61
63
62import Control.DeepSeq
64import Control.DeepSeq
63import Data.Bits
65import Data.Bits
66+#if !(MIN_VERSION_base(4,11,0))
67+import Data.Semigroup
68+#endif
64import Data.Text (Text)
69import Data.Text (Text)
65import Data.Word
70import Data.Word
66import GHC.Generics
71import GHC.Generics
@@ -113,6 +118,19 @@ data Attr = Attr
113-- Then the foreground color encoded into 8 bits.
118-- Then the foreground color encoded into 8 bits.
114-- Then the background color encoded into 8 bits.
119-- Then the background color encoded into 8 bits.
115
120
121+instance Semigroup Attr where
122+ attr0 <> attr1 =
123+ Attr ( attrStyle attr0 <> attrStyle attr1 )
124+ ( attrForeColor attr0 <> attrForeColor attr1 )
125+ ( attrBackColor attr0 <> attrBackColor attr1 )
126+ ( attrURL attr0 <> attrURL attr1 )
127+
128+instance Monoid Attr where
129+ mempty = Attr mempty mempty mempty mempty
130+#if !(MIN_VERSION_base(4,11,0))
131+ mappend = (<>)
132+#endif
133+
116-- | Specifies the display attributes such that the final style and
134-- | Specifies the display attributes such that the final style and
117-- color values do not depend on the previously applied display
135-- color values do not depend on the previously applied display
118-- attribute. The display attributes can still depend on the terminal's
136-- attribute. The display attributes can still depend on the terminal's
@@ -127,20 +145,43 @@ data FixedAttr = FixedAttr
127-- | The style and color attributes can either be the terminal defaults.
145-- | The style and color attributes can either be the terminal defaults.
128-- Or be equivalent to the previously applied style. Or be a specific
146-- Or be equivalent to the previously applied style. Or be a specific
129-- value.
147-- value.
130−data MaybeDefault v = Default | KeepCurrent | SetTo !v
148+data MaybeDefault v where
131− deriving (Eq, Read, Show)
149+ Default :: MaybeDefault v
150+ KeepCurrent :: MaybeDefault v
151+ SetTo :: forall v . ( Eq v, Show v, Read v ) => !v -> MaybeDefault v
132
152
133instance (NFData v) => NFData (MaybeDefault v) where
153instance (NFData v) => NFData (MaybeDefault v) where
134 rnf Default = ()
154 rnf Default = ()
135 rnf KeepCurrent = ()
155 rnf KeepCurrent = ()
136 rnf (SetTo v) = rnf v
156 rnf (SetTo v) = rnf v
137
157
158+deriving instance Eq v => Eq (MaybeDefault v)
159+deriving instance Eq v => Show (MaybeDefault v)
160+deriving instance (Eq v, Show v, Read v) => Read (MaybeDefault v)
161+
162+instance Eq v => Semigroup (MaybeDefault v) where
163+ Default <> Default = Default
164+ Default <> KeepCurrent = Default
165+ Default <> SetTo v = SetTo v
166+ KeepCurrent <> Default = Default
167+ KeepCurrent <> KeepCurrent = KeepCurrent
168+ KeepCurrent <> SetTo v = SetTo v
169+ SetTo _v <> Default = Default
170+ SetTo v <> KeepCurrent = SetTo v
171+ SetTo _ <> SetTo v = SetTo v
172+
173+instance Eq v => Monoid ( MaybeDefault v ) where
174+ mempty = KeepCurrent
175+#if !(MIN_VERSION_base(4,11,0))
176+ mappend = (<>)
177+#endif
178+
138-- | Styles are represented as an 8 bit word. Each bit in the word is 1
179-- | Styles are represented as an 8 bit word. Each bit in the word is 1
139-- if the style attribute assigned to that bit should be applied and 0
180-- if the style attribute assigned to that bit should be applied and 0
140-- if the style attribute should not be applied.
181-- if the style attribute should not be applied.
141type Style = Word8
182type Style = Word8
142
183
143−-- | Valid style attributes include:
184+-- | The 7 possible style attributes:
144--
185--
145-- * standout
186-- * standout
146--
187--
@@ -156,11 +197,9 @@ type Style = Word8
156--
197--
157-- * italic
198-- * italic
158--
199--
159−-- * strikethrough (via the smxx/rmxx terminfo capabilities)
160−--
161-- (The invisible, protect, and altcharset display attributes some
200-- (The invisible, protect, and altcharset display attributes some
162-- terminals support are not supported via VTY.)
201-- terminals support are not supported via VTY.)
163−standout, underline, reverseVideo, blink, dim, bold, italic, strikethrough :: Style
202+standout, underline, reverseVideo, blink, dim, bold, italic :: Style
164standout = 0x01
203standout = 0x01
165underline = 0x02
204underline = 0x02
166reverseVideo = 0x04
205reverseVideo = 0x04
@@ -168,7 +207,6 @@ blink = 0x08
168dim = 0x10
207dim = 0x10
169bold = 0x20
208bold = 0x20
170italic = 0x40
209italic = 0x40
171−strikethrough = 0x80
172
210
173defaultStyleMask :: Style
211defaultStyleMask :: Style
174defaultStyleMask = 0x00
212defaultStyleMask = 0x00
src/Graphics/Vty/Attributes/Color.hs+3−67
@@ -1,14 +1,8 @@
1{-# LANGUAGE DeriveGeneric #-}
1{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE DeriveAnyClass #-}
2{-# LANGUAGE DeriveAnyClass #-}
3−{-# LANGUAGE MultiWayIf #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5
3
6module Graphics.Vty.Attributes.Color
4module Graphics.Vty.Attributes.Color
7 ( Color(..)
5 ( Color(..)
8− , ColorMode(..)
9−
10− -- * Detecting Terminal Color Support
11− , detectColorMode
12
6
13 -- ** Fixed Colors
7 -- ** Fixed Colors
14 -- | Standard 8-color ANSI terminal color codes.
8 -- | Standard 8-color ANSI terminal color codes.
@@ -38,10 +32,7 @@ module Graphics.Vty.Attributes.Color
38 , brightCyan
32 , brightCyan
39 , brightWhite
33 , brightWhite
40 -- ** Creating Colors From RGB
34 -- ** Creating Colors From RGB
41− , linearColor
42− , srgbColor
43 , rgbColor
35 , rgbColor
44− , color240
45 , module Graphics.Vty.Attributes.Color240
36 , module Graphics.Vty.Attributes.Color240
46 )
37 )
47where
38where
@@ -49,11 +40,6 @@ where
49import Data.Word
40import Data.Word
50import GHC.Generics
41import GHC.Generics
51import Control.DeepSeq
42import Control.DeepSeq
52−import System.Environment (lookupEnv)
53−
54−import qualified System.Console.Terminfo as Terminfo
55−import Control.Exception (catch)
56−import Data.Maybe
57
43
58import Graphics.Vty.Attributes.Color240
44import Graphics.Vty.Attributes.Color240
59
45
@@ -95,7 +81,7 @@ import Graphics.Vty.Attributes.Color240
95-- reported then the color reproduction will be incorrect.
81-- reported then the color reproduction will be incorrect.
96--
82--
97-- If the terminal reports <= 16 colors then the 240 color palette
83-- If the terminal reports <= 16 colors then the 240 color palette
98−-- points are only mapped to the 8 color palette. I'm not sure of
84+-- points are only mapped to the 8 color pallete. I'm not sure of
99-- the RGB points for the "bright" colors which is why they are not
85-- the RGB points for the "bright" colors which is why they are not
100-- addressable via the 240 color palette.
86-- addressable via the 240 color palette.
101--
87--
@@ -109,33 +95,9 @@ import Graphics.Vty.Attributes.Color240
109-- terminfo but I don't know it.
95-- terminfo but I don't know it.
110--
96--
111-- Seriously, terminal color support is INSANE.
97-- Seriously, terminal color support is INSANE.
112−data Color = ISOColor !Word8 | Color240 !Word8 | RGBColor !Word8 !Word8 !Word8
98+data Color = ISOColor !Word8 | Color240 !Word8
113 deriving ( Eq, Show, Read, Generic, NFData )
99 deriving ( Eq, Show, Read, Generic, NFData )
114
100
115−data ColorMode
116− = NoColor
117− | ColorMode8
118− | ColorMode16
119− | ColorMode240 !Word8
120− | FullColor
121− deriving ( Eq, Show )
122−
123−detectColorMode :: String -> IO ColorMode
124−detectColorMode termName' = do
125− term <- catch (Just <$> Terminfo.setupTerm termName')
126− (\(_ :: Terminfo.SetupTermError) -> return Nothing)
127− let getCap cap = term >>= \t -> Terminfo.getCapability t cap
128− termColors = fromMaybe 0 $ getCap (Terminfo.tiGetNum "colors")
129− colorterm <- lookupEnv "COLORTERM"
130− return $ if
131− | termColors < 8 -> NoColor
132− | termColors < 16 -> ColorMode8
133− | termColors == 16 -> ColorMode16
134− | termColors < 256 -> ColorMode240 (fromIntegral termColors - 16)
135− | colorterm == Just "truecolor" -> FullColor
136− | colorterm == Just "24bit" -> FullColor
137− | otherwise -> ColorMode240 240
138−
139black, red, green, yellow, blue, magenta, cyan, white :: Color
101black, red, green, yellow, blue, magenta, cyan, white :: Color
140black = ISOColor 0
102black = ISOColor 0
141red = ISOColor 1
103red = ISOColor 1
@@ -157,35 +119,9 @@ brightMagenta= ISOColor 13
157brightCyan = ISOColor 14
119brightCyan = ISOColor 14
158brightWhite = ISOColor 15
120brightWhite = ISOColor 15
159
121
160−linearColor :: Integral i => i -> i -> i -> Color
161−linearColor r g b = RGBColor r' g' b'
162− where
163− r' = fromIntegral (clamp r) :: Word8
164− g' = fromIntegral (clamp g) :: Word8
165− b' = fromIntegral (clamp b) :: Word8
166− clamp = min 255 . max 0
167−
168−srgbColor :: Integral i => i -> i -> i -> Color
169−srgbColor r g b =
170− -- srgb to rgb transformation as described at
171− -- https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation
172− --
173− -- TODO: it may be worth translating this to a lookup table, as with color240
174− let shrink n = fromIntegral n / 255 :: Double
175− -- called gamma^-1 in wiki
176− gamma u
177− | u <= 0.04045 = u/12.92
178− | otherwise = ((u + 0.055) / 1.055) ** 2.4
179− -- TODO: this is a slightly inaccurate conversion. is it worth doing proterly?
180− expand n = round (255 * n)
181− convert = expand . gamma . shrink
182− in RGBColor (convert r) (convert g) (convert b)
183−
184−color240 :: Integral i => i -> i -> i -> Color
185−color240 r g b = Color240 (rgbColorToColor240 r g b)
186
122
187-- | Create a Vty 'Color' (in the 240 color set) from an RGB triple.
123-- | Create a Vty 'Color' (in the 240 color set) from an RGB triple.
188-- This function is lossy in the sense that we only internally support 240 colors but the
124-- This function is lossy in the sense that we only internally support 240 colors but the
189-- #RRGGBB format supports 16^3 colors.
125-- #RRGGBB format supports 16^3 colors.
190rgbColor :: Integral i => i -> i -> i -> Color
126rgbColor :: Integral i => i -> i -> i -> Color
191−rgbColor = color240
127+rgbColor r g b = Color240 (rgbColorToColor240 r g b)
src/Graphics/Vty/Attributes/Color240.hs+218−10
@@ -39,18 +39,226 @@ rgbColorToColor240 r g b
39 | r == 218 && g == 218 && b == 218 = 237
39 | r == 218 && g == 218 && b == 218 = 237
40 | r == 228 && g == 228 && b == 228 = 238
40 | r == 228 && g == 228 && b == 228 = 238
41 | r == 238 && g == 238 && b == 238 = 239
41 | r == 238 && g == 238 && b == 238 = 239
42− | otherwise = 36 * go r + 6 * go g + go b
42+ | r <= 0 && g <= 0 && b <= 0 = 0
43− where go = simpleColor_ (error (printf "RGB color %d %d %d does not map to 240 palette."
43+ | r <= 0 && g <= 0 && b <= 95 = 1
44+ | r <= 0 && g <= 0 && b <= 135 = 2
45+ | r <= 0 && g <= 0 && b <= 175 = 3
46+ | r <= 0 && g <= 0 && b <= 215 = 4
47+ | r <= 0 && g <= 0 && b <= 255 = 5
48+ | r <= 0 && g <= 95 && b <= 0 = 6
49+ | r <= 0 && g <= 95 && b <= 95 = 7
50+ | r <= 0 && g <= 95 && b <= 135 = 8
51+ | r <= 0 && g <= 95 && b <= 175 = 9
52+ | r <= 0 && g <= 95 && b <= 215 = 10
53+ | r <= 0 && g <= 95 && b <= 255 = 11
54+ | r <= 0 && g <= 135 && b <= 0 = 12
55+ | r <= 0 && g <= 135 && b <= 95 = 13
56+ | r <= 0 && g <= 135 && b <= 135 = 14
57+ | r <= 0 && g <= 135 && b <= 175 = 15
58+ | r <= 0 && g <= 135 && b <= 215 = 16
59+ | r <= 0 && g <= 135 && b <= 255 = 17
60+ | r <= 0 && g <= 175 && b <= 0 = 18
61+ | r <= 0 && g <= 175 && b <= 95 = 19
62+ | r <= 0 && g <= 175 && b <= 135 = 20
63+ | r <= 0 && g <= 175 && b <= 175 = 21
64+ | r <= 0 && g <= 175 && b <= 215 = 22
65+ | r <= 0 && g <= 175 && b <= 255 = 23
66+ | r <= 0 && g <= 215 && b <= 0 = 24
67+ | r <= 0 && g <= 215 && b <= 95 = 25
68+ | r <= 0 && g <= 215 && b <= 135 = 26
69+ | r <= 0 && g <= 215 && b <= 175 = 27
70+ | r <= 0 && g <= 215 && b <= 215 = 28
71+ | r <= 0 && g <= 215 && b <= 255 = 29
72+ | r <= 0 && g <= 255 && b <= 0 = 30
73+ | r <= 0 && g <= 255 && b <= 95 = 31
74+ | r <= 0 && g <= 255 && b <= 135 = 32
75+ | r <= 0 && g <= 255 && b <= 175 = 33
76+ | r <= 0 && g <= 255 && b <= 215 = 34
77+ | r <= 0 && g <= 255 && b <= 255 = 35
78+ | r <= 95 && g <= 0 && b <= 0 = 36
79+ | r <= 95 && g <= 0 && b <= 95 = 37
80+ | r <= 95 && g <= 0 && b <= 135 = 38
81+ | r <= 95 && g <= 0 && b <= 175 = 39
82+ | r <= 95 && g <= 0 && b <= 215 = 40
83+ | r <= 95 && g <= 0 && b <= 255 = 41
84+ | r <= 95 && g <= 95 && b <= 0 = 42
85+ | r <= 95 && g <= 95 && b <= 95 = 43
86+ | r <= 95 && g <= 95 && b <= 135 = 44
87+ | r <= 95 && g <= 95 && b <= 175 = 45
88+ | r <= 95 && g <= 95 && b <= 215 = 46
89+ | r <= 95 && g <= 95 && b <= 255 = 47
90+ | r <= 95 && g <= 135 && b <= 0 = 48
91+ | r <= 95 && g <= 135 && b <= 95 = 49
92+ | r <= 95 && g <= 135 && b <= 135 = 50
93+ | r <= 95 && g <= 135 && b <= 175 = 51
94+ | r <= 95 && g <= 135 && b <= 215 = 52
95+ | r <= 95 && g <= 135 && b <= 255 = 53
96+ | r <= 95 && g <= 175 && b <= 0 = 54
97+ | r <= 95 && g <= 175 && b <= 95 = 55
98+ | r <= 95 && g <= 175 && b <= 135 = 56
99+ | r <= 95 && g <= 175 && b <= 175 = 57
100+ | r <= 95 && g <= 175 && b <= 215 = 58
101+ | r <= 95 && g <= 175 && b <= 255 = 59
102+ | r <= 95 && g <= 215 && b <= 0 = 60
103+ | r <= 95 && g <= 215 && b <= 95 = 61
104+ | r <= 95 && g <= 215 && b <= 135 = 62
105+ | r <= 95 && g <= 215 && b <= 175 = 63
106+ | r <= 95 && g <= 215 && b <= 215 = 64
107+ | r <= 95 && g <= 215 && b <= 255 = 65
108+ | r <= 95 && g <= 255 && b <= 0 = 66
109+ | r <= 95 && g <= 255 && b <= 95 = 67
110+ | r <= 95 && g <= 255 && b <= 135 = 68
111+ | r <= 95 && g <= 255 && b <= 175 = 69
112+ | r <= 95 && g <= 255 && b <= 215 = 70
113+ | r <= 95 && g <= 255 && b <= 255 = 71
114+ | r <= 135 && g <= 0 && b <= 0 = 72
115+ | r <= 135 && g <= 0 && b <= 95 = 73
116+ | r <= 135 && g <= 0 && b <= 135 = 74
117+ | r <= 135 && g <= 0 && b <= 175 = 75
118+ | r <= 135 && g <= 0 && b <= 215 = 76
119+ | r <= 135 && g <= 0 && b <= 255 = 77
120+ | r <= 135 && g <= 95 && b <= 0 = 78
121+ | r <= 135 && g <= 95 && b <= 95 = 79
122+ | r <= 135 && g <= 95 && b <= 135 = 80
123+ | r <= 135 && g <= 95 && b <= 175 = 81
124+ | r <= 135 && g <= 95 && b <= 215 = 82
125+ | r <= 135 && g <= 95 && b <= 255 = 83
126+ | r <= 135 && g <= 135 && b <= 0 = 84
127+ | r <= 135 && g <= 135 && b <= 95 = 85
128+ | r <= 135 && g <= 135 && b <= 135 = 86
129+ | r <= 135 && g <= 135 && b <= 175 = 87
130+ | r <= 135 && g <= 135 && b <= 215 = 88
131+ | r <= 135 && g <= 135 && b <= 255 = 89
132+ | r <= 135 && g <= 175 && b <= 0 = 90
133+ | r <= 135 && g <= 175 && b <= 95 = 91
134+ | r <= 135 && g <= 175 && b <= 135 = 92
135+ | r <= 135 && g <= 175 && b <= 175 = 93
136+ | r <= 135 && g <= 175 && b <= 215 = 94
137+ | r <= 135 && g <= 175 && b <= 255 = 95
138+ | r <= 135 && g <= 215 && b <= 0 = 96
139+ | r <= 135 && g <= 215 && b <= 95 = 97
140+ | r <= 135 && g <= 215 && b <= 135 = 98
141+ | r <= 135 && g <= 215 && b <= 175 = 99
142+ | r <= 135 && g <= 215 && b <= 215 = 100
143+ | r <= 135 && g <= 215 && b <= 255 = 101
144+ | r <= 135 && g <= 255 && b <= 0 = 102
145+ | r <= 135 && g <= 255 && b <= 95 = 103
146+ | r <= 135 && g <= 255 && b <= 135 = 104
147+ | r <= 135 && g <= 255 && b <= 175 = 105
148+ | r <= 135 && g <= 255 && b <= 215 = 106
149+ | r <= 135 && g <= 255 && b <= 255 = 107
150+ | r <= 175 && g <= 0 && b <= 0 = 108
151+ | r <= 175 && g <= 0 && b <= 95 = 109
152+ | r <= 175 && g <= 0 && b <= 135 = 110
153+ | r <= 175 && g <= 0 && b <= 175 = 111
154+ | r <= 175 && g <= 0 && b <= 215 = 112
155+ | r <= 175 && g <= 0 && b <= 255 = 113
156+ | r <= 175 && g <= 95 && b <= 0 = 114
157+ | r <= 175 && g <= 95 && b <= 95 = 115
158+ | r <= 175 && g <= 95 && b <= 135 = 116
159+ | r <= 175 && g <= 95 && b <= 175 = 117
160+ | r <= 175 && g <= 95 && b <= 215 = 118
161+ | r <= 175 && g <= 95 && b <= 255 = 119
162+ | r <= 175 && g <= 135 && b <= 0 = 120
163+ | r <= 175 && g <= 135 && b <= 95 = 121
164+ | r <= 175 && g <= 135 && b <= 135 = 122
165+ | r <= 175 && g <= 135 && b <= 175 = 123
166+ | r <= 175 && g <= 135 && b <= 215 = 124
167+ | r <= 175 && g <= 135 && b <= 255 = 125
168+ | r <= 175 && g <= 175 && b <= 0 = 126
169+ | r <= 175 && g <= 175 && b <= 95 = 127
170+ | r <= 175 && g <= 175 && b <= 135 = 128
171+ | r <= 175 && g <= 175 && b <= 175 = 129
172+ | r <= 175 && g <= 175 && b <= 215 = 130
173+ | r <= 175 && g <= 175 && b <= 255 = 131
174+ | r <= 175 && g <= 215 && b <= 0 = 132
175+ | r <= 175 && g <= 215 && b <= 95 = 133
176+ | r <= 175 && g <= 215 && b <= 135 = 134
177+ | r <= 175 && g <= 215 && b <= 175 = 135
178+ | r <= 175 && g <= 215 && b <= 215 = 136
179+ | r <= 175 && g <= 215 && b <= 255 = 137
180+ | r <= 175 && g <= 255 && b <= 0 = 138
181+ | r <= 175 && g <= 255 && b <= 95 = 139
182+ | r <= 175 && g <= 255 && b <= 135 = 140
183+ | r <= 175 && g <= 255 && b <= 175 = 141
184+ | r <= 175 && g <= 255 && b <= 215 = 142
185+ | r <= 175 && g <= 255 && b <= 255 = 143
186+ | r <= 215 && g <= 0 && b <= 0 = 144
187+ | r <= 215 && g <= 0 && b <= 95 = 145
188+ | r <= 215 && g <= 0 && b <= 135 = 146
189+ | r <= 215 && g <= 0 && b <= 175 = 147
190+ | r <= 215 && g <= 0 && b <= 215 = 148
191+ | r <= 215 && g <= 0 && b <= 255 = 149
192+ | r <= 215 && g <= 95 && b <= 0 = 150
193+ | r <= 215 && g <= 95 && b <= 95 = 151
194+ | r <= 215 && g <= 95 && b <= 135 = 152
195+ | r <= 215 && g <= 95 && b <= 175 = 153
196+ | r <= 215 && g <= 95 && b <= 215 = 154
197+ | r <= 215 && g <= 95 && b <= 255 = 155
198+ | r <= 215 && g <= 135 && b <= 0 = 156
199+ | r <= 215 && g <= 135 && b <= 95 = 157
200+ | r <= 215 && g <= 135 && b <= 135 = 158
201+ | r <= 215 && g <= 135 && b <= 175 = 159
202+ | r <= 215 && g <= 135 && b <= 215 = 160
203+ | r <= 215 && g <= 135 && b <= 255 = 161
204+ | r <= 215 && g <= 175 && b <= 0 = 162
205+ | r <= 215 && g <= 175 && b <= 95 = 163
206+ | r <= 215 && g <= 175 && b <= 135 = 164
207+ | r <= 215 && g <= 175 && b <= 175 = 165
208+ | r <= 215 && g <= 175 && b <= 215 = 166
209+ | r <= 215 && g <= 175 && b <= 255 = 167
210+ | r <= 215 && g <= 215 && b <= 0 = 168
211+ | r <= 215 && g <= 215 && b <= 95 = 169
212+ | r <= 215 && g <= 215 && b <= 135 = 170
213+ | r <= 215 && g <= 215 && b <= 175 = 171
214+ | r <= 215 && g <= 215 && b <= 215 = 172
215+ | r <= 215 && g <= 215 && b <= 255 = 173
216+ | r <= 215 && g <= 255 && b <= 0 = 174
217+ | r <= 215 && g <= 255 && b <= 95 = 175
218+ | r <= 215 && g <= 255 && b <= 135 = 176
219+ | r <= 215 && g <= 255 && b <= 175 = 177
220+ | r <= 215 && g <= 255 && b <= 215 = 178
221+ | r <= 215 && g <= 255 && b <= 255 = 179
222+ | r <= 255 && g <= 0 && b <= 0 = 180
223+ | r <= 255 && g <= 0 && b <= 95 = 181
224+ | r <= 255 && g <= 0 && b <= 135 = 182
225+ | r <= 255 && g <= 0 && b <= 175 = 183
226+ | r <= 255 && g <= 0 && b <= 215 = 184
227+ | r <= 255 && g <= 0 && b <= 255 = 185
228+ | r <= 255 && g <= 95 && b <= 0 = 186
229+ | r <= 255 && g <= 95 && b <= 95 = 187
230+ | r <= 255 && g <= 95 && b <= 135 = 188
231+ | r <= 255 && g <= 95 && b <= 175 = 189
232+ | r <= 255 && g <= 95 && b <= 215 = 190
233+ | r <= 255 && g <= 95 && b <= 255 = 191
234+ | r <= 255 && g <= 135 && b <= 0 = 192
235+ | r <= 255 && g <= 135 && b <= 95 = 193
236+ | r <= 255 && g <= 135 && b <= 135 = 194
237+ | r <= 255 && g <= 135 && b <= 175 = 195
238+ | r <= 255 && g <= 135 && b <= 215 = 196
239+ | r <= 255 && g <= 135 && b <= 255 = 197
240+ | r <= 255 && g <= 175 && b <= 0 = 198
241+ | r <= 255 && g <= 175 && b <= 95 = 199
242+ | r <= 255 && g <= 175 && b <= 135 = 200
243+ | r <= 255 && g <= 175 && b <= 175 = 201
244+ | r <= 255 && g <= 175 && b <= 215 = 202
245+ | r <= 255 && g <= 175 && b <= 255 = 203
246+ | r <= 255 && g <= 215 && b <= 0 = 204
247+ | r <= 255 && g <= 215 && b <= 95 = 205
248+ | r <= 255 && g <= 215 && b <= 135 = 206
249+ | r <= 255 && g <= 215 && b <= 175 = 207
250+ | r <= 255 && g <= 215 && b <= 215 = 208
251+ | r <= 255 && g <= 215 && b <= 255 = 209
252+ | r <= 255 && g <= 255 && b <= 0 = 210
253+ | r <= 255 && g <= 255 && b <= 95 = 211
254+ | r <= 255 && g <= 255 && b <= 135 = 212
255+ | r <= 255 && g <= 255 && b <= 175 = 213
256+ | r <= 255 && g <= 255 && b <= 215 = 214
257+ | r <= 255 && g <= 255 && b <= 255 = 215
258+ | otherwise = error (printf "RGB color %d %d %d does not map to 240 palette."
44 (fromIntegral r :: Int)
259 (fromIntegral r :: Int)
45 (fromIntegral g :: Int)
260 (fromIntegral g :: Int)
46− (fromIntegral b :: Int)))
261+ (fromIntegral b :: Int))
47−
48−simpleColor_ :: Integral i => Word8 -> i -> Word8
49−simpleColor_ e c
50− | c <= 0 = 0
51− | c <= 95 = 1
52− | c <= 255 = fromIntegral ((c-16) `div` 40)
53− | otherwise = e
54
262
55-- | Create a RGB triple from a value in the Color240 set.
263-- | Create a RGB triple from a value in the Color240 set.
56color240CodeToRGB :: Word8 -> Maybe (Int, Int, Int)
264color240CodeToRGB :: Word8 -> Maybe (Int, Int, Int)
src/Graphics/Vty/Config.hs+7−81
@@ -3,7 +3,6 @@
3{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
3{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE ScopedTypeVariables #-}
6−{-# LANGUAGE LambdaCase, MultiWayIf #-}
7-- | Vty supports a configuration file format and associated 'Config'
6-- | Vty supports a configuration file format and associated 'Config'
8-- data type. The 'Config' can be provided to 'mkVty' to customize the
7-- data type. The 'Config' can be provided to 'mkVty' to customize the
9-- application's use of Vty.
8-- application's use of Vty.
@@ -55,7 +54,7 @@
55-- If a debug log is requested then vty will output the current input
54-- If a debug log is requested then vty will output the current input
56-- table to the log in the above format. A workflow for using this is
55-- table to the log in the above format. A workflow for using this is
57-- to set @VTY_DEBUG_LOG@. Run the application. Check the debug log for
56-- to set @VTY_DEBUG_LOG@. Run the application. Check the debug log for
58−-- incorrect mappings. Add corrected mappings to @$HOME\/.vty\/config@.
57+-- incorrect mappings. Add corrected mappings to @$HOME/.vty/config@.
59--
58--
60-- = Unicode Character Width Maps
59-- = Unicode Character Width Maps
61--
60--
@@ -100,9 +99,6 @@ module Graphics.Vty.Config
100 , vtyDataDirectory
99 , vtyDataDirectory
101 , terminalWidthTablePath
100 , terminalWidthTablePath
102 , vtyConfigFileEnvName
101 , vtyConfigFileEnvName
103−
104− , ConfigUpdateResult(..)
105− , addConfigWidthMap
106 )
102 )
107where
103where
108
104
@@ -123,15 +119,12 @@ import Data.Semigroup (Semigroup(..))
123import Data.Typeable (Typeable)
119import Data.Typeable (Typeable)
124
120
125import Graphics.Vty.Input.Events
121import Graphics.Vty.Input.Events
126−import Graphics.Vty.Attributes.Color (ColorMode(..), detectColorMode)
127
122
128import GHC.Generics
123import GHC.Generics
129
124
130−import System.Directory ( getAppUserDataDirectory, doesFileExist
125+import System.Directory (getAppUserDataDirectory)
131− , createDirectoryIfMissing
132− )
133import System.Environment (lookupEnv)
126import System.Environment (lookupEnv)
134−import System.FilePath ((</>), takeDirectory)
127+import System.FilePath ((</>))
135import System.Posix.IO (stdInput, stdOutput)
128import System.Posix.IO (stdInput, stdOutput)
136import System.Posix.Types (Fd(..))
129import System.Posix.Types (Fd(..))
137import Foreign.C.Types (CInt(..), CChar(..))
130import Foreign.C.Types (CInt(..), CChar(..))
@@ -185,19 +178,9 @@ data Config =
185 , termWidthMaps :: [(String, FilePath)]
178 , termWidthMaps :: [(String, FilePath)]
186 -- ^ Terminal width map files.
179 -- ^ Terminal width map files.
187 , allowCustomUnicodeWidthTables :: Maybe Bool
180 , allowCustomUnicodeWidthTables :: Maybe Bool
188− -- ^ Whether to permit custom Unicode width table loading by
181+ -- ^ Whether to permit custom Unicode width table loading.
189− -- 'Graphics.Vty.mkVty'. @'Just' 'False'@ indicates that
182+ -- 'Just False' indicates that table loading should not be
190− -- table loading should not be performed. Other values permit
183+ -- performed. Other values permit table loading.
191− -- table loading.
192− --
193− -- If a table load is attempted and fails, information
194− -- about the failure will be logged to the debug log if the
195− -- configuration specifies one. If no custom table is loaded
196− -- (or if a load fails), the built-in character width table
197− -- will be used.
198− , colorMode :: Maybe ColorMode
199− -- ^ The color mode used to know how many colors the terminal
200− -- supports.
201 }
184 }
202 deriving (Show, Eq)
185 deriving (Show, Eq)
203
186
@@ -219,7 +202,6 @@ instance Semigroup Config where
219 , termWidthMaps = termWidthMaps c1 <|> termWidthMaps c0
202 , termWidthMaps = termWidthMaps c1 <|> termWidthMaps c0
220 , allowCustomUnicodeWidthTables =
203 , allowCustomUnicodeWidthTables =
221 allowCustomUnicodeWidthTables c1 <|> allowCustomUnicodeWidthTables c0
204 allowCustomUnicodeWidthTables c1 <|> allowCustomUnicodeWidthTables c0
222− , colorMode = colorMode c1 <|> colorMode c0
223 }
205 }
224
206
225instance Monoid Config where
207instance Monoid Config where
@@ -235,7 +217,6 @@ instance Monoid Config where
235 , termName = Nothing
217 , termName = Nothing
236 , termWidthMaps = []
218 , termWidthMaps = []
237 , allowCustomUnicodeWidthTables = Nothing
219 , allowCustomUnicodeWidthTables = Nothing
238− , colorMode = Nothing
239 }
220 }
240#if !(MIN_VERSION_base(4,11,0))
221#if !(MIN_VERSION_base(4,11,0))
241 mappend = (<>)
222 mappend = (<>)
@@ -291,8 +272,7 @@ standardIOConfig = do
291 mb <- lookupEnv termVariable
272 mb <- lookupEnv termVariable
292 case mb of
273 case mb of
293 Nothing -> throwIO VtyMissingTermEnvVar
274 Nothing -> throwIO VtyMissingTermEnvVar
294− Just t -> do
275+ Just t ->
295− mcolorMode <- detectColorMode t
296 return defaultConfig
276 return defaultConfig
297 { vmin = Just 1
277 { vmin = Just 1
298 , mouseMode = Just False
278 , mouseMode = Just False
@@ -301,7 +281,6 @@ standardIOConfig = do
301 , inputFd = Just stdInput
281 , inputFd = Just stdInput
302 , outputFd = Just stdOutput
282 , outputFd = Just stdOutput
303 , termName = Just t
283 , termName = Just t
304− , colorMode = Just mcolorMode
305 }
284 }
306
285
307parseConfigFile :: FilePath -> IO Config
286parseConfigFile :: FilePath -> IO Config
@@ -433,56 +412,3 @@ getTtyEraseChar fd = do
433 if c /= 0
412 if c /= 0
434 then return $ Just $ toEnum $ fromEnum c
413 then return $ Just $ toEnum $ fromEnum c
435 else return Nothing
414 else return Nothing
436−
437−data ConfigUpdateResult =
438− ConfigurationCreated
439− | ConfigurationModified
440− | ConfigurationConflict String
441− | ConfigurationRedundant
442− deriving (Eq, Show)
443−
444−-- | Add a @widthMap@ directive to the Vty configuration file at the
445−-- specified path.
446−--
447−-- If the configuration path refers to a configuration that already
448−-- contains the directive for the specified map and terminal type, the
449−-- configuration file will not be modified. If the file does not contain
450−-- the directive, it will be appended to the file.
451−--
452−-- If the configuration path does not exist, a new configuration file
453−-- will be created and any directories in the path will also be created.
454−--
455−-- This returns @True@ if the configuration was created or modified and
456−-- @False@ otherwise. This does not handle exceptions raised by file or
457−-- directory permissions issues.
458−addConfigWidthMap :: FilePath
459− -- ^ The configuration file path of the configuration
460− -- to modify or create.
461− -> String
462− -- ^ The @TERM@ value for the @widthMap@ directive.
463− -> FilePath
464− -- ^ The width table file path for the directive.
465− -> IO ConfigUpdateResult
466−addConfigWidthMap configPath term tablePath = do
467− configEx <- doesFileExist configPath
468− if configEx
469− then updateConfig
470− else createConfig >> return ConfigurationCreated
471−
472− where
473− directive = "widthMap " <> show term <> " " <> show tablePath <> "\n"
474−
475− createConfig = do
476− let dir = takeDirectory configPath
477− createDirectoryIfMissing True dir
478− writeFile configPath directive
479−
480− updateConfig = do
481− config <- parseConfigFile configPath
482− if (term, tablePath) `elem` termWidthMaps config
483− then return ConfigurationRedundant
484− else case lookup term (termWidthMaps config) of
485− Just other -> return $ ConfigurationConflict other
486− Nothing -> do
487− appendFile configPath directive
488− return ConfigurationModified
src/Graphics/Vty/DisplayAttributes.hs−3
@@ -96,8 +96,6 @@ data StyleStateChange
96 | RemoveStandout
96 | RemoveStandout
97 | ApplyItalic
97 | ApplyItalic
98 | RemoveItalic
98 | RemoveItalic
99− | ApplyStrikethrough
100− | RemoveStrikethrough
101 | ApplyUnderline
99 | ApplyUnderline
102 | RemoveUnderline
100 | RemoveUnderline
103 | ApplyReverseVideo
101 | ApplyReverseVideo
@@ -146,7 +144,6 @@ diffStyles prev cur
146 [ styleDiff standout ApplyStandout RemoveStandout
144 [ styleDiff standout ApplyStandout RemoveStandout
147 , styleDiff underline ApplyUnderline RemoveUnderline
145 , styleDiff underline ApplyUnderline RemoveUnderline
148 , styleDiff italic ApplyItalic RemoveItalic
146 , styleDiff italic ApplyItalic RemoveItalic
149− , styleDiff strikethrough ApplyStrikethrough RemoveStrikethrough
150 , styleDiff reverseVideo ApplyReverseVideo RemoveReverseVideo
147 , styleDiff reverseVideo ApplyReverseVideo RemoveReverseVideo
151 , styleDiff blink ApplyBlink RemoveBlink
148 , styleDiff blink ApplyBlink RemoveBlink
152 , styleDiff dim ApplyDim RemoveDim
149 , styleDiff dim ApplyDim RemoveDim
src/Graphics/Vty/Image.hs+10−11
@@ -1,4 +1,5 @@
1-- Copyright 2009-2010 Corey O'Connor
1-- Copyright 2009-2010 Corey O'Connor
2+{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE NamedFieldPuns #-}
3{-# LANGUAGE NamedFieldPuns #-}
3{-# LANGUAGE DisambiguateRecordFields #-}
4{-# LANGUAGE DisambiguateRecordFields #-}
4-- | A Vty program makes 'Picture's from 'Image's. This module provides
5-- | A Vty program makes 'Picture's from 'Image's. This module provides
@@ -116,16 +117,14 @@ horizCat = foldr horizJoin EmptyImage
116vertCat :: [Image] -> Image
117vertCat :: [Image] -> Image
117vertCat = foldr vertJoin EmptyImage
118vertCat = foldr vertJoin EmptyImage
118
119
119−-- | Make an 'Image' from a lazy text value. The text value should be
120+-- | Make an 'Image' from a lazy text value. This function should not be
120−-- sanitized of escape sequences (ASCII 27) and carriage returns;
121+-- given a text value containing escapes.
121−-- otherwise layout and attribute problems may result.
122text :: Attr -> TL.Text -> Image
122text :: Attr -> TL.Text -> Image
123text a txt = let displayWidth = safeWctlwidth txt
123text a txt = let displayWidth = safeWctlwidth txt
124 in HorizText a txt displayWidth (fromIntegral $! TL.length txt)
124 in HorizText a txt displayWidth (fromIntegral $! TL.length txt)
125
125
126−-- | Make an 'Image' from a text value. The text value should be
126+-- | Make an 'Image' from a text value. This function should not be
127−-- sanitized of escape sequences (ASCII 27) and carriage returns;
127+-- given a text value containing escapes.
128−-- otherwise layout and attribute problems may result.
129text' :: Attr -> T.Text -> Image
128text' :: Attr -> T.Text -> Image
130text' a txt = let displayWidth = safeWctwidth txt
129text' a txt = let displayWidth = safeWctwidth txt
131 in HorizText a (TL.fromStrict txt) displayWidth (T.length txt)
130 in HorizText a (TL.fromStrict txt) displayWidth (T.length txt)
@@ -137,11 +136,10 @@ char a c =
137 let displayWidth = safeWcwidth c
136 let displayWidth = safeWcwidth c
138 in HorizText a (TL.singleton c) displayWidth 1
137 in HorizText a (TL.singleton c) displayWidth 1
139
138
140−-- | Make an image from a string of characters laid out on a single
139+-- | Make an image from a string of characters layed out on a single
141-- row with the same display attribute. The string is assumed to be a
140-- row with the same display attribute. The string is assumed to be a
142−-- sequence of ISO-10646 characters. The input string should be
141+-- sequence of ISO-10646 characters. This function should not be given a
143−-- sanitized of escape sequences (ASCII 27) and carriage returns;
142+-- string containing escapes.
144−-- otherwise layout and attribute problems may result.
145--
143--
146-- Note: depending on how the Haskell compiler represents string
144-- Note: depending on how the Haskell compiler represents string
147-- literals, a string literal in a UTF-8 encoded source file, for
145-- literals, a string literal in a UTF-8 encoded source file, for
@@ -158,7 +156,8 @@ iso10646String a str =
158--
156--
159-- This is an alias for iso10646String since the usual case is that a
157-- This is an alias for iso10646String since the usual case is that a
160-- literal string like "foo" is represented internally as a list of ISO
158-- literal string like "foo" is represented internally as a list of ISO
161−-- 10646 31 bit characters.
159+-- 10646 31 bit characters. This function should not be given a string
160+-- containing escapes.
162--
161--
163-- Note: Keep in mind that GHC will compile source encoded as UTF-8
162-- Note: Keep in mind that GHC will compile source encoded as UTF-8
164-- but the literal strings, while UTF-8 encoded in the source, will be
163-- but the literal strings, while UTF-8 encoded in the source, will be
src/Graphics/Vty/Image/Internal.hs+3−3
@@ -146,7 +146,7 @@ data Image =
146
146
147-- | pretty print just the structure of an image.
147-- | pretty print just the structure of an image.
148ppImageStructure :: Image -> String
148ppImageStructure :: Image -> String
149−ppImageStructure = go 0
149+ppImageStructure inImg = go 0 inImg
150 where
150 where
151 go indent img = tab indent ++ pp indent img
151 go indent img = tab indent ++ pp indent img
152 tab indent = concat $ replicate indent " "
152 tab indent = concat $ replicate indent " "
@@ -228,7 +228,7 @@ instance Monoid Image where
228--
228--
229-- The result image will have a width equal to the sum of the two images
229-- The result image will have a width equal to the sum of the two images
230-- width. And the height will equal the largest height of the two
230-- width. And the height will equal the largest height of the two
231−-- images. The area not defined in one image due to a height mismatch
231+-- images. The area not defined in one image due to a height missmatch
232-- will be filled with the background pattern.
232-- will be filled with the background pattern.
233horizJoin :: Image -> Image -> Image
233horizJoin :: Image -> Image -> Image
234horizJoin EmptyImage i = i
234horizJoin EmptyImage i = i
@@ -259,7 +259,7 @@ horizJoin _ _ = error "horizJoin applied to undefined values."
259--
259--
260-- The result image will have a height equal to the sum of the heights
260-- The result image will have a height equal to the sum of the heights
261-- of both images. The width will equal the largest width of the two
261-- of both images. The width will equal the largest width of the two
262−-- images. The area not defined in one image due to a width mismatch
262+-- images. The area not defined in one image due to a width missmatch
263-- will be filled with the background pattern.
263-- will be filled with the background pattern.
264vertJoin :: Image -> Image -> Image
264vertJoin :: Image -> Image -> Image
265vertJoin EmptyImage i = i
265vertJoin EmptyImage i = i
src/Graphics/Vty/Inline.hs+7−5
@@ -1,3 +1,5 @@
1+{-# LANGUAGE BangPatterns #-}
2+
1-- | The inline module provides a limited interface to changing the
3-- | The inline module provides a limited interface to changing the
2-- style of terminal output. The intention is for this interface to be
4-- style of terminal output. The intention is for this interface to be
3-- used inline with other output systems.
5-- used inline with other output systems.
@@ -56,13 +58,13 @@ data InlineState =
56-- | Set the background color to the provided 'Color'.
58-- | Set the background color to the provided 'Color'.
57backColor :: Color -> InlineM ()
59backColor :: Color -> InlineM ()
58backColor c = modify $ \s ->
60backColor c = modify $ \s ->
59− s { inlineAttr = inlineAttr s `withBackColor` c
61+ s { inlineAttr = inlineAttr s `mappend` (currentAttr `withBackColor` c)
60 }
62 }
61
63
62-- | Set the foreground color to the provided 'Color'.
64-- | Set the foreground color to the provided 'Color'.
63foreColor :: Color -> InlineM ()
65foreColor :: Color -> InlineM ()
64foreColor c = modify $ \s ->
66foreColor c = modify $ \s ->
65− s { inlineAttr = inlineAttr s `withForeColor` c
67+ s { inlineAttr = inlineAttr s `mappend` (currentAttr `withForeColor` c)
66 }
68 }
67
69
68-- | Attempt to change the 'Style' of the following text..
70-- | Attempt to change the 'Style' of the following text..
@@ -71,7 +73,7 @@ foreColor c = modify $ \s ->
71-- produced. The style can still be removed.
73-- produced. The style can still be removed.
72applyStyle :: Style -> InlineM ()
74applyStyle :: Style -> InlineM ()
73applyStyle st = modify $ \s ->
75applyStyle st = modify $ \s ->
74− s { inlineAttr = inlineAttr s `withStyle` st
76+ s { inlineAttr = inlineAttr s `mappend` (currentAttr `withStyle` st)
75 }
77 }
76
78
77-- | Attempt to remove the specified 'Style' from the display of the
79-- | Attempt to remove the specified 'Style' from the display of the
@@ -83,8 +85,8 @@ removeStyle :: Style -> InlineM ()
83removeStyle sMask = modify $ \s ->
85removeStyle sMask = modify $ \s ->
84 s { inlineAttr =
86 s { inlineAttr =
85 let style' = case attrStyle (inlineAttr s) of
87 let style' = case attrStyle (inlineAttr s) of
86− Default -> error "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
88+ Default -> error $ "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
87− KeepCurrent -> error "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
89+ KeepCurrent -> error $ "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
88 SetTo st -> st .&. complement sMask
90 SetTo st -> st .&. complement sMask
89 in (inlineAttr s) { attrStyle = SetTo style' }
91 in (inlineAttr s) { attrStyle = SetTo style' }
90 }
92 }
src/Graphics/Vty/Input.hs+22−11
@@ -77,7 +77,7 @@
77-- The input encoding determines how UTF-8 encoded characters are
77-- The input encoding determines how UTF-8 encoded characters are
78-- recognized.
78-- recognized.
79--
79--
80−-- * 7-bit mode: UTF-8 can be input unambiguously. UTF-8 input is
80+-- * 7-bit mode: UTF-8 can be input unambiguiously. UTF-8 input is
81-- a superset of ASCII. UTF-8 does not overlap escaped control key
81-- a superset of ASCII. UTF-8 does not overlap escaped control key
82-- sequences. However, the escape key must be differentiated from
82-- sequences. However, the escape key must be differentiated from
83-- escaped control key sequences by the timing of the input bytes.
83-- escaped control key sequences by the timing of the input bytes.
@@ -95,7 +95,7 @@
95--
95--
96-- == Terminal Input is Broken
96-- == Terminal Input is Broken
97--
97--
98−-- Clearly terminal input has fundamental issues. There is no easy way
98+-- Clearly terminal input has fundemental issues. There is no easy way
99-- to reliably resolve these issues.
99-- to reliably resolve these issues.
100--
100--
101-- One resolution would be to ditch standard terminal interfaces
101-- One resolution would be to ditch standard terminal interfaces
@@ -143,8 +143,22 @@ import Data.Monoid ((<>))
143-- bytes comes from 'classifyMapForTerm' which is then overridden by
143-- bytes comes from 'classifyMapForTerm' which is then overridden by
144-- the the applicable entries from the configuration's 'inputMap'.
144-- the the applicable entries from the configuration's 'inputMap'.
145--
145--
146−-- The terminal device's mode flags are configured by the
146+-- The terminal device is configured with the attributes:
147−-- 'attributeControl' function.
147+--
148+-- * IXON disabled: disables software flow control on outgoing data.
149+-- This stops the process from being suspended if the output terminal
150+-- cannot keep up.
151+--
152+-- * Raw mode is used for input.
153+--
154+-- * ISIG disabled (enables keyboard combinations that result in
155+-- signals)
156+--
157+-- * ECHO disabled (input is not echoed to the output)
158+--
159+-- * ICANON disabled (canonical mode (line mode) input is not used)
160+--
161+-- * IEXTEN disabled (extended functions are disabled)
148inputForConfig :: Config -> IO Input
162inputForConfig :: Config -> IO Input
149inputForConfig config@Config{ termName = Just termName
163inputForConfig config@Config{ termName = Just termName
150 , inputFd = Just termFd
164 , inputFd = Just termFd
@@ -154,23 +168,20 @@ inputForConfig config@Config{ termName = Just termName
154 terminal <- Terminfo.setupTerm termName
168 terminal <- Terminfo.setupTerm termName
155 let inputOverrides = [(s,e) | (t,s,e) <- inputMap, t == Nothing || t == Just termName]
169 let inputOverrides = [(s,e) | (t,s,e) <- inputMap, t == Nothing || t == Just termName]
156 activeInputMap = classifyMapForTerm termName terminal `mappend` inputOverrides
170 activeInputMap = classifyMapForTerm termName terminal `mappend` inputOverrides
157− (setAttrs, unsetAttrs) <- attributeControl termFd
171+ (setAttrs,unsetAttrs) <- attributeControl termFd
158 setAttrs
172 setAttrs
159 input <- initInput config activeInputMap
173 input <- initInput config activeInputMap
160 let pokeIO = Catch $ do
174 let pokeIO = Catch $ do
175+ let e = error "vty internal failure: this value should not propagate to users"
161 setAttrs
176 setAttrs
162− atomically $ writeTChan (input^.eventChannel) ResumeAfterSignal
177+ atomically $ writeTChan (input^.eventChannel) (EvResize e e)
163 _ <- installHandler windowChange pokeIO Nothing
178 _ <- installHandler windowChange pokeIO Nothing
164 _ <- installHandler continueProcess pokeIO Nothing
179 _ <- installHandler continueProcess pokeIO Nothing
165−
166− let restore = unsetAttrs
167−
168 return $ input
180 return $ input
169 { shutdownInput = do
181 { shutdownInput = do
170 shutdownInput input
182 shutdownInput input
171 _ <- installHandler windowChange Ignore Nothing
183 _ <- installHandler windowChange Ignore Nothing
172 _ <- installHandler continueProcess Ignore Nothing
184 _ <- installHandler continueProcess Ignore Nothing
173− restore
185+ unsetAttrs
174− , restoreInputState = restoreInputState input >> restore
175 }
186 }
176inputForConfig config = (<> config) <$> standardIOConfig >>= inputForConfig
187inputForConfig config = (<> config) <$> standardIOConfig >>= inputForConfig
src/Graphics/Vty/Input/Classify.hs+29−53
@@ -1,11 +1,10 @@
1{-# OPTIONS_HADDOCK hide #-}
1{-# OPTIONS_HADDOCK hide #-}
2−-- This makes a kind of trie. Has space efficiency issues with large
2+-- This makes a kind of tri. Has space efficiency issues with large
3-- input blocks. Likely building a parser and just applying that would
3-- input blocks. Likely building a parser and just applying that would
4-- be better.
4-- be better.
5module Graphics.Vty.Input.Classify
5module Graphics.Vty.Input.Classify
6 ( classify
6 ( classify
7 , KClass(..)
7 , KClass(..)
8− , ClassifierState(..)
9 )
8 )
10where
9where
11
10
@@ -17,39 +16,25 @@ import Graphics.Vty.Input.Classify.Types
17
16
18import Codec.Binary.UTF8.Generic (decode)
17import Codec.Binary.UTF8.Generic (decode)
19
18
20−import Control.Arrow (first)
19+import Data.List (inits)
21import qualified Data.Map as M( fromList, lookup )
20import qualified Data.Map as M( fromList, lookup )
22import Data.Maybe ( mapMaybe )
21import Data.Maybe ( mapMaybe )
23import qualified Data.Set as S( fromList, member )
22import qualified Data.Set as S( fromList, member )
24
23
24+import Data.Char
25import Data.Word
25import Data.Word
26
26
27−import qualified Data.ByteString as BS
28−import qualified Data.ByteString.Char8 as BS8
29−import Data.ByteString.Char8 (ByteString)
30−
31−-- | Whether the classifier is currently processing a chunked format.
32−-- Currently, only bracketed pastes use this.
33−data ClassifierState
34− = ClassifierStart
35− -- ^ Not processing a chunked format.
36− | ClassifierInChunk ByteString [ByteString]
37− -- ^ Currently processing a chunked format. The initial chunk is in the
38− -- first argument and a reversed remainder of the chunks is collected in
39− -- the second argument. At the end of the processing, the chunks are
40− -- reversed and concatenated with the final chunk.
41−
42−compile :: ClassifyMap -> ByteString -> KClass
27+compile :: ClassifyMap -> [Char] -> KClass
43compile table = cl' where
28compile table = cl' where
44 -- take all prefixes and create a set of these
29 -- take all prefixes and create a set of these
45− prefixSet = S.fromList $ concatMap (init . BS.inits . BS8.pack . fst) table
30+ prefixSet = S.fromList $ concatMap (init . inits . fst) $ table
46 maxValidInputLength = maximum (map (length . fst) table)
31 maxValidInputLength = maximum (map (length . fst) table)
47− eventForInput = M.fromList $ map (first BS8.pack) table
32+ eventForInput = M.fromList table
48− cl' inputBlock | BS8.null inputBlock = Prefix
33+ cl' [] = Prefix
49 cl' inputBlock = case M.lookup inputBlock eventForInput of
34 cl' inputBlock = case M.lookup inputBlock eventForInput of
50 -- if the inputBlock is exactly what is expected for an
35 -- if the inputBlock is exactly what is expected for an
51 -- event then consume the whole block and return the event
36 -- event then consume the whole block and return the event
52− Just e -> Valid e BS8.empty
37+ Just e -> Valid e []
53 Nothing -> case S.member inputBlock prefixSet of
38 Nothing -> case S.member inputBlock prefixSet of
54 True -> Prefix
39 True -> Prefix
55 -- look up progressively smaller tails of the input
40 -- look up progressively smaller tails of the input
@@ -60,49 +45,40 @@ compile table = cl' where
60 -- H: There will always be one match. The prefixSet
45 -- H: There will always be one match. The prefixSet
61 -- contains, by definition, all prefixes of an event.
46 -- contains, by definition, all prefixes of an event.
62 False ->
47 False ->
63− let inputPrefixes = reverse . take maxValidInputLength . tail . BS8.inits $ inputBlock
48+ let inputPrefixes = reverse $ take maxValidInputLength $ tail $ inits inputBlock
64 in case mapMaybe (\s -> (,) s `fmap` M.lookup s eventForInput) inputPrefixes of
49 in case mapMaybe (\s -> (,) s `fmap` M.lookup s eventForInput) inputPrefixes of
65− (s,e) : _ -> Valid e (BS8.drop (BS8.length s) inputBlock)
50+ (s,e) : _ -> Valid e (drop (length s) inputBlock)
66 -- neither a prefix or a full event.
51 -- neither a prefix or a full event.
67 [] -> Invalid
52 [] -> Invalid
68
53
69−classify :: ClassifyMap -> ClassifierState -> ByteString -> KClass
54+classify :: ClassifyMap -> [Char] -> KClass
70−classify table = process
55+classify table =
71− where
72− standardClassifier = compile table
56+ let standardClassifier = compile table
73−
74− process ClassifierStart s =
75− case BS.uncons s of
57+ in \s -> case s of
76− _ | bracketedPasteStarted s ->
58+ _ | bracketedPasteStarted s ->
77− if bracketedPasteFinished s
78− then parseBracketedPaste s
79− else Chunk
80− _ | isMouseEvent s -> classifyMouseEvent s
81− _ | isFocusEvent s -> classifyFocusEvent s
82− Just (c,cs) | c >= 0xC2 -> classifyUtf8 c cs
83− _ -> standardClassifier s
84−
85− process (ClassifierInChunk p ps) s | bracketedPasteStarted p =
86 if bracketedPasteFinished s
59 if bracketedPasteFinished s
87− then parseBracketedPaste $ BS.concat $ p:reverse (s:ps)
60+ then parseBracketedPaste s
88− else Chunk
61+ else Prefix
89− process ClassifierInChunk{} _ = Invalid
62+ _ | isMouseEvent s -> classifyMouseEvent s
63+ _ | isFocusEvent s -> classifyFocusEvent s
64+ c:cs | ord c >= 0xC2 -> classifyUtf8 c cs
65+ _ -> standardClassifier s
90
66
91−classifyUtf8 :: Word8 -> ByteString -> KClass
67+classifyUtf8 :: Char -> [Char] -> KClass
92classifyUtf8 c cs =
68classifyUtf8 c cs =
93− let n = utf8Length c
69+ let n = utf8Length (ord c)
94− (codepoint,rest) = BS8.splitAt (n - 1) cs
70+ (codepoint,rest) = splitAt n (c:cs)
95
71
96 codepoint8 :: [Word8]
72 codepoint8 :: [Word8]
97− codepoint8 = c:BS.unpack codepoint
73+ codepoint8 = map (fromIntegral . ord) codepoint
98
74
99 in case decode codepoint8 of
75 in case decode codepoint8 of
100− _ | n < BS.length codepoint + 1 -> Prefix
76+ _ | n < length codepoint -> Prefix
101− Just (unicodeChar, _) -> Valid (EvKey (KChar unicodeChar) []) rest
77+ Just (unicodeChar, _) -> Valid (EvKey (KChar unicodeChar) []) rest
102 -- something bad happened; just ignore and continue.
78 -- something bad happened; just ignore and continue.
103− Nothing -> Invalid
79+ Nothing -> Invalid
104
80
105−utf8Length :: Word8 -> Int
81+utf8Length :: (Num t, Ord a, Num a) => a -> t
106utf8Length c
82utf8Length c
107 | c < 0x80 = 1
83 | c < 0x80 = 1
108 | c < 0xE0 = 2
84 | c < 0xE0 = 2
src/Graphics/Vty/Input/Classify/Parse.hs+7−10
@@ -16,15 +16,12 @@ import Graphics.Vty.Input.Classify.Types
16import Control.Monad.Trans.Maybe
16import Control.Monad.Trans.Maybe
17import Control.Monad.State
17import Control.Monad.State
18
18
19−import qualified Data.ByteString.Char8 as BS8
20−import Data.ByteString.Char8 (ByteString)
21−
22−type Parser a = MaybeT (State ByteString) a
19+type Parser a = MaybeT (State String) a
23
20
24-- | Run a parser on a given input string. If the parser fails, return
21-- | Run a parser on a given input string. If the parser fails, return
25-- 'Invalid'. Otherwise return the valid event ('Valid') and the
22-- 'Invalid'. Otherwise return the valid event ('Valid') and the
26-- remaining unparsed characters.
23-- remaining unparsed characters.
27−runParser :: ByteString -> Parser Event -> KClass
24+runParser :: String -> Parser Event -> KClass
28runParser s parser =
25runParser s parser =
29 case runState (runMaybeT parser) s of
26 case runState (runMaybeT parser) s of
30 (Nothing, _) -> Invalid
27 (Nothing, _) -> Invalid
@@ -39,9 +36,9 @@ failParse = fail "invalid parse"
39-- return '123' and consume those characters.
36-- return '123' and consume those characters.
40readInt :: Parser Int
37readInt :: Parser Int
41readInt = do
38readInt = do
42− s <- BS8.unpack <$> get
39+ s <- get
43 case (reads :: ReadS Int) s of
40 case (reads :: ReadS Int) s of
44− [(i, rest)] -> put (BS8.pack rest) >> return i
41+ [(i, rest)] -> put rest >> return i
45 _ -> failParse
42 _ -> failParse
46
43
47-- | Read a character from the input stream. If one cannot be read (e.g.
44-- | Read a character from the input stream. If one cannot be read (e.g.
@@ -49,9 +46,9 @@ readInt = do
49readChar :: Parser Char
46readChar :: Parser Char
50readChar = do
47readChar = do
51 s <- get
48 s <- get
52− case BS8.uncons s of
49+ case s of
53− Just (c,rest) -> put rest >> return c
50+ c:rest -> put rest >> return c
54− Nothing -> failParse
51+ _ -> failParse
55
52
56-- | Read a character from the input stream and fail parsing if it is
53-- | Read a character from the input stream and fail parsing if it is
57-- not the specified character.
54-- not the specified character.
src/Graphics/Vty/Input/Classify/Types.hs+1−7
@@ -1,6 +1,5 @@
1-- | This module exports the input classification type to avoid import
1-- | This module exports the input classification type to avoid import
2-- cycles between other modules that need this.
2-- cycles between other modules that need this.
3−{-# LANGUAGE StrictData #-}
4module Graphics.Vty.Input.Classify.Types
3module Graphics.Vty.Input.Classify.Types
5 ( KClass(..)
4 ( KClass(..)
6 )
5 )
@@ -8,10 +7,8 @@ where
8
7
9import Graphics.Vty.Input.Events
8import Graphics.Vty.Input.Events
10
9
11−import Data.ByteString.Char8 (ByteString)
12−
13data KClass
10data KClass
14− = Valid Event ByteString
11+ = Valid Event [Char]
15 -- ^ A valid event was parsed. Any unused characters from the input
12 -- ^ A valid event was parsed. Any unused characters from the input
16 -- stream are also provided.
13 -- stream are also provided.
17 | Invalid
14 | Invalid
@@ -19,7 +16,4 @@ data KClass
19 | Prefix
16 | Prefix
20 -- ^ The input characters form the prefix of a valid event character
17 -- ^ The input characters form the prefix of a valid event character
21 -- sequence.
18 -- sequence.
22− | Chunk
23− -- ^ The input characters are either start of a bracketed paste chunk
24− -- or in the middle of a bracketed paste chunk.
25 deriving(Show, Eq)
19 deriving(Show, Eq)
src/Graphics/Vty/Input/Events.hs+6−24
@@ -1,8 +1,6 @@
1{-# Language DeriveGeneric #-}
1{-# Language DeriveGeneric #-}
2−{-# Language StrictData #-}
3module Graphics.Vty.Input.Events where
2module Graphics.Vty.Input.Events where
4
3
5−import Control.DeepSeq
6import Data.ByteString
4import Data.ByteString
7import GHC.Generics
5import GHC.Generics
8
6
@@ -16,29 +14,23 @@ import GHC.Generics
16--
14--
17-- * Actually, support for most of these but KEsc, KChar, KBS, and
15-- * Actually, support for most of these but KEsc, KChar, KBS, and
18-- KEnter vary by terminal and keyboard.
16-- KEnter vary by terminal and keyboard.
19−data Key = KEsc | KChar {-# UNPACK #-} Char | KBS | KEnter
17+data Key = KEsc | KChar Char | KBS | KEnter
20 | KLeft | KRight | KUp | KDown
18 | KLeft | KRight | KUp | KDown
21 | KUpLeft | KUpRight | KDownLeft | KDownRight | KCenter
19 | KUpLeft | KUpRight | KDownLeft | KDownRight | KCenter
22− | KFun {-# UNPACK #-} Int | KBackTab | KPrtScr | KPause | KIns
20+ | KFun Int | KBackTab | KPrtScr | KPause | KIns
23 | KHome | KPageUp | KDel | KEnd | KPageDown | KBegin | KMenu
21 | KHome | KPageUp | KDel | KEnd | KPageDown | KBegin | KMenu
24 deriving (Eq,Show,Read,Ord,Generic)
22 deriving (Eq,Show,Read,Ord,Generic)
25
23
26−instance NFData Key
27−
28-- | Modifier keys. Key codes are interpreted such that users are more
24-- | Modifier keys. Key codes are interpreted such that users are more
29-- likely to have Meta than Alt; for instance on the PC Linux console,
25-- likely to have Meta than Alt; for instance on the PC Linux console,
30-- 'MMeta' will generally correspond to the physical Alt key.
26-- 'MMeta' will generally correspond to the physical Alt key.
31data Modifier = MShift | MCtrl | MMeta | MAlt
27data Modifier = MShift | MCtrl | MMeta | MAlt
32 deriving (Eq,Show,Read,Ord,Generic)
28 deriving (Eq,Show,Read,Ord,Generic)
33
29
34−instance NFData Modifier
35−
36-- | Mouse buttons.
30-- | Mouse buttons.
37data Button = BLeft | BMiddle | BRight | BScrollUp | BScrollDown
31data Button = BLeft | BMiddle | BRight | BScrollUp | BScrollDown
38 deriving (Eq,Show,Read,Ord,Generic)
32 deriving (Eq,Show,Read,Ord,Generic)
39
33
40−instance NFData Button
41−
42-- | Events.
34-- | Events.
43data Event
35data Event
44 = EvKey Key [Modifier]
36 = EvKey Key [Modifier]
@@ -52,8 +44,10 @@ data Event
52 -- without specifying which one; in that case, Nothing is provided.
44 -- without specifying which one; in that case, Nothing is provided.
53 -- Otherwise Just the button released is included in the event.
45 -- Otherwise Just the button released is included in the event.
54 | EvResize Int Int
46 | EvResize Int Int
55− -- The terminal window was resized and the size is provided in the
47+ -- ^ If read from 'eventChannel' this is the size at the time of the
56− -- integer fields (width, height).
48+ -- signal. If read from 'nextEvent' this is the size at the time the
49+ -- event was processed by Vty. Typically these are the same, but if
50+ -- somebody is resizing the terminal quickly they can be different.
57 | EvPaste ByteString
51 | EvPaste ByteString
58 -- ^ A paste event occurs when a bracketed paste input sequence is
52 -- ^ A paste event occurs when a bracketed paste input sequence is
59 -- received. For terminals that support bracketed paste mode, these
53 -- received. For terminals that support bracketed paste mode, these
@@ -68,16 +62,4 @@ data Event
68 -- ^ The terminal running the application gained input focus.
62 -- ^ The terminal running the application gained input focus.
69 deriving (Eq,Show,Read,Ord,Generic)
63 deriving (Eq,Show,Read,Ord,Generic)
70
64
71−instance NFData Event
72−
73type ClassifyMap = [(String,Event)]
65type ClassifyMap = [(String,Event)]
74−
75−-- | The type of internal events that drive the internal Vty event
76−-- dispatching to the application.
77−data InternalEvent =
78− ResumeAfterSignal
79− -- ^ Vty resumed operation after the process was interrupted with a
80− -- signal. In practice this translates into a screen redraw in the
81− -- input event loop.
82− | InputEvent Event
83− -- ^ An input event was received.
src/Graphics/Vty/Input/Focus.hs+13−15
@@ -11,32 +11,30 @@ import Graphics.Vty.Input.Classify.Types
11import Graphics.Vty.Input.Classify.Parse
11import Graphics.Vty.Input.Classify.Parse
12
12
13import Control.Monad.State
13import Control.Monad.State
14−
14+import Data.List (isPrefixOf)
15−import qualified Data.ByteString.Char8 as BS8
16−import Data.ByteString.Char8 (ByteString)
17
15
18-- | These sequences set xterm-based terminals to send focus event
16-- | These sequences set xterm-based terminals to send focus event
19-- sequences.
17-- sequences.
20−requestFocusEvents :: ByteString
18+requestFocusEvents :: String
21−requestFocusEvents = BS8.pack "\ESC[?1004h"
19+requestFocusEvents = "\ESC[?1004h"
22
20
23-- | These sequences disable focus events.
21-- | These sequences disable focus events.
24−disableFocusEvents :: ByteString
22+disableFocusEvents :: String
25−disableFocusEvents = BS8.pack "\ESC[?1004l"
23+disableFocusEvents = "\ESC[?1004l"
26
24
27-- | Does the specified string begin with a focus event?
25-- | Does the specified string begin with a focus event?
28−isFocusEvent :: ByteString -> Bool
26+isFocusEvent :: String -> Bool
29−isFocusEvent s = BS8.isPrefixOf focusIn s ||
27+isFocusEvent s = isPrefixOf focusIn s ||
30− BS8.isPrefixOf focusOut s
28+ isPrefixOf focusOut s
31
29
32−focusIn :: ByteString
30+focusIn :: String
33−focusIn = BS8.pack "\ESC[I"
31+focusIn = "\ESC[I"
34
32
35−focusOut :: ByteString
33+focusOut :: String
36−focusOut = BS8.pack "\ESC[O"
34+focusOut = "\ESC[O"
37
35
38-- | Attempt to classify an input string as a focus event.
36-- | Attempt to classify an input string as a focus event.
39−classifyFocusEvent :: ByteString -> KClass
37+classifyFocusEvent :: String -> KClass
40classifyFocusEvent s = runParser s $ do
38classifyFocusEvent s = runParser s $ do
41 when (not $ isFocusEvent s) failParse
39 when (not $ isFocusEvent s) failParse
42
40
src/Graphics/Vty/Input/Loop.hs+29−86
@@ -1,9 +1,8 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE NoMonomorphismRestriction #-}
3{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5−{-# LANGUAGE TemplateHaskell #-}
6{-# OPTIONS_HADDOCK hide #-}
2{-# OPTIONS_HADDOCK hide #-}
3+{-# LANGUAGE NoMonomorphismRestriction #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE CPP #-}
7-- | The input layer used to be a single function that correctly
6-- | The input layer used to be a single function that correctly
8-- accounted for the non-threaded runtime by emulating the terminal
7-- accounted for the non-threaded runtime by emulating the terminal
9-- VMIN adn VTIME handling. This has been removed and replace with a
8-- VMIN adn VTIME handling. This has been removed and replace with a
@@ -34,15 +33,12 @@ import Control.Monad.Trans.State (StateT(..), evalStateT)
34import Control.Monad.State.Class (MonadState, modify)
33import Control.Monad.State.Class (MonadState, modify)
35import Control.Monad.Trans.Reader (ReaderT(..))
34import Control.Monad.Trans.Reader (ReaderT(..))
36
35
37−import qualified Data.ByteString.Char8 as BS8
36+import Data.Char
38−import qualified Data.ByteString as BS
39−import Data.ByteString.Char8 (ByteString)
40import Data.IORef
37import Data.IORef
41import Data.Word (Word8)
38import Data.Word (Word8)
42
39
43−import Foreign (allocaArray)
40+import Foreign ( allocaArray, peekArray, Ptr )
44import Foreign.C.Types (CInt(..))
41import Foreign.C.Types (CInt(..))
45−import Foreign.Ptr (Ptr, castPtr)
46
42
47import System.IO
43import System.IO
48import System.Posix.IO (fdReadBuf, setFdOption, FdOption(..))
44import System.Posix.IO (fdReadBuf, setFdOption, FdOption(..))
@@ -55,15 +51,10 @@ data Input = Input
55 { -- | Channel of events direct from input processing. Unlike
51 { -- | Channel of events direct from input processing. Unlike
56 -- 'nextEvent' this will not refresh the display if the next event
52 -- 'nextEvent' this will not refresh the display if the next event
57 -- is an 'EvResize'.
53 -- is an 'EvResize'.
58− _eventChannel :: TChan InternalEvent
54+ _eventChannel :: TChan Event
59− -- | Shuts down the input processing. As part of shutting down the
55+ -- | Shuts down the input processing. This should return the
60− -- input, this should also restore the input state.
56+ -- terminal input state to before he input initialized.
61 , shutdownInput :: IO ()
57 , shutdownInput :: IO ()
62− -- | Restore the terminal's input state to what it was prior
63− -- to configuring input for Vty. This should be done as part of
64− -- 'shutdownInput' but is exposed in case you need to access it
65− -- directly.
66− , restoreInputState :: IO ()
67 -- | Changes to this value are reflected after the next event.
58 -- | Changes to this value are reflected after the next event.
68 , _configRef :: IORef Config
59 , _configRef :: IORef Config
69 -- | input debug log
60 -- | input debug log
@@ -80,11 +71,10 @@ data InputBuffer = InputBuffer
80makeLenses ''InputBuffer
71makeLenses ''InputBuffer
81
72
82data InputState = InputState
73data InputState = InputState
83− { _unprocessedBytes :: ByteString
74+ { _unprocessedBytes :: String
84− , _classifierState :: ClassifierState
85 , _appliedConfig :: Config
75 , _appliedConfig :: Config
86 , _inputBuffer :: InputBuffer
76 , _inputBuffer :: InputBuffer
87− , _classifier :: ClassifierState -> ByteString -> KClass
77+ , _classifier :: String -> KClass
88 }
78 }
89
79
90makeLenses ''InputState
80makeLenses ''InputState
@@ -109,20 +99,20 @@ loopInputProcessor = do
109 dropInvalid
99 dropInvalid
110 loopInputProcessor
100 loopInputProcessor
111
101
112−addBytesToProcess :: ByteString -> InputM ()
102+addBytesToProcess :: String -> InputM ()
113addBytesToProcess block = unprocessedBytes <>= block
103addBytesToProcess block = unprocessedBytes <>= block
114
104
115emit :: Event -> InputM ()
105emit :: Event -> InputM ()
116emit event = do
106emit event = do
117 logMsg $ "parsed event: " ++ show event
107 logMsg $ "parsed event: " ++ show event
118− view eventChannel >>= liftIO . atomically . flip writeTChan (InputEvent event)
108+ view eventChannel >>= liftIO . atomically . flip writeTChan event
119
109
120-- The timing requirements are assured by the VMIN and VTIME set for the
110-- The timing requirements are assured by the VMIN and VTIME set for the
121-- device.
111-- device.
122--
112--
123-- Precondition: Under the threaded runtime. Only current use is from a
113-- Precondition: Under the threaded runtime. Only current use is from a
124-- forkOS thread. That case satisfies precondition.
114-- forkOS thread. That case satisfies precondition.
125−readFromDevice :: InputM ByteString
115+readFromDevice :: InputM String
126readFromDevice = do
116readFromDevice = do
127 newConfig <- view configRef >>= liftIO . readIORef
117 newConfig <- view configRef >>= liftIO . readIORef
128 oldConfig <- use appliedConfig
118 oldConfig <- use appliedConfig
@@ -142,10 +132,9 @@ readFromDevice = do
142 threadWaitRead fd
132 threadWaitRead fd
143 bytesRead <- fdReadBuf fd bufferPtr (fromIntegral maxBytes)
133 bytesRead <- fdReadBuf fd bufferPtr (fromIntegral maxBytes)
144 if bytesRead > 0
134 if bytesRead > 0
145− then BS.packCStringLen (castPtr bufferPtr, fromIntegral bytesRead)
135+ then fmap (map $ chr . fromIntegral) $ peekArray (fromIntegral bytesRead) bufferPtr
146− else return BS.empty
136+ else return []
147− when (not $ BS.null stringRep) $
148− logMsg $ "input bytes: " ++ show (BS8.unpack stringRep)
137+ when (not $ null stringRep) $ logMsg $ "input bytes: " ++ show stringRep
149 return stringRep
138 return stringRep
150
139
151applyConfig :: Fd -> Config -> IO ()
140applyConfig :: Fd -> Config -> IO ()
@@ -156,86 +145,41 @@ applyConfig _ _ = fail "(vty) applyConfig was not provided a complete configurat
156parseEvent :: InputM Event
145parseEvent :: InputM Event
157parseEvent = do
146parseEvent = do
158 c <- use classifier
147 c <- use classifier
159− s <- use classifierState
160 b <- use unprocessedBytes
148 b <- use unprocessedBytes
161− case c s b of
149+ case c b of
162 Valid e remaining -> do
150 Valid e remaining -> do
163 logMsg $ "valid parse: " ++ show e
151 logMsg $ "valid parse: " ++ show e
164 logMsg $ "remaining: " ++ show remaining
152 logMsg $ "remaining: " ++ show remaining
165− classifierState .= ClassifierStart
166 unprocessedBytes .= remaining
153 unprocessedBytes .= remaining
167 return e
154 return e
168− _ -> mzero
155+ _ -> mzero
169
156
170dropInvalid :: InputM ()
157dropInvalid :: InputM ()
171dropInvalid = do
158dropInvalid = do
172 c <- use classifier
159 c <- use classifier
173− s <- use classifierState
174 b <- use unprocessedBytes
160 b <- use unprocessedBytes
175− case c s b of
176− Chunk -> do
177− classifierState .=
178− case s of
179− ClassifierStart -> ClassifierInChunk b []
180− ClassifierInChunk p bs -> ClassifierInChunk p (b:bs)
181− unprocessedBytes .= BS8.empty
182− Invalid -> do
161+ when (c b == Invalid) $ do
183− logMsg "dropping input bytes"
162+ logMsg "dropping input bytes"
184− classifierState .= ClassifierStart
185− unprocessedBytes .= BS8.empty
163+ unprocessedBytes .= []
186− _ -> return ()
187
164
188runInputProcessorLoop :: ClassifyMap -> Input -> IO ()
165runInputProcessorLoop :: ClassifyMap -> Input -> IO ()
189runInputProcessorLoop classifyTable input = do
166runInputProcessorLoop classifyTable input = do
190 let bufferSize = 1024
167 let bufferSize = 1024
191 allocaArray bufferSize $ \(bufferPtr :: Ptr Word8) -> do
168 allocaArray bufferSize $ \(bufferPtr :: Ptr Word8) -> do
192− s0 <- InputState BS8.empty ClassifierStart
193− <$> readIORef (_configRef input)
169+ s0 <- InputState [] <$> readIORef (_configRef input)
194− <*> pure (InputBuffer bufferPtr bufferSize)
170+ <*> pure (InputBuffer bufferPtr bufferSize)
195− <*> pure (classify classifyTable)
171+ <*> pure (classify classifyTable)
196 runReaderT (evalStateT loopInputProcessor s0) input
172 runReaderT (evalStateT loopInputProcessor s0) input
197
173
198−-- | Construct two IO actions: one to configure the terminal for Vty and
199−-- one to restore the terminal mode flags to the values they had at the
200−-- time this function was called.
201−--
202−-- This function constructs a configuration action to clear the
203−-- following terminal mode flags:
204−--
205−-- * IXON disabled: disables software flow control on outgoing data.
206−-- This stops the process from being suspended if the output terminal
207−-- cannot keep up.
208−--
209−-- * Raw mode is used for input.
210−--
211−-- * ISIG (enables keyboard combinations that result in
212−-- signals)
213−--
214−-- * ECHO (input is not echoed to the output)
215−--
216−-- * ICANON (canonical mode (line mode) input is not used)
217−--
218−-- * IEXTEN (extended functions are disabled)
219−--
220−-- The configuration action also explicitly sets these flags:
221−--
222−-- * ICRNL (input carriage returns are mapped to newlines)
223attributeControl :: Fd -> IO (IO (), IO ())
174attributeControl :: Fd -> IO (IO (), IO ())
224attributeControl fd = do
175attributeControl fd = do
225 original <- getTerminalAttributes fd
176 original <- getTerminalAttributes fd
226− let vtyMode = foldl withMode clearedFlags flagsToSet
227− clearedFlags = foldl withoutMode original flagsToUnset
228− flagsToSet = [ MapCRtoLF -- ICRNL
229− ]
230− flagsToUnset = [ StartStopOutput -- IXON
231− , KeyboardInterrupts -- ISIG
177+ let vtyMode = foldl withoutMode original [ StartStopOutput, KeyboardInterrupts
232− , EnableEcho -- ECHO
233− , ProcessInput -- ICANON
234− , ExtendedFunctions -- IEXTEN
178+ , EnableEcho, ProcessInput, ExtendedFunctions
235− ]
179+ ]
236 let setAttrs = setTerminalAttributes fd vtyMode Immediately
180 let setAttrs = setTerminalAttributes fd vtyMode Immediately
237 unsetAttrs = setTerminalAttributes fd original Immediately
181 unsetAttrs = setTerminalAttributes fd original Immediately
238− return (setAttrs, unsetAttrs)
182+ return (setAttrs,unsetAttrs)
239
183
240logInitialInputState :: Input -> ClassifyMap -> IO()
184logInitialInputState :: Input -> ClassifyMap -> IO()
241logInitialInputState input classifyTable = case _inputDebug input of
185logInitialInputState input classifyTable = case _inputDebug input of
@@ -243,7 +187,7 @@ logInitialInputState input classifyTable = case _inputDebug input of
243 Just h -> do
187 Just h -> do
244 Config{ vmin = Just theVmin
188 Config{ vmin = Just theVmin
245 , vtime = Just theVtime
189 , vtime = Just theVtime
246− , termName = Just theTerm } <- readIORef $ _configRef input
190+ , termName = Just theTerm, .. } <- readIORef $ _configRef input
247 _ <- hPrintf h "initial (vmin,vtime): %s\n" (show (theVmin, theVtime))
191 _ <- hPrintf h "initial (vmin,vtime): %s\n" (show (theVmin, theVtime))
248 forM_ classifyTable $ \i -> case i of
192 forM_ classifyTable $ \i -> case i of
249 (inBytes, EvKey k mods) -> hPrintf h "map %s %s %s %s\n" (show theTerm)
193 (inBytes, EvKey k mods) -> hPrintf h "map %s %s %s %s\n" (show theTerm)
@@ -259,7 +203,6 @@ initInput config classifyTable = do
259 applyConfig fd config
203 applyConfig fd config
260 stopSync <- newEmptyMVar
204 stopSync <- newEmptyMVar
261 input <- Input <$> atomically newTChan
205 input <- Input <$> atomically newTChan
262− <*> pure (return ())
263 <*> pure (return ())
206 <*> pure (return ())
264 <*> newIORef config
207 <*> newIORef config
265 <*> maybe (return Nothing)
208 <*> maybe (return Nothing)
src/Graphics/Vty/Input/Mouse.hs+17−19
@@ -15,12 +15,10 @@ import Graphics.Vty.Input.Classify.Types
15import Graphics.Vty.Input.Classify.Parse
15import Graphics.Vty.Input.Classify.Parse
16
16
17import Control.Monad.State
17import Control.Monad.State
18+import Data.List (isPrefixOf)
18import Data.Maybe (catMaybes)
19import Data.Maybe (catMaybes)
19import Data.Bits ((.&.))
20import Data.Bits ((.&.))
20
21
21−import qualified Data.ByteString.Char8 as BS8
22−import Data.ByteString.Char8 (ByteString)
23−
24-- A mouse event in SGR extended mode is
22-- A mouse event in SGR extended mode is
25--
23--
26-- '\ESC' '[' '<' B ';' X ';' Y ';' ('M'|'m')
24-- '\ESC' '[' '<' B ';' X ';' Y ';' ('M'|'m')
@@ -34,28 +32,28 @@ import Data.ByteString.Char8 (ByteString)
34
32
35-- | These sequences set xterm-based terminals to send mouse event
33-- | These sequences set xterm-based terminals to send mouse event
36-- sequences.
34-- sequences.
37−requestMouseEvents :: ByteString
35+requestMouseEvents :: String
38−requestMouseEvents = BS8.pack "\ESC[?1000h\ESC[?1002h\ESC[?1006h"
36+requestMouseEvents = "\ESC[?1000h\ESC[?1002h\ESC[?1006h"
39
37
40-- | These sequences disable mouse events.
38-- | These sequences disable mouse events.
41−disableMouseEvents :: ByteString
39+disableMouseEvents :: String
42−disableMouseEvents = BS8.pack "\ESC[?1000l\ESC[?1002l\ESC[?1006l"
40+disableMouseEvents = "\ESC[?1000l\ESC[?1002l\ESC[?1006l"
43
41
44-- | Does the specified string begin with a mouse event?
42-- | Does the specified string begin with a mouse event?
45−isMouseEvent :: ByteString -> Bool
43+isMouseEvent :: String -> Bool
46isMouseEvent s = isSGREvent s || isNormalEvent s
44isMouseEvent s = isSGREvent s || isNormalEvent s
47
45
48−isSGREvent :: ByteString -> Bool
46+isSGREvent :: String -> Bool
49−isSGREvent = BS8.isPrefixOf sgrPrefix
47+isSGREvent = isPrefixOf sgrPrefix
50
48
51−sgrPrefix :: ByteString
49+sgrPrefix :: String
52−sgrPrefix = BS8.pack "\ESC[M"
50+sgrPrefix = "\ESC[M"
53
51
54−isNormalEvent :: ByteString -> Bool
52+isNormalEvent :: String -> Bool
55−isNormalEvent = BS8.isPrefixOf normalPrefix
53+isNormalEvent = isPrefixOf normalPrefix
56
54
57−normalPrefix :: ByteString
55+normalPrefix :: String
58−normalPrefix = BS8.pack "\ESC[<"
56+normalPrefix = "\ESC[<"
59
57
60-- Modifier bits:
58-- Modifier bits:
61shiftBit :: Int
59shiftBit :: Int
@@ -89,8 +87,8 @@ scrollDown = 65
89hasBitSet :: Int -> Int -> Bool
87hasBitSet :: Int -> Int -> Bool
90hasBitSet val bit = val .&. bit > 0
88hasBitSet val bit = val .&. bit > 0
91
89
92−-- | Attempt to classify an input string as a mouse event.
90+-- | Attempt to lassify an input string as a mouse event.
93−classifyMouseEvent :: ByteString -> KClass
91+classifyMouseEvent :: String -> KClass
94classifyMouseEvent s = runParser s $ do
92classifyMouseEvent s = runParser s $ do
95 when (not $ isMouseEvent s) failParse
93 when (not $ isMouseEvent s) failParse
96
94
@@ -102,7 +100,7 @@ classifyMouseEvent s = runParser s $ do
102 'M' -> classifyNormalMouseEvent
100 'M' -> classifyNormalMouseEvent
103 _ -> failParse
101 _ -> failParse
104
102
105−-- Given a modifier/button value, determine which button was indicated
103+-- Given a modifer/button value, determine which button was indicated
106getSGRButton :: Int -> Parser Button
104getSGRButton :: Int -> Parser Button
107getSGRButton mods =
105getSGRButton mods =
108 let buttonMap = [ (leftButton, BLeft)
106 let buttonMap = [ (leftButton, BLeft)
src/Graphics/Vty/Input/Paste.hs+24−16
@@ -9,33 +9,41 @@ module Graphics.Vty.Input.Paste
9where
9where
10
10
11import qualified Data.ByteString.Char8 as BS8
11import qualified Data.ByteString.Char8 as BS8
12−import Data.ByteString.Char8 (ByteString)
13
12
14import Graphics.Vty.Input.Events
13import Graphics.Vty.Input.Events
15import Graphics.Vty.Input.Classify.Types
14import Graphics.Vty.Input.Classify.Types
16
15
17−bracketedPasteStart :: ByteString
16+import Data.List (isPrefixOf, isInfixOf)
18−bracketedPasteStart = BS8.pack "\ESC[200~"
19
17
18+bracketedPasteStart :: String
19+bracketedPasteStart = "\ESC[200~"
20+
20−bracketedPasteEnd :: ByteString
21+bracketedPasteEnd :: String
21−bracketedPasteEnd = BS8.pack "\ESC[201~"
22+bracketedPasteEnd = "\ESC[201~"
22
23
23-- | Does the input start a bracketed paste?
24-- | Does the input start a bracketed paste?
24−bracketedPasteStarted :: ByteString -> Bool
25+bracketedPasteStarted :: String -> Bool
25−bracketedPasteStarted = BS8.isPrefixOf bracketedPasteStart
26+bracketedPasteStarted = isPrefixOf bracketedPasteStart
26
27
27-- | Does the input contain a complete bracketed paste?
28-- | Does the input contain a complete bracketed paste?
28−bracketedPasteFinished :: ByteString -> Bool
29+bracketedPasteFinished :: String -> Bool
29−bracketedPasteFinished = BS8.isInfixOf bracketedPasteEnd
30+bracketedPasteFinished = isInfixOf bracketedPasteEnd
30
31
31-- | Parse a bracketed paste. This should only be called on a string if
32-- | Parse a bracketed paste. This should only be called on a string if
32-- both 'bracketedPasteStarted' and 'bracketedPasteFinished' return
33-- both 'bracketedPasteStarted' and 'bracketedPasteFinished' return
33-- 'True'.
34-- 'True'.
34−parseBracketedPaste :: ByteString -> KClass
35+parseBracketedPaste :: String -> KClass
35parseBracketedPaste s =
36parseBracketedPaste s =
37+ let (p, rest) = takeUntil (drop (length bracketedPasteStart) s) bracketedPasteEnd
38+ rest' = if bracketedPasteEnd `isPrefixOf` rest
39+ then drop (length bracketedPasteEnd) rest
40+ else rest
36− Valid (EvPaste p) (BS8.drop endLen rest')
41+ in Valid (EvPaste $ BS8.pack p) rest'
37− where
42+
38− startLen = BS8.length bracketedPasteStart
43+takeUntil :: (Eq a) => [a] -> [a] -> ([a],[a])
39− endLen = BS8.length bracketedPasteEnd
44+takeUntil [] _ = ([], [])
40− (_, rest ) = BS8.breakSubstring bracketedPasteStart s
45+takeUntil cs sub
41− (p, rest') = BS8.breakSubstring bracketedPasteEnd . BS8.drop startLen $ rest
46+ | length cs < length sub = (cs, [])
47+ | take (length sub) cs == sub = ([], drop (length sub) cs)
48+ | otherwise = let (pre, suf) = takeUntil (tail cs) sub
49+ in (head cs:pre, suf)
src/Graphics/Vty/Input/Terminfo.hs+4−6
@@ -74,7 +74,7 @@ visibleChars = [ ([x], EvKey (KChar x) [])
74ctrlChars :: ClassifyMap
74ctrlChars :: ClassifyMap
75ctrlChars =
75ctrlChars =
76 [ ([toEnum x],EvKey (KChar y) [MCtrl])
76 [ ([toEnum x],EvKey (KChar y) [MCtrl])
77− | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_'])
77+ | (x,y) <- zip ([0..31]) ('@':['a'..'z']++['['..'_'])
78 , y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
78 , y /= 'i' -- Resolve issue #3 where CTRL-i hides TAB.
79 , y /= 'h' -- CTRL-h should not hide BS
79 , y /= 'h' -- CTRL-h should not hide BS
80 ]
80 ]
@@ -86,12 +86,10 @@ ctrlMetaChars = map (\(s,EvKey c m) -> ('\ESC':s, EvKey c (MMeta:m))) ctrlChars
86-- | Esc, meta-esc, delete, meta-delete, enter, meta-enter.
86-- | Esc, meta-esc, delete, meta-delete, enter, meta-enter.
87specialSupportKeys :: ClassifyMap
87specialSupportKeys :: ClassifyMap
88specialSupportKeys =
88specialSupportKeys =
89− [ ("\ESC\ESC[5~",EvKey KPageUp [MMeta])
90− , ("\ESC\ESC[6~",EvKey KPageDown [MMeta])
91− -- special support for ESC
89+ [ -- special support for ESC
92− , ("\ESC",EvKey KEsc []), ("\ESC\ESC",EvKey KEsc [MMeta])
90+ ("\ESC",EvKey KEsc []), ("\ESC\ESC",EvKey KEsc [MMeta])
93 -- Special support for backspace
91 -- Special support for backspace
94− , ("\DEL",EvKey KBS []), ("\ESC\DEL",EvKey KBS [MMeta]), ("\b",EvKey KBS [])
92+ , ("\DEL",EvKey KBS []), ("\ESC\DEL",EvKey KBS [MMeta])
95 -- Special support for Enter
93 -- Special support for Enter
96 , ("\ESC\^J",EvKey KEnter [MMeta]), ("\^J",EvKey KEnter [])
94 , ("\ESC\^J",EvKey KEnter [MMeta]), ("\^J",EvKey KEnter [])
97 -- explicit support for tab
95 -- explicit support for tab
src/Graphics/Vty/Input/Terminfo/ANSIVT.hs+1−1
@@ -59,7 +59,7 @@ navKeys3 =
59-- This encoding depends on the terminal.
59-- This encoding depends on the terminal.
60functionKeys1 :: ClassifyMap
60functionKeys1 :: ClassifyMap
61functionKeys1 =
61functionKeys1 =
62− let f ff nrs m = [ ("\ESC["++show n++"~",EvKey (KFun $ n-head nrs+ff) m) | n <- nrs ] in
62+ let f ff nrs m = [ ("\ESC["++show n++"~",EvKey (KFun $ n-(nrs!!0)+ff) m) | n <- nrs ] in
63 concat [f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ]
63 concat [f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ]
64
64
65-- | encoding for meta plus char
65-- | encoding for meta plus char
src/Graphics/Vty/Output.hs+5−6
@@ -1,4 +1,4 @@
1−{-# LANGUAGE RecordWildCards, CPP #-}
1+{-# LANGUAGE RecordWildCards, NamedFieldPuns, CPP #-}
2-- | This module provides functions for accessing the current terminal
2-- | This module provides functions for accessing the current terminal
3-- or a specific terminal device.
3-- or a specific terminal device.
4--
4--
@@ -58,12 +58,11 @@ import Data.Monoid ((<>))
58-- * If TERM contains "xterm" or "screen", use XTermColor.
58-- * If TERM contains "xterm" or "screen", use XTermColor.
59-- * otherwise use the TerminfoBased driver.
59-- * otherwise use the TerminfoBased driver.
60outputForConfig :: Config -> IO Output
60outputForConfig :: Config -> IO Output
61−outputForConfig Config{ outputFd = Just fd, termName = Just termName
61+outputForConfig Config{ outputFd = Just fd, termName = Just termName, .. } = do
62− , colorMode = Just colorMode, .. } = do
63 t <- if "xterm" `isPrefixOf` termName || "screen" `isPrefixOf` termName
62 t <- if "xterm" `isPrefixOf` termName || "screen" `isPrefixOf` termName
64− then XTermColor.reserveTerminal termName fd colorMode
63+ then XTermColor.reserveTerminal termName fd
65 -- Not an xterm-like terminal. try for generic terminfo.
64 -- Not an xterm-like terminal. try for generic terminfo.
66− else TerminfoBased.reserveTerminal termName fd colorMode
65+ else TerminfoBased.reserveTerminal termName fd
67
66
68 case mouseMode of
67 case mouseMode of
69 Just s -> setMode t Mouse s
68 Just s -> setMode t Mouse s
@@ -78,7 +77,7 @@ outputForConfig config = (<> config) <$> standardIOConfig >>= outputForConfig
78
77
79-- | Sets the cursor position to the given output column and row.
78-- | Sets the cursor position to the given output column and row.
80--
79--
81−-- This is not necessarily the same as the character position with the
80+-- This is not necessarially the same as the character position with the
82-- same coordinates. Characters can be a variable number of columns in
81-- same coordinates. Characters can be a variable number of columns in
83-- width.
82-- width.
84--
83--
src/Graphics/Vty/Output/Interface.hs+18−47
@@ -1,9 +1,9 @@
1-- Copyright Corey O'Connor
1-- Copyright Corey O'Connor
2+{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE RankNTypes #-}
3{-# LANGUAGE RankNTypes #-}
3{-# LANGUAGE ExistentialQuantification #-}
4{-# LANGUAGE ExistentialQuantification #-}
4{-# LANGUAGE GADTs #-}
5{-# LANGUAGE GADTs #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleContexts #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7-- | This module provides an abstract interface for performing terminal
7-- | This module provides an abstract interface for performing terminal
8-- output. The only user-facing part of this API is 'Output'.
8-- output. The only user-facing part of this API is 'Output'.
9module Graphics.Vty.Output.Interface
9module Graphics.Vty.Output.Interface
@@ -73,12 +73,13 @@ data Output = Output
73 -- | Return the display to the state before `reserveDisplay` If no
73 -- | Return the display to the state before `reserveDisplay` If no
74 -- previous state then set the display state to the initial state.
74 -- previous state then set the display state to the initial state.
75 , releaseDisplay :: IO ()
75 , releaseDisplay :: IO ()
76− -- | Sets the current display bounds (width, height).
77− , setDisplayBounds :: (Int, Int) -> IO ()
78 -- | Returns the current display bounds.
76 -- | Returns the current display bounds.
79 , displayBounds :: IO DisplayRegion
77 , displayBounds :: IO DisplayRegion
80 -- | Output the bytestring to the terminal device.
78 -- | Output the bytestring to the terminal device.
81 , outputByteBuffer :: BS.ByteString -> IO ()
79 , outputByteBuffer :: BS.ByteString -> IO ()
80+ -- | Specifies the maximum number of colors supported by the
81+ -- context.
82+ , contextColorCount :: Int
82 -- | Specifies whether the cursor can be shown / hidden.
83 -- | Specifies whether the cursor can be shown / hidden.
83 , supportsCursorVisibility :: Bool
84 , supportsCursorVisibility :: Bool
84 -- | Indicates support for terminal modes for this output device.
85 -- | Indicates support for terminal modes for this output device.
@@ -98,24 +99,6 @@ data Output = Output
98 , ringTerminalBell :: IO ()
99 , ringTerminalBell :: IO ()
99 -- | Returns whether the terminal has an audio bell feature.
100 -- | Returns whether the terminal has an audio bell feature.
100 , supportsBell :: IO Bool
101 , supportsBell :: IO Bool
101− -- | Returns whether the terminal supports italicized text.
102− --
103− -- This is terminal-dependent and should make a best effort to
104− -- determine whether this feature is supported, but even if the
105− -- terminal advertises support (e.g. via terminfo) that might not
106− -- be a reliable indicator of whether the feature will work as
107− -- desired.
108− , supportsItalics :: IO Bool
109− -- | Returns whether the terminal supports strikethrough text.
110− --
111− -- This is terminal-dependent and should make a best effort to
112− -- determine whether this feature is supported, but even if the
113− -- terminal advertises support (e.g. via terminfo) that might not
114− -- be a reliable indicator of whether the feature will work as
115− -- desired.
116− , supportsStrikethrough :: IO Bool
117− -- | Returns how many colors the terminal supports.
118− , outputColorMode :: ColorMode
119 }
102 }
120
103
121displayContext :: Output -> DisplayRegion -> IO DisplayContext
104displayContext :: Output -> DisplayRegion -> IO DisplayContext
@@ -206,12 +189,6 @@ outputPicture dc pic = do
206 AbsoluteCursor x y ->
189 AbsoluteCursor x y ->
207 writeShowCursor dc `mappend`
190 writeShowCursor dc `mappend`
208 writeMoveCursor dc (clampX x) (clampY y)
191 writeMoveCursor dc (clampX x) (clampY y)
209− PositionOnly isAbs x y ->
210− if isAbs
211− then writeMoveCursor dc (clampX x) (clampY y)
212− else let (ox, oy) = charToOutputPos m (clampX x, clampY y)
213− m = cursorOutputMap ops $ picCursor pic
214− in writeMoveCursor dc (clampX ox) (clampY oy)
215 Cursor x y ->
192 Cursor x y ->
216 let m = cursorOutputMap ops $ picCursor pic
193 let m = cursorOutputMap ops $ picCursor pic
217 (ox, oy) = charToOutputPos m (clampX x, clampY y)
194 (ox, oy) = charToOutputPos m (clampX x, clampY y)
@@ -309,23 +286,17 @@ limitAttrForDisplay t attr
309 where
286 where
310 clampColor Default = Default
287 clampColor Default = Default
311 clampColor KeepCurrent = KeepCurrent
288 clampColor KeepCurrent = KeepCurrent
312− clampColor (SetTo c) = clampColor' (outputColorMode t) c
289+ clampColor (SetTo c) = clampColor' c
313−
314− clampColor' NoColor _ = Default
290+ clampColor' (ISOColor v)
315−
291+ | contextColorCount t < 8 = Default
316− clampColor' ColorMode8 (ISOColor v)
317− | v >= 8 = SetTo $ ISOColor (v - 8)
292+ | contextColorCount t < 16 && v >= 8 = SetTo $ ISOColor (v - 8)
318− | otherwise = SetTo $ ISOColor v
293+ | otherwise = SetTo $ ISOColor v
319− clampColor' ColorMode8 _ = Default
294+ clampColor' (Color240 v)
320−
295+ -- Should we choose closest ISO color?
321− clampColor' ColorMode16 c@(ISOColor _) = SetTo c
296+ | contextColorCount t < 8 = Default
322− clampColor' ColorMode16 _ = Default
297+ | contextColorCount t < 16 = Default
323−
298+ | contextColorCount t <= 256 = SetTo $ Color240 v
324− clampColor' (ColorMode240 _) c@(ISOColor _) = SetTo c
325− clampColor' (ColorMode240 colorCount) c@(Color240 n)
326− | n <= colorCount = SetTo c
327− | otherwise = Default
299+ | otherwise
328− clampColor' colorMode@(ColorMode240 _) (RGBColor r g b) =
300+ = let p :: Double = fromIntegral v / 240.0
329− clampColor' colorMode (color240 r g b)
301+ v' = floor $ p * (fromIntegral $ contextColorCount t)
330−
302+ in SetTo $ Color240 v'
331− clampColor' FullColor c = SetTo c
src/Graphics/Vty/Output/Mock.hs+2−6
@@ -11,7 +11,6 @@ module Graphics.Vty.Output.Mock
11where
11where
12
12
13import Graphics.Vty.Image (DisplayRegion)
13import Graphics.Vty.Image (DisplayRegion)
14−import Graphics.Vty.Attributes.Color (ColorMode(ColorMode16))
15import Graphics.Vty.Output.Interface
14import Graphics.Vty.Output.Interface
16
15
17import Blaze.ByteString.Builder.Word (writeWord8)
16import Blaze.ByteString.Builder.Word (writeWord8)
@@ -31,7 +30,7 @@ type MockData = IORef (UTF8.UTF8 BS.ByteString)
31-- without considering terminal specific issues.
30-- without considering terminal specific issues.
32--
31--
33-- The mock implementation is useful in manually determining if the
32-- The mock implementation is useful in manually determining if the
34−-- sequence of terminal operations matches the expected sequence. The
33+-- sequence of terminal operations matche the expected sequence. The
35-- requirement of the produced representation is simplicity in parsing
34-- requirement of the produced representation is simplicity in parsing
36-- the text representation and determining how the picture was mapped to
35-- the text representation and determining how the picture was mapped to
37-- terminal operations.
36-- terminal operations.
@@ -49,19 +48,16 @@ mockTerminal r = liftIO $ do
49 , releaseDisplay = return ()
48 , releaseDisplay = return ()
50 , ringTerminalBell = return ()
49 , ringTerminalBell = return ()
51 , supportsBell = return False
50 , supportsBell = return False
52− , supportsItalics = return False
53− , supportsStrikethrough = return False
54− , setDisplayBounds = const $ return ()
55 , displayBounds = return r
51 , displayBounds = return r
56 , outputByteBuffer = \bytes -> do
52 , outputByteBuffer = \bytes -> do
57 putStrLn $ "mock outputByteBuffer of " ++ show (BS.length bytes) ++ " bytes"
53 putStrLn $ "mock outputByteBuffer of " ++ show (BS.length bytes) ++ " bytes"
58 writeIORef outRef $ UTF8.fromRep bytes
54 writeIORef outRef $ UTF8.fromRep bytes
55+ , contextColorCount = 16
59 , supportsCursorVisibility = True
56 , supportsCursorVisibility = True
60 , supportsMode = const False
57 , supportsMode = const False
61 , setMode = const $ const $ return ()
58 , setMode = const $ const $ return ()
62 , getModeStatus = const $ return False
59 , getModeStatus = const $ return False
63 , assumedStateRef = newAssumedStateRef
60 , assumedStateRef = newAssumedStateRef
64− , outputColorMode = ColorMode16
65 , mkDisplayContext = \tActual rActual -> return $ DisplayContext
61 , mkDisplayContext = \tActual rActual -> return $ DisplayContext
66 { contextRegion = rActual
62 { contextRegion = rActual
67 , contextDevice = tActual
63 , contextDevice = tActual
src/Graphics/Vty/Output/TerminfoBased.hs+39−106
@@ -1,3 +1,4 @@
1+{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE CPP #-}
4{-# LANGUAGE CPP #-}
@@ -9,12 +10,10 @@
9-- Copyright Corey O'Connor (coreyoconnor@gmail.com)
10-- Copyright Corey O'Connor (coreyoconnor@gmail.com)
10module Graphics.Vty.Output.TerminfoBased
11module Graphics.Vty.Output.TerminfoBased
11 ( reserveTerminal
12 ( reserveTerminal
12− , setWindowSize
13 )
13 )
14where
14where
15
15
16import Control.Monad (when)
16import Control.Monad (when)
17−import Data.Bits (shiftL, (.&.))
18import qualified Data.ByteString as BS
17import qualified Data.ByteString as BS
19import Data.ByteString.Internal (toForeignPtr)
18import Data.ByteString.Internal (toForeignPtr)
20import Data.Terminfo.Parse
19import Data.Terminfo.Parse
@@ -25,8 +24,9 @@ import Graphics.Vty.Image (DisplayRegion)
25import Graphics.Vty.DisplayAttributes
24import Graphics.Vty.DisplayAttributes
26import Graphics.Vty.Output.Interface
25import Graphics.Vty.Output.Interface
27
26
28−import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable, writeWord8)
27+import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable)
29
28
29+import Data.Bits ((.&.))
30import Data.IORef
30import Data.IORef
31import Data.Maybe (isJust, isNothing, fromJust)
31import Data.Maybe (isJust, isNothing, fromJust)
32import Data.Word
32import Data.Word
@@ -49,6 +49,7 @@ data TerminfoCaps = TerminfoCaps
49 , cup :: CapExpression
49 , cup :: CapExpression
50 , cnorm :: Maybe CapExpression
50 , cnorm :: Maybe CapExpression
51 , civis :: Maybe CapExpression
51 , civis :: Maybe CapExpression
52+ , supportsNoColors :: Bool
52 , useAltColorMap :: Bool
53 , useAltColorMap :: Bool
53 , setForeColor :: CapExpression
54 , setForeColor :: CapExpression
54 , setBackColor :: CapExpression
55 , setBackColor :: CapExpression
@@ -65,8 +66,6 @@ data DisplayAttrCaps = DisplayAttrCaps
65 , exitStandout :: Maybe CapExpression
66 , exitStandout :: Maybe CapExpression
66 , enterItalic :: Maybe CapExpression
67 , enterItalic :: Maybe CapExpression
67 , exitItalic :: Maybe CapExpression
68 , exitItalic :: Maybe CapExpression
68− , enterStrikethrough :: Maybe CapExpression
69− , exitStrikethrough :: Maybe CapExpression
70 , enterUnderline :: Maybe CapExpression
69 , enterUnderline :: Maybe CapExpression
71 , exitUnderline :: Maybe CapExpression
70 , exitUnderline :: Maybe CapExpression
72 , enterReverseVideo :: Maybe CapExpression
71 , enterReverseVideo :: Maybe CapExpression
@@ -103,28 +102,28 @@ sendCapToTerminal t cap capParams = do
103--
102--
104-- * Providing independent string capabilities for all display
103-- * Providing independent string capabilities for all display
105-- attributes.
104-- attributes.
106−reserveTerminal :: String -> Fd -> ColorMode -> IO Output
105+reserveTerminal :: String -> Fd -> IO Output
107−reserveTerminal termName outFd colorMode = do
106+reserveTerminal termName outFd = do
108 ti <- Terminfo.setupTerm termName
107 ti <- Terminfo.setupTerm termName
109 -- assumes set foreground always implies set background exists.
108 -- assumes set foreground always implies set background exists.
110 -- if set foreground is not set then all color changing style
109 -- if set foreground is not set then all color changing style
111 -- attributes are filtered.
110 -- attributes are filtered.
112 msetaf <- probeCap ti "setaf"
111 msetaf <- probeCap ti "setaf"
113 msetf <- probeCap ti "setf"
112 msetf <- probeCap ti "setf"
114− let (useAlt, setForeCap)
113+ let (noColors, useAlt, setForeCap)
115 = case msetaf of
114 = case msetaf of
116− Just setaf -> (False, setaf)
115+ Just setaf -> (False, False, setaf)
117 Nothing -> case msetf of
116 Nothing -> case msetf of
118− Just setf -> (True, setf)
117+ Just setf -> (False, True, setf)
119− Nothing -> (True, error $ "no fore color support for terminal " ++ termName)
118+ Nothing -> (True, True, error $ "no fore color support for terminal " ++ termName)
120 msetab <- probeCap ti "setab"
119 msetab <- probeCap ti "setab"
121 msetb <- probeCap ti "setb"
120 msetb <- probeCap ti "setb"
122− let setBackCap
121+ let set_back_cap
123 = case msetab of
122 = case msetab of
124− Just setab -> setab
125 Nothing -> case msetb of
123 Nothing -> case msetb of
126 Just setb -> setb
124 Just setb -> setb
127 Nothing -> error $ "no back color support for terminal " ++ termName
125 Nothing -> error $ "no back color support for terminal " ++ termName
126+ Just setab -> setab
128
127
129 hyperlinkModeStatus <- newIORef False
128 hyperlinkModeStatus <- newIORef False
130 newAssumedStateRef <- newIORef initialAssumedState
129 newAssumedStateRef <- newIORef initialAssumedState
@@ -150,9 +149,10 @@ reserveTerminal termName outFd colorMode = do
150 <*> requireCap ti "cup"
149 <*> requireCap ti "cup"
151 <*> probeCap ti "cnorm"
150 <*> probeCap ti "cnorm"
152 <*> probeCap ti "civis"
151 <*> probeCap ti "civis"
152+ <*> pure noColors
153 <*> pure useAlt
153 <*> pure useAlt
154 <*> pure setForeCap
154 <*> pure setForeCap
155− <*> pure setBackCap
155+ <*> pure set_back_cap
156 <*> requireCap ti "sgr0"
156 <*> requireCap ti "sgr0"
157 <*> requireCap ti "clear"
157 <*> requireCap ti "clear"
158 <*> requireCap ti "el"
158 <*> requireCap ti "el"
@@ -164,10 +164,6 @@ reserveTerminal termName outFd colorMode = do
164 sendCap setDefaultAttr []
164 sendCap setDefaultAttr []
165 maybeSendCap cnorm []
165 maybeSendCap cnorm []
166 , supportsBell = return $ isJust $ ringBellAudio terminfoCaps
166 , supportsBell = return $ isJust $ ringBellAudio terminfoCaps
167− , supportsItalics = return $ (isJust $ enterItalic (displayAttrCaps terminfoCaps)) &&
168− (isJust $ exitItalic (displayAttrCaps terminfoCaps))
169− , supportsStrikethrough = return $ (isJust $ enterStrikethrough (displayAttrCaps terminfoCaps)) &&
170− (isJust $ exitStrikethrough (displayAttrCaps terminfoCaps))
171 , ringTerminalBell = maybeSendCap ringBellAudio []
167 , ringTerminalBell = maybeSendCap ringBellAudio []
172 , reserveDisplay = do
168 , reserveDisplay = do
173 -- If there is no support for smcup: Clear the screen
169 -- If there is no support for smcup: Clear the screen
@@ -178,8 +174,6 @@ reserveTerminal termName outFd colorMode = do
178 , releaseDisplay = do
174 , releaseDisplay = do
179 maybeSendCap rmcup []
175 maybeSendCap rmcup []
180 maybeSendCap cnorm []
176 maybeSendCap cnorm []
181− , setDisplayBounds = \(w, h) ->
182− setWindowSize outFd (w, h)
183 , displayBounds = do
177 , displayBounds = do
184 rawSize <- getWindowSize outFd
178 rawSize <- getWindowSize outFd
185 case rawSize of
179 case rawSize of
@@ -192,15 +186,20 @@ reserveTerminal termName outFd colorMode = do
192 when (toEnum len /= actualLen) $ fail $ "Graphics.Vty.Output: outputByteBuffer "
186 when (toEnum len /= actualLen) $ fail $ "Graphics.Vty.Output: outputByteBuffer "
193 ++ "length mismatch. " ++ show len ++ " /= " ++ show actualLen
187 ++ "length mismatch. " ++ show len ++ " /= " ++ show actualLen
194 ++ " Please report this bug to vty project."
188 ++ " Please report this bug to vty project."
189+ , contextColorCount
190+ = case supportsNoColors terminfoCaps of
191+ False -> case Terminfo.getCapability ti (Terminfo.tiGetNum "colors" ) of
192+ Nothing -> 8
193+ Just v -> toEnum v
194+ True -> 1
195 , supportsCursorVisibility = isJust $ civis terminfoCaps
195 , supportsCursorVisibility = isJust $ civis terminfoCaps
196 , supportsMode = terminfoModeSupported
196 , supportsMode = terminfoModeSupported
197 , setMode = terminfoSetMode
197 , setMode = terminfoSetMode
198 , getModeStatus = terminfoModeStatus
198 , getModeStatus = terminfoModeStatus
199 , assumedStateRef = newAssumedStateRef
199 , assumedStateRef = newAssumedStateRef
200− , outputColorMode = colorMode
201 -- I think fix would help assure tActual is the only
200 -- I think fix would help assure tActual is the only
202 -- reference. I was having issues tho.
201 -- reference. I was having issues tho.
203− , mkDisplayContext = (`terminfoDisplayContext` terminfoCaps)
202+ , mkDisplayContext = \tActual -> terminfoDisplayContext tActual terminfoCaps
204 }
203 }
205 sendCap s = sendCapToTerminal t (s terminfoCaps)
204 sendCap s = sendCapToTerminal t (s terminfoCaps)
206 maybeSendCap s = when (isJust $ s terminfoCaps) . sendCap (fromJust . s)
205 maybeSendCap s = when (isJust $ s terminfoCaps) . sendCap (fromJust . s)
@@ -232,8 +231,6 @@ currentDisplayAttrCaps ti
232 <*> probeCap ti "rmso"
231 <*> probeCap ti "rmso"
233 <*> probeCap ti "sitm"
232 <*> probeCap ti "sitm"
234 <*> probeCap ti "ritm"
233 <*> probeCap ti "ritm"
235− <*> probeCap ti "smxx"
236− <*> probeCap ti "rmxx"
237 <*> probeCap ti "smul"
234 <*> probeCap ti "smul"
238 <*> probeCap ti "rmul"
235 <*> probeCap ti "rmul"
239 <*> probeCap ti "rev"
236 <*> probeCap ti "rev"
@@ -247,13 +244,6 @@ getWindowSize fd = do
247 (a,b) <- (`divMod` 65536) `fmap` c_getWindowSize fd
244 (a,b) <- (`divMod` 65536) `fmap` c_getWindowSize fd
248 return (fromIntegral b, fromIntegral a)
245 return (fromIntegral b, fromIntegral a)
249
246
250−foreign import ccall "gwinsz.h vty_c_set_window_size" c_setWindowSize :: Fd -> CLong -> IO ()
251−
252−setWindowSize :: Fd -> (Int, Int) -> IO ()
253−setWindowSize fd (w, h) = do
254− let val = (h `shiftL` 16) + w
255− c_setWindowSize fd $ fromIntegral val
256−
257terminfoDisplayContext :: Output -> TerminfoCaps -> DisplayRegion -> IO DisplayContext
247terminfoDisplayContext :: Output -> TerminfoCaps -> DisplayRegion -> IO DisplayContext
258terminfoDisplayContext tActual terminfoCaps r = return dc
248terminfoDisplayContext tActual terminfoCaps r = return dc
259 where dc = DisplayContext
249 where dc = DisplayContext
@@ -269,11 +259,7 @@ terminfoDisplayContext tActual terminfoCaps r = return dc
269 , writeSetAttr = terminfoWriteSetAttr dc terminfoCaps
259 , writeSetAttr = terminfoWriteSetAttr dc terminfoCaps
270 , writeDefaultAttr = \urlsEnabled ->
260 , writeDefaultAttr = \urlsEnabled ->
271 writeCapExpr (setDefaultAttr terminfoCaps) [] `mappend`
261 writeCapExpr (setDefaultAttr terminfoCaps) [] `mappend`
272− (if urlsEnabled then writeURLEscapes EndLink else mempty) `mappend`
262+ (if urlsEnabled then writeURLEscapes EndLink else mempty)
273− (case exitStrikethrough $ displayAttrCaps terminfoCaps of
274− Just cap -> writeCapExpr cap []
275− Nothing -> mempty
276− )
277 , writeRowEnd = writeCapExpr (clearEol terminfoCaps) []
263 , writeRowEnd = writeCapExpr (clearEol terminfoCaps) []
278 , inlineHack = return ()
264 , inlineHack = return ()
279 }
265 }
@@ -295,7 +281,7 @@ writeURLEscapes NoLinkChange =
295-- | Portably setting the display attributes is a giant pain in the ass.
281-- | Portably setting the display attributes is a giant pain in the ass.
296--
282--
297-- If the terminal supports the sgr capability (which sets the on/off
283-- If the terminal supports the sgr capability (which sets the on/off
298−-- state of each style directly; and, for no good reason, resets the
284+-- state of each style directly ; and, for no good reason, resets the
299-- colors to the default) this procedure is used:
285-- colors to the default) this procedure is used:
300--
286--
301-- 0. set the style attributes. This resets the fore and back color.
287-- 0. set the style attributes. This resets the fore and back color.
@@ -334,9 +320,9 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
334 -- The only way to reset either color, portably, to the default
320 -- The only way to reset either color, portably, to the default
335 -- is to use either the set state capability or the set default
321 -- is to use either the set state capability or the set default
336 -- capability.
322 -- capability.
337− True -> do
323+ True -> do
338 case reqDisplayCapSeqFor (displayAttrCaps terminfoCaps)
324 case reqDisplayCapSeqFor (displayAttrCaps terminfoCaps)
339− (fixedStyle attr)
325+ (fixedStyle attr )
340 (styleToApplySeq $ fixedStyle attr) of
326 (styleToApplySeq $ fixedStyle attr) of
341 -- only way to reset a color to the defaults
327 -- only way to reset a color to the defaults
342 EnterExitSeq caps -> writeDefaultAttr dc urlsEnabled
328 EnterExitSeq caps -> writeDefaultAttr dc urlsEnabled
@@ -346,11 +332,11 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
346 setColors
332 setColors
347 -- implicitly resets the colors to the defaults
333 -- implicitly resets the colors to the defaults
348 SetState state -> writeCapExpr (fromJust $ setAttrStates
334 SetState state -> writeCapExpr (fromJust $ setAttrStates
349− $ displayAttrCaps terminfoCaps
335+ $ displayAttrCaps
336+ $ terminfoCaps
350 )
337 )
351 (sgrArgsForState state)
338 (sgrArgsForState state)
352 `mappend` setItalics
339 `mappend` setItalics
353− `mappend` setStrikethrough
354 `mappend` setColors
340 `mappend` setColors
355 -- Otherwise the display colors are not changing or changing
341 -- Otherwise the display colors are not changing or changing
356 -- between two non-default points.
342 -- between two non-default points.
@@ -369,16 +355,15 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
369 -- applied states.
355 -- applied states.
370 EnterExitSeq caps -> foldMap (\cap -> writeCapExpr cap []) caps
356 EnterExitSeq caps -> foldMap (\cap -> writeCapExpr cap []) caps
371 `mappend`
357 `mappend`
372− writeColorDiff Foreground (foreColorDiff diffs)
358+ writeColorDiff setForeColor (foreColorDiff diffs)
373 `mappend`
359 `mappend`
374− writeColorDiff Background (backColorDiff diffs)
360+ writeColorDiff setBackColor (backColorDiff diffs)
375 -- implicitly resets the colors to the defaults
361 -- implicitly resets the colors to the defaults
376 SetState state -> writeCapExpr (fromJust $ setAttrStates
362 SetState state -> writeCapExpr (fromJust $ setAttrStates
377 $ displayAttrCaps terminfoCaps
363 $ displayAttrCaps terminfoCaps
378 )
364 )
379 (sgrArgsForState state)
365 (sgrArgsForState state)
380 `mappend` setItalics
366 `mappend` setItalics
381− `mappend` setStrikethrough
382 `mappend` setColors
367 `mappend` setColors
383 where
368 where
384 urlAttrs True = writeURLEscapes (urlDiff diffs)
369 urlAttrs True = writeURLEscapes (urlDiff diffs)
@@ -396,72 +381,31 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
396 , Just sitm <- enterItalic (displayAttrCaps terminfoCaps)
381 , Just sitm <- enterItalic (displayAttrCaps terminfoCaps)
397 = writeCapExpr sitm []
382 = writeCapExpr sitm []
398 | otherwise = mempty
383 | otherwise = mempty
399− setStrikethrough
400− | hasStyle (fixedStyle attr) strikethrough
401− , Just smxx <- enterStrikethrough (displayAttrCaps terminfoCaps)
402− = writeCapExpr smxx []
403− | otherwise = mempty
404 setColors =
384 setColors =
405 (case fixedForeColor attr of
385 (case fixedForeColor attr of
406− Just c -> writeColor Foreground c
386+ Just c -> writeCapExpr (setForeColor terminfoCaps)
387+ [toEnum $ colorMap c]
407 Nothing -> mempty)
388 Nothing -> mempty)
408 `mappend`
389 `mappend`
409 (case fixedBackColor attr of
390 (case fixedBackColor attr of
410− Just c -> writeColor Background c
391+ Just c -> writeCapExpr (setBackColor terminfoCaps)
392+ [toEnum $ colorMap c]
411 Nothing -> mempty)
393 Nothing -> mempty)
412− writeColorDiff _side NoColorChange
394+ writeColorDiff _f NoColorChange
413 = mempty
395 = mempty
414− writeColorDiff _side ColorToDefault
396+ writeColorDiff _f ColorToDefault
415 = error "ColorToDefault is not a possible case for applyColorDiffs"
397 = error "ColorToDefault is not a possible case for applyColorDiffs"
416− writeColorDiff side (SetColor c)
398+ writeColorDiff f (SetColor c)
417− = writeColor side c
418−
419− writeColor side (RGBColor r g b) =
420− case outputColorMode (contextDevice dc) of
421− FullColor ->
422− hardcodeColor side (r, g, b)
423− _ ->
424− error "clampColor should remove rgb colors in standard mode"
425− writeColor side c =
426− writeCapExpr (setSideColor side terminfoCaps) [toEnum $ colorMap c]
399+ = writeCapExpr (f terminfoCaps) [toEnum $ colorMap c]
427−
428−-- a color can either be in the foreground or the background
429−data ColorSide = Foreground | Background
430−
431−-- get the capability for drawing a color on a specific side
432−setSideColor :: ColorSide -> TerminfoCaps -> CapExpression
433−setSideColor Foreground = setForeColor
434−setSideColor Background = setBackColor
435−
436−hardcodeColor :: ColorSide -> (Word8, Word8, Word8) -> Write
437−hardcodeColor side (r, g, b) =
438− -- hardcoded color codes are formatted as "\x1b[{side};2;{r};{g};{b}m"
439− mconcat [ writeStr "\x1b[", sideCode, delimiter, writeChar '2', delimiter
440− , writeColor r, delimiter, writeColor g, delimiter, writeColor b
441− , writeChar 'm']
442− where
443− writeChar = writeWord8 . fromIntegral . fromEnum
444− writeStr = mconcat . map writeChar
445− writeColor = writeStr . show
446− delimiter = writeChar ';'
447− -- 38/48 are used to set whether we should write to the
448− -- foreground/background. I really don't want to know why.
449− sideCode = case side of
450− Foreground -> writeStr "38"
451− Background -> writeStr "48"
452
400
453-- | The color table used by a terminal is a 16 color set followed by a
401-- | The color table used by a terminal is a 16 color set followed by a
454-- 240 color set that might not be supported by the terminal.
402-- 240 color set that might not be supported by the terminal.
455--
403--
456−-- This takes a Color which clearly identifies which palette to use and
404+-- This takes a Color which clearly identifies which pallete to use and
457−-- computes the index into the full 256 color palette.
405+-- computes the index into the full 256 color pallete.
458ansiColorIndex :: Color -> Int
406ansiColorIndex :: Color -> Int
459ansiColorIndex (ISOColor v) = fromEnum v
407ansiColorIndex (ISOColor v) = fromEnum v
460ansiColorIndex (Color240 v) = 16 + fromEnum v
408ansiColorIndex (Color240 v) = 16 + fromEnum v
461−ansiColorIndex (RGBColor _ _ _) =
462− error $ unlines [ "Attempted to create color index from rgb color."
463− , "This is currently unsupported, and shouldn't ever happen"
464− ]
465
409
466-- | For terminals without setaf/setab
410-- | For terminals without setaf/setab
467--
411--
@@ -478,10 +422,6 @@ altColorIndex (ISOColor 6) = 3
478altColorIndex (ISOColor 7) = 7
422altColorIndex (ISOColor 7) = 7
479altColorIndex (ISOColor v) = fromEnum v
423altColorIndex (ISOColor v) = fromEnum v
480altColorIndex (Color240 v) = 16 + fromEnum v
424altColorIndex (Color240 v) = 16 + fromEnum v
481−altColorIndex (RGBColor _ _ _) =
482− error $ unlines [ "Attempted to create color index from rgb color."
483− , "This is currently unsupported, and shouldn't ever happen"
484− ]
485
425
486{- | The sequence of terminfo caps to apply a given style are determined
426{- | The sequence of terminfo caps to apply a given style are determined
487 - according to these rules.
427 - according to these rules.
@@ -509,7 +449,6 @@ data DisplayAttrState = DisplayAttrState
509 { applyStandout :: Bool
449 { applyStandout :: Bool
510 , applyUnderline :: Bool
450 , applyUnderline :: Bool
511 , applyItalic :: Bool
451 , applyItalic :: Bool
512− , applyStrikethrough :: Bool
513 , applyReverseVideo :: Bool
452 , applyReverseVideo :: Bool
514 , applyBlink :: Bool
453 , applyBlink :: Bool
515 , applyDim :: Bool
454 , applyDim :: Bool
@@ -546,8 +485,6 @@ reqDisplayCapSeqFor caps s diffs
546 -- set state cap then just use the set state cap.
485 -- set state cap then just use the set state cap.
547 ( True, True ) -> SetState $ stateForStyle s
486 ( True, True ) -> SetState $ stateForStyle s
548 where
487 where
549− noEnterExitCap ApplyStrikethrough = isNothing $ enterStrikethrough caps
550− noEnterExitCap RemoveStrikethrough = isNothing $ exitStrikethrough caps
551 noEnterExitCap ApplyItalic = isNothing $ enterItalic caps
488 noEnterExitCap ApplyItalic = isNothing $ enterItalic caps
552 noEnterExitCap RemoveItalic = isNothing $ exitItalic caps
489 noEnterExitCap RemoveItalic = isNothing $ exitItalic caps
553 noEnterExitCap ApplyStandout = isNothing $ enterStandout caps
490 noEnterExitCap ApplyStandout = isNothing $ enterStandout caps
@@ -562,8 +499,6 @@ reqDisplayCapSeqFor caps s diffs
562 noEnterExitCap RemoveDim = True
499 noEnterExitCap RemoveDim = True
563 noEnterExitCap ApplyBold = isNothing $ enterBoldMode caps
500 noEnterExitCap ApplyBold = isNothing $ enterBoldMode caps
564 noEnterExitCap RemoveBold = True
501 noEnterExitCap RemoveBold = True
565− enterExitCap ApplyStrikethrough = fromJust $ enterStrikethrough caps
566− enterExitCap RemoveStrikethrough = fromJust $ exitStrikethrough caps
567 enterExitCap ApplyItalic = fromJust $ enterItalic caps
502 enterExitCap ApplyItalic = fromJust $ enterItalic caps
568 enterExitCap RemoveItalic = fromJust $ exitItalic caps
503 enterExitCap RemoveItalic = fromJust $ exitItalic caps
569 enterExitCap ApplyStandout = fromJust $ enterStandout caps
504 enterExitCap ApplyStandout = fromJust $ enterStandout caps
@@ -580,7 +515,6 @@ stateForStyle s = DisplayAttrState
580 { applyStandout = isStyleSet standout
515 { applyStandout = isStyleSet standout
581 , applyUnderline = isStyleSet underline
516 , applyUnderline = isStyleSet underline
582 , applyItalic = isStyleSet italic
517 , applyItalic = isStyleSet italic
583− , applyStrikethrough = isStyleSet strikethrough
584 , applyReverseVideo = isStyleSet reverseVideo
518 , applyReverseVideo = isStyleSet reverseVideo
585 , applyBlink = isStyleSet blink
519 , applyBlink = isStyleSet blink
586 , applyDim = isStyleSet dim
520 , applyDim = isStyleSet dim
@@ -593,7 +527,6 @@ styleToApplySeq s = concat
593 [ applyIfRequired ApplyStandout standout
527 [ applyIfRequired ApplyStandout standout
594 , applyIfRequired ApplyUnderline underline
528 , applyIfRequired ApplyUnderline underline
595 , applyIfRequired ApplyItalic italic
529 , applyIfRequired ApplyItalic italic
596− , applyIfRequired ApplyStrikethrough strikethrough
597 , applyIfRequired ApplyReverseVideo reverseVideo
530 , applyIfRequired ApplyReverseVideo reverseVideo
598 , applyIfRequired ApplyBlink blink
531 , applyIfRequired ApplyBlink blink
599 , applyIfRequired ApplyDim dim
532 , applyIfRequired ApplyDim dim
src/Graphics/Vty/Output/XTermColor.hs+18−27
@@ -10,23 +10,17 @@ where
10import Graphics.Vty.Output.Interface
10import Graphics.Vty.Output.Interface
11import Graphics.Vty.Input.Mouse
11import Graphics.Vty.Input.Mouse
12import Graphics.Vty.Input.Focus
12import Graphics.Vty.Input.Focus
13−import Graphics.Vty.Attributes.Color (ColorMode)
14import qualified Graphics.Vty.Output.TerminfoBased as TerminfoBased
13import qualified Graphics.Vty.Output.TerminfoBased as TerminfoBased
15
14
16import Blaze.ByteString.Builder (writeToByteString)
15import Blaze.ByteString.Builder (writeToByteString)
17import Blaze.ByteString.Builder.Word (writeWord8)
16import Blaze.ByteString.Builder.Word (writeWord8)
18
17
19−import qualified Data.ByteString.Char8 as BS8
20−import Data.ByteString.Char8 (ByteString)
21−import Foreign.Ptr (castPtr)
22−
23import Control.Monad (void, when)
18import Control.Monad (void, when)
24import Control.Monad.Trans
19import Control.Monad.Trans
25−import Data.Char (toLower)
26import Data.IORef
20import Data.IORef
27
21
28−import System.Posix.IO (fdWriteBuf)
22+import System.Posix.IO (fdWrite)
29−import System.Posix.Types (ByteCount, Fd)
23+import System.Posix.Types (Fd)
30import System.Posix.Env (getEnv)
24import System.Posix.Env (getEnv)
31
25
32import Data.List (isInfixOf)
26import Data.List (isInfixOf)
@@ -36,15 +30,9 @@ import Data.Maybe (catMaybes)
36import Data.Monoid ((<>))
30import Data.Monoid ((<>))
37#endif
31#endif
38
32
39−-- | Write a 'ByteString' to an 'Fd'.
40−fdWrite :: Fd -> ByteString -> IO ByteCount
41−fdWrite fd s =
42− BS8.useAsCStringLen s $ \(buf,len) -> do
43− fdWriteBuf fd (castPtr buf) (fromIntegral len)
44−
45-- | Construct an Xterm output driver. Initialize the display to UTF-8.
33-- | Construct an Xterm output driver. Initialize the display to UTF-8.
46−reserveTerminal :: ( Applicative m, MonadIO m ) => String -> Fd -> ColorMode -> m Output
34+reserveTerminal :: ( Applicative m, MonadIO m ) => String -> Fd -> m Output
47−reserveTerminal variant outFd colorMode = liftIO $ do
35+reserveTerminal variant outFd = liftIO $ do
48 let flushedPut = void . fdWrite outFd
36 let flushedPut = void . fdWrite outFd
49 -- If the terminal variant is xterm-color use xterm instead since,
37 -- If the terminal variant is xterm-color use xterm instead since,
50 -- more often than not, xterm-color is broken.
38 -- more often than not, xterm-color is broken.
@@ -52,7 +40,7 @@ reserveTerminal variant outFd colorMode = liftIO $ do
52
40
53 utf8a <- utf8Active
41 utf8a <- utf8Active
54 when (not utf8a) $ flushedPut setUtf8CharSet
42 when (not utf8a) $ flushedPut setUtf8CharSet
55− t <- TerminfoBased.reserveTerminal variant' outFd colorMode
43+ t <- TerminfoBased.reserveTerminal variant' outFd
56
44
57 mouseModeStatus <- newIORef False
45 mouseModeStatus <- newIORef False
58 focusModeStatus <- newIORef False
46 focusModeStatus <- newIORef False
@@ -104,27 +92,30 @@ reserveTerminal variant outFd colorMode = liftIO $ do
104utf8Active :: IO Bool
92utf8Active :: IO Bool
105utf8Active = do
93utf8Active = do
106 let vars = ["LC_ALL", "LANG", "LC_CTYPE"]
94 let vars = ["LC_ALL", "LANG", "LC_CTYPE"]
107− results <- map (toLower <$>) . catMaybes <$> mapM getEnv vars
95+ results <- catMaybes <$> mapM getEnv vars
108− let matches = filter ("utf8" `isInfixOf`) results <>
96+ let matches = filter ("UTF8" `isInfixOf`) results <>
109− filter ("utf-8" `isInfixOf`) results
97+ filter ("UTF-8" `isInfixOf`) results
110 return $ not $ null matches
98 return $ not $ null matches
111
99
112-- | Enable bracketed paste mode:
100-- | Enable bracketed paste mode:
113-- http://cirw.in/blog/bracketed-paste
101-- http://cirw.in/blog/bracketed-paste
114−enableBracketedPastes :: ByteString
102+enableBracketedPastes :: String
115−enableBracketedPastes = BS8.pack "\ESC[?2004h"
103+enableBracketedPastes = "\ESC[?2004h"
116
104
117-- | Disable bracketed paste mode:
105-- | Disable bracketed paste mode:
118−disableBracketedPastes :: ByteString
106+disableBracketedPastes :: String
119−disableBracketedPastes = BS8.pack "\ESC[?2004l"
107+disableBracketedPastes = "\ESC[?2004l"
120
108
121-- | These sequences set xterm based terminals to UTF-8 output.
109-- | These sequences set xterm based terminals to UTF-8 output.
122--
110--
123-- There is no known terminfo capability equivalent to this.
111-- There is no known terminfo capability equivalent to this.
124−setUtf8CharSet, setDefaultCharSet :: ByteString
112+setUtf8CharSet, setDefaultCharSet :: String
125−setUtf8CharSet = BS8.pack "\ESC%G"
113+setUtf8CharSet = "\ESC%G"
126−setDefaultCharSet = BS8.pack "\ESC%@"
114+setDefaultCharSet = "\ESC%@"
127
115
116+-- | I think xterm is broken: Reseting the background color as the first
117+-- bytes serialized on a new line does not effect the background color
118+-- xterm uses to clear the line. Which is used *after* the next newline.
128xtermInlineHack :: Output -> IO ()
119xtermInlineHack :: Output -> IO ()
129xtermInlineHack t = do
120xtermInlineHack t = do
130 let writeReset = foldMap (writeWord8.toEnum.fromEnum) "\ESC[K"
121 let writeReset = foldMap (writeWord8.toEnum.fromEnum) "\ESC[K"
src/Graphics/Vty/Picture.hs+1−8
@@ -1,3 +1,4 @@
1+{-# LANGUAGE BangPatterns #-}
1-- A 'Picture' is a background paired with a set of 'Image' layers. The
2-- A 'Picture' is a background paired with a set of 'Image' layers. The
2-- 'Picture' data structure is representative of the final terminal
3-- 'Picture' data structure is representative of the final terminal
3-- view.
4-- view.
@@ -79,14 +80,6 @@ picForLayers is = Picture
79data Cursor =
80data Cursor =
80 -- | Hide the cursor
81 -- | Hide the cursor
81 NoCursor
82 NoCursor
82− -- | Set the terminal's cursor position without displaying a cursor
83− -- character. This is important for accessibility with screen
84− -- readers where a cursor position needs to be reported but we may
85− -- not want to show a block cursor in that location for cosmetic
86− -- reasons. The boolean argument indicates whether the positioning
87− -- should be absolute as with 'AbsoluteCursor' ('True') or logical
88− -- as with 'Cursor' ('False').
89− | PositionOnly !Bool !Int !Int
90 -- | Show the cursor at the given logical column accounting for
83 -- | Show the cursor at the given logical column accounting for
91 -- character width in the presence of multi-column characters.
84 -- character width in the presence of multi-column characters.
92 | Cursor !Int !Int
85 | Cursor !Int !Int
src/Graphics/Vty/PictureToSpans.hs+4−4
@@ -72,7 +72,7 @@ displayOpsForPic pic r = Vector.create (combinedOpsForLayers pic r)
72-- | Returns the DisplayOps for an image rendered to a window the size
72-- | Returns the DisplayOps for an image rendered to a window the size
73-- of the image.
73-- of the image.
74--
74--
75−-- largely used only for debugging.
75+-- largerly used only for debugging.
76displayOpsForImage :: Image -> DisplayOps
76displayOpsForImage :: Image -> DisplayOps
77displayOpsForImage i = displayOpsForPic (picForImage i) (imageWidth i, imageHeight i)
77displayOpsForImage i = displayOpsForPic (picForImage i) (imageWidth i, imageHeight i)
78
78
@@ -81,7 +81,7 @@ combinedOpsForLayers :: Picture -> DisplayRegion -> ST s (MRowOps s)
81combinedOpsForLayers pic r
81combinedOpsForLayers pic r
82 | regionWidth r == 0 || regionHeight r == 0 = MVector.new 0
82 | regionWidth r == 0 || regionHeight r == 0 = MVector.new 0
83 | otherwise = do
83 | otherwise = do
84− layerOps <- mapM (`buildSpans` r) (picLayers pic)
84+ layerOps <- mapM (\layer -> buildSpans layer r) (picLayers pic)
85 case layerOps of
85 case layerOps of
86 [] -> fail "empty picture"
86 [] -> fail "empty picture"
87 [ops] -> substituteSkips (picBackground pic) ops
87 [ops] -> substituteSkips (picBackground pic) ops
@@ -136,8 +136,8 @@ mergeUnder upper lower = do
136 return upper
136 return upper
137
137
138mergeRowUnder :: SpanOps -> SpanOps -> SpanOps
138mergeRowUnder :: SpanOps -> SpanOps -> SpanOps
139−mergeRowUnder upperRowOps =
139+mergeRowUnder upperRowOps lowerRowOps =
140− onUpperOp Vector.empty (Vector.head upperRowOps) (Vector.tail upperRowOps)
140+ onUpperOp Vector.empty (Vector.head upperRowOps) (Vector.tail upperRowOps) lowerRowOps
141 where
141 where
142 -- H: it will never be the case that we are out of upper ops
142 -- H: it will never be the case that we are out of upper ops
143 -- before lower ops.
143 -- before lower ops.
src/Graphics/Vty/Span.hs+4−2
@@ -1,4 +1,6 @@
1-- Copyright Corey O'Connor
1-- Copyright Corey O'Connor
2+{-# LANGUAGE BangPatterns #-}
3+{-# LANGUAGE NamedFieldPuns #-}
2{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
3-- | A picture is translated into a sequences of state changes and
5-- | A picture is translated into a sequences of state changes and
4-- character spans. The attribute is applied to all following spans,
6-- character spans. The attribute is applied to all following spans,
@@ -50,7 +52,7 @@ dropOps :: Int -> SpanOps -> SpanOps
50dropOps w = snd . splitOpsAt w
52dropOps w = snd . splitOpsAt w
51
53
52splitOpsAt :: Int -> SpanOps -> (SpanOps, SpanOps)
54splitOpsAt :: Int -> SpanOps -> (SpanOps, SpanOps)
53−splitOpsAt = splitOpsAt'
55+splitOpsAt inW inOps = splitOpsAt' inW inOps
54 where
56 where
55 splitOpsAt' 0 ops = (Vector.empty, ops)
57 splitOpsAt' 0 ops = (Vector.empty, ops)
56 splitOpsAt' remainingColumns ops = case Vector.head ops of
58 splitOpsAt' remainingColumns ops = case Vector.head ops of
@@ -101,7 +103,7 @@ displayOpsColumns ops
101
103
102-- | The number of rows the DisplayOps are defined for.
104-- | The number of rows the DisplayOps are defined for.
103displayOpsRows :: DisplayOps -> Int
105displayOpsRows :: DisplayOps -> Int
104−displayOpsRows = Vector.length
106+displayOpsRows ops = Vector.length ops
105
107
106affectedRegion :: DisplayOps -> DisplayRegion
108affectedRegion :: DisplayOps -> DisplayRegion
107affectedRegion ops = (displayOpsColumns ops, displayOpsRows ops)
109affectedRegion ops = (displayOpsColumns ops, displayOpsRows ops)
src/Graphics/Vty/UnicodeWidthTable/IO.hs+33−17
@@ -1,7 +1,6 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2module Graphics.Vty.UnicodeWidthTable.IO
2module Graphics.Vty.UnicodeWidthTable.IO
3 ( readUnicodeWidthTable
3 ( readUnicodeWidthTable
4− , parseUnicodeWidthTable
5 , writeUnicodeWidthTable
4 , writeUnicodeWidthTable
6 )
5 )
7where
6where
@@ -22,23 +21,20 @@ import Graphics.Vty.UnicodeWidthTable.Types
22-- This either returns a successfully parsed table or a table parsing
21-- This either returns a successfully parsed table or a table parsing
23-- error message. This does not handle I/O exceptions.
22-- error message. This does not handle I/O exceptions.
24readUnicodeWidthTable :: FilePath -> IO (Either String UnicodeWidthTable)
23readUnicodeWidthTable :: FilePath -> IO (Either String UnicodeWidthTable)
25−readUnicodeWidthTable path = parseUnicodeWidthTable <$> BSL.readFile path
24+readUnicodeWidthTable path = do
26−
25+ body <- BSL.readFile path
27−-- | Parse a binary unicode width table.
28−parseUnicodeWidthTable :: BSL.ByteString -> Either String UnicodeWidthTable
29−parseUnicodeWidthTable bs =
30− case runGetOrFail tableParser bs of
26+ case runGetOrFail tableParser body of
31 Left (_, _, msg) ->
27 Left (_, _, msg) ->
32− Left msg
28+ return $ Left msg
33
29
34 -- Even if we parsed a table, leftover bytes indicate something
30 -- Even if we parsed a table, leftover bytes indicate something
35 -- could be wrong.
31 -- could be wrong.
36 Right (remainingBytes, _, _) | not (BSL.null remainingBytes) ->
32 Right (remainingBytes, _, _) | not (BSL.null remainingBytes) ->
37− Left $ "Error: " <> show (BSL.length remainingBytes) <>
33+ return $ Left $ "Error: " <> show (BSL.length remainingBytes) <>
38− " byte(s) left unconsumed"
34+ " byte(s) left unconsumed"
39
35
40 Right (_, _, table) ->
36 Right (_, _, table) ->
41− Right table
37+ return $ Right table
42
38
43-- | Write the unicode width table to the specified path.
39-- | Write the unicode width table to the specified path.
44--
40--
@@ -52,14 +48,30 @@ writeUnicodeWidthTable path table = do
52widthTableMagic :: Word32
48widthTableMagic :: Word32
53widthTableMagic = 0xc1a9f7e0
49widthTableMagic = 0xc1a9f7e0
54
50
51+-- NB: This parsing code uses explicit types for parsing each value to
52+-- catch situations where someone changes the types of the fields of
53+-- WidthTableRange or other values and in doing so would silently break
54+-- the parser. If the parser used a style like
55+--
56+-- WidthTableRange <$> get <*> get <*> get
57+--
58+-- then that would result in valid Haskell code that would fail to read
59+-- files that it would have previously parsed. We want those errors
60+-- caught by GHc. At the time of this writing, the library data types
61+-- *happen* to match the binary layout of the version 1 format, but that
62+-- could definitely change in later formats. In those cases we should
63+-- deal with the difference by doing the appropriate conversions.
64+
55tableParser :: Get UnicodeWidthTable
65tableParser :: Get UnicodeWidthTable
56tableParser = do
66tableParser = do
67+ magic :: Word32
57− magic <- getWord32le
68+ <- getWord32le
58
69
59 when (magic /= widthTableMagic) $
70 when (magic /= widthTableMagic) $
60 fail "Table magic number invalid"
71 fail "Table magic number invalid"
61
72
62− version <- getWord8
73+ version :: Word8
74+ <- get
63
75
64 case version of
76 case version of
65 1 -> tableV1Parser
77 1 -> tableV1Parser
@@ -67,12 +79,16 @@ tableParser = do
67
79
68tableV1Parser :: Get UnicodeWidthTable
80tableV1Parser :: Get UnicodeWidthTable
69tableV1Parser = do
81tableV1Parser = do
82+ numRanges :: Word32
70− numRanges <- getWord32le
83+ <- getWord32le
71
84
72 let parseRange = do
85 let parseRange = do
86+ start :: Word32
73− start <- getWord32le
87+ <- getWord32le
88+ size :: Word32
74− size <- getWord32le
89+ <- getWord32le
75− cols <- getWord8
90+ cols :: Word8
91+ <- get
76 return WidthTableRange { rangeStart = start
92 return WidthTableRange { rangeStart = start
77 , rangeSize = size
93 , rangeSize = size
78 , rangeColumns = cols
94 , rangeColumns = cols
src/Graphics/Vty/UnicodeWidthTable/Install.hs+30−65
@@ -1,38 +1,39 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE ForeignFunctionInterface #-}
2{-# LANGUAGE ForeignFunctionInterface #-}
3module Graphics.Vty.UnicodeWidthTable.Install
3module Graphics.Vty.UnicodeWidthTable.Install
4− ( TableInstallException(..)
4+ ( installUnicodeWidthTable
5− , installUnicodeWidthTable
5+
6 , isCustomTableReady
6 , isCustomTableReady
7 )
7 )
8where
8where
9
9
10import Control.Monad (when, forM_)
10import Control.Monad (when, forM_)
11−import qualified Control.Exception as E
12−import GHC.Conc.Sync (withMVar)
13−import Control.Concurrent.MVar (MVar, newMVar)
14import Data.Word (Word8, Word32)
11import Data.Word (Word8, Word32)
15#if !(MIN_VERSION_base(4,11,0))
12#if !(MIN_VERSION_base(4,11,0))
16import Data.Semigroup ((<>))
13import Data.Semigroup ((<>))
17#endif
14#endif
18−import System.IO.Unsafe (unsafePerformIO)
19
15
20import Graphics.Vty.UnicodeWidthTable.Types
16import Graphics.Vty.UnicodeWidthTable.Types
21
17
22−-- | The lock used to make functions in this module thread-safe.
18+foreign import ccall unsafe "vty_init_custom_table"
23−installLock :: MVar ()
19+ initCustomTable :: Int -> IO Int
24−{-# NOINLINE installLock #-}
20+
25−installLock = unsafePerformIO $ newMVar ()
21+foreign import ccall unsafe "vty_set_custom_table_range"
22+ setCustomTableRange :: Word32 -> Word32 -> Word8 -> IO Int
23+
24+foreign import ccall unsafe "vty_activate_custom_table"
25+ activateCustomTable :: IO Int
26+
27+foreign import ccall unsafe "vty_custom_table_ready"
28+ c_isCustomTableReady :: IO Int
29+
30+foreign import ccall unsafe "vty_deallocate_custom_table"
31+ deallocateCustomTable :: IO ()
26
32
27-- | Returns True if and only if a custom table has been allocated and
33-- | Returns True if and only if a custom table has been allocated and
28−-- marked as ready for use.
34+-- marked as ready for use. Returns False otherwise.
29−--
30−-- This function is thread-safe.
31isCustomTableReady :: IO Bool
35isCustomTableReady :: IO Bool
32−isCustomTableReady = withInstallLock $ (== 1) <$> c_isCustomTableReady
36+isCustomTableReady = (== 1) <$> c_isCustomTableReady
33−
34−withInstallLock :: IO a -> IO a
35−withInstallLock act = withMVar installLock $ const act
36
37
37-- This is the size of the allocated custom character width table, in
38-- This is the size of the allocated custom character width table, in
38-- character slots. It's important that this be large enough to hold all
39-- character slots. It's important that this be large enough to hold all
@@ -41,31 +42,11 @@ withInstallLock act = withMVar installLock $ const act
41tableSize :: Int
42tableSize :: Int
42tableSize = 0x110000
43tableSize = 0x110000
43
44
44−-- | Exception type raised by 'installUnicodeWidthTable'.
45−data TableInstallException =
46− TableInitFailure Int Int
47− -- ^ The width table could not be initialized. Args: failure status,
48− -- requested table size.
49− | TableRangeFailure Int WidthTableRange
50− -- ^ A code point range could not be configured. Args: failure
51− -- status, offending range.
52− | TableActivationFailure Int
53− -- ^ The table could not be activated. Args: failure status.
54− deriving (Eq, Show)
55−
56−instance E.Exception TableInstallException
57−
58-- | Install a custom unicode character width
45-- | Install a custom unicode character width
59-- table. Such tables are obtained with
46-- table. Such tables are obtained with
60-- 'Graphics.Vty.UnicodeWidthTable.Query.buildUnicodeWidthTable' and
47-- 'Graphics.Vty.UnicodeWidthTable.Query.buildUnicodeWidthTable' and
61-- 'Graphics.Vty.UnicodeWidthTable.IO.readUnicodeWidthTable'.
48-- 'Graphics.Vty.UnicodeWidthTable.IO.readUnicodeWidthTable'.
62--
49--
63−-- ALERT! This function is probably not what you want to use because
64−-- it is automatically called by 'Graphics.Vty.mkVty'. You will only
65−-- ever need to call this function if you want to use functions
66−-- in 'Graphics.Text.Width' without controlling the terminal with
67−-- 'Graphics.Vty.mkVty'.
68−--
69-- This affects the behavior of the 'Graphics.Vty.Image.wcwidth'
50-- This affects the behavior of the 'Graphics.Vty.Image.wcwidth'
70-- function and functions that call it. It does so by
51-- function and functions that call it. It does so by
71-- changing global state available to the C implementation
52-- changing global state available to the C implementation
@@ -82,20 +63,20 @@ instance E.Exception TableInstallException
82-- they don't want to control the terminal with 'mkVty' but do want to
63-- they don't want to control the terminal with 'mkVty' but do want to
83-- make calls to 'Graphics.Vty.Image.wcwidth'.
64-- make calls to 'Graphics.Vty.Image.wcwidth'.
84--
65--
85−-- It's also important to note that once a custom table has been
66+-- It's also important to note that once a
86−-- installed, it is permanent for the life of the process. No new table
67+-- custom table has been installed, it is permanent for the life of the
87−-- can be installed, and the new custom table cannot be removed.
68+-- process. No new table can be installed, and the new custom table
69+-- cannot be removed.
88--
70--
89-- If this function fails for any reason -- if the table cannot be
71-- If this function fails for any reason -- if the table cannot be
90-- installed or is invalid, or if a custom table already exists -- this
72-- installed or is invalid, or if a custom table already exists -- this
91−-- will raise a 'TableInstallException' exception.
73+-- will raise an exception by calling 'error'.
92−--
93−-- This function is thread-safe.
94installUnicodeWidthTable :: UnicodeWidthTable -> IO ()
74installUnicodeWidthTable :: UnicodeWidthTable -> IO ()
95−installUnicodeWidthTable table = withInstallLock $ do
75+installUnicodeWidthTable table = do
96 initResult <- initCustomTable tableSize
76 initResult <- initCustomTable tableSize
97 when (initResult /= 0) $
77 when (initResult /= 0) $
98− E.throwIO $ TableInitFailure initResult tableSize
78+ error $ "installUnicodeWidthTable: error initializing " <>
79+ "custom table, status " <> show initResult
99
80
100 forM_ (unicodeWidthTableRanges table) $ \r -> do
81 forM_ (unicodeWidthTableRanges table) $ \r -> do
101 result <- setCustomTableRange (rangeStart r)
82 result <- setCustomTableRange (rangeStart r)
@@ -104,26 +85,10 @@ installUnicodeWidthTable table = withInstallLock $ do
104
85
105 when (result /= 0) $ do
86 when (result /= 0) $ do
106 deallocateCustomTable
87 deallocateCustomTable
107− E.throwIO $ TableRangeFailure result r
88+ error $ "installUnicodeWidthTable: error installing range " <>
89+ show r <> ", status " <> show result
108
90
109 actResult <- activateCustomTable
91 actResult <- activateCustomTable
110 when (actResult /= 0) $
92 when (actResult /= 0) $
111− E.throwIO $ TableActivationFailure actResult
93+ error $ "installUnicodeWidthTable: error activating custom " <>
112−
94+ "table, status " <> show actResult
113−------------------------------------------------------------------------
114−-- C imports
115−
116−foreign import ccall unsafe "vty_init_custom_table"
117− initCustomTable :: Int -> IO Int
118−
119−foreign import ccall unsafe "vty_set_custom_table_range"
120− setCustomTableRange :: Word32 -> Word32 -> Word8 -> IO Int
121−
122−foreign import ccall unsafe "vty_activate_custom_table"
123− activateCustomTable :: IO Int
124−
125−foreign import ccall unsafe "vty_custom_table_ready"
126− c_isCustomTableReady :: IO Int
127−
128−foreign import ccall unsafe "vty_deallocate_custom_table"
129− deallocateCustomTable :: IO ()
src/Graphics/Vty/UnicodeWidthTable/Query.hs+12−14
@@ -1,7 +1,6 @@
1{-# LANGUAGE TupleSections #-}
1{-# LANGUAGE TupleSections #-}
2module Graphics.Vty.UnicodeWidthTable.Query
2module Graphics.Vty.UnicodeWidthTable.Query
3 ( buildUnicodeWidthTable
3 ( buildUnicodeWidthTable
4− , defaultUnicodeTableUpperBound
5 )
4 )
6where
5where
7
6
@@ -54,25 +53,24 @@ mkRanges pairs =
54
53
55-- The uppermost code point to consider when building Unicode width
54-- The uppermost code point to consider when building Unicode width
56-- tables.
55-- tables.
57−defaultUnicodeTableUpperBound :: Char
56+--
58−defaultUnicodeTableUpperBound = '\xe0000'
57+-- This only covers some of the possible Unicode range and is sure to
58+-- become stale eventually. Granted, at the time of this writing, even
59+-- the latest version of Unicode (13) totals 143,859 characters and that
60+-- only gets us to code point 0x231f3 or so. But it's only a matter of
61+-- time before this bound is too low.
62+unicodeTableUpperBound :: Char
63+unicodeTableUpperBound = '\x2FFFF'
59
64
60-- | Construct a unicode character width table by querying the terminal
65-- | Construct a unicode character width table by querying the terminal
61-- connected to stdout. This works by emitting characters to stdout
66-- connected to stdout. This works by emitting characters to stdout
62-- and then querying the terminal to determine the resulting cursor
67-- and then querying the terminal to determine the resulting cursor
63-- position in order to measure character widths. Consequently this will
68-- position in order to measure character widths. Consequently this will
64-- generate a lot of output and may take a while, depending on your
69-- generate a lot of output and may take a while, depending on your
65−-- system performance. This should not be run in a terminal while it is
70+-- system performance.
66−-- controlled by Vty.
67−--
68−-- The argument specifies the upper bound code point to test when
69−-- building the table. This allows callers to decide how much of the
70−-- Unicode code point space to scan when building the table.
71−--
72−-- This does not handle exceptions.
73−buildUnicodeWidthTable :: Char -> IO UnicodeWidthTable
71+buildUnicodeWidthTable :: IO UnicodeWidthTable
74−buildUnicodeWidthTable tableUpperBound = do
72+buildUnicodeWidthTable = do
75− pairs <- forM (filter shouldConsider ['\0'..tableUpperBound]) $ \i ->
73+ pairs <- forM (filter shouldConsider ['\0'..unicodeTableUpperBound]) $ \i ->
76 (i,) <$> charWidth i
74 (i,) <$> charWidth i
77
75
78 return UnicodeWidthTable { unicodeWidthTableRanges = reverse $ mkRanges pairs
76 return UnicodeWidthTable { unicodeWidthTableRanges = reverse $ mkRanges pairs
test/VerifyColor240.hsdeleted−269
@@ -1,269 +0,0 @@
1−module VerifyColor240 where
2−
3−import Data.Word(Word8)
4−import Verify
5−
6−import Graphics.Vty.Attributes.Color240(rgbColorToColor240)
7−
8−oldRgbColorToColor240 :: Integral i => i -> i -> i -> Word8
9−oldRgbColorToColor240 r g b
10− | r < 0 && g < 0 && b < 0 = error "rgbColor with negative color component intensity"
11− | r == 8 && g == 8 && b == 8 = 216
12− | r == 18 && g == 18 && b == 18 = 217
13− | r == 28 && g == 28 && b == 28 = 218
14− | r == 38 && g == 38 && b == 38 = 219
15− | r == 48 && g == 48 && b == 48 = 220
16− | r == 58 && g == 58 && b == 58 = 221
17− | r == 68 && g == 68 && b == 68 = 222
18− | r == 78 && g == 78 && b == 78 = 223
19− | r == 88 && g == 88 && b == 88 = 224
20− | r == 98 && g == 98 && b == 98 = 225
21− | r == 108 && g == 108 && b == 108 = 226
22− | r == 118 && g == 118 && b == 118 = 227
23− | r == 128 && g == 128 && b == 128 = 228
24− | r == 138 && g == 138 && b == 138 = 229
25− | r == 148 && g == 148 && b == 148 = 230
26− | r == 158 && g == 158 && b == 158 = 231
27− | r == 168 && g == 168 && b == 168 = 232
28− | r == 178 && g == 178 && b == 178 = 233
29− | r == 188 && g == 188 && b == 188 = 234
30− | r == 198 && g == 198 && b == 198 = 235
31− | r == 208 && g == 208 && b == 208 = 236
32− | r == 218 && g == 218 && b == 218 = 237
33− | r == 228 && g == 228 && b == 228 = 238
34− | r == 238 && g == 238 && b == 238 = 239
35− | r <= 0 && g <= 0 && b <= 0 = 0
36− | r <= 0 && g <= 0 && b <= 95 = 1
37− | r <= 0 && g <= 0 && b <= 135 = 2
38− | r <= 0 && g <= 0 && b <= 175 = 3
39− | r <= 0 && g <= 0 && b <= 215 = 4
40− | r <= 0 && g <= 0 && b <= 255 = 5
41− | r <= 0 && g <= 95 && b <= 0 = 6
42− | r <= 0 && g <= 95 && b <= 95 = 7
43− | r <= 0 && g <= 95 && b <= 135 = 8
44− | r <= 0 && g <= 95 && b <= 175 = 9
45− | r <= 0 && g <= 95 && b <= 215 = 10
46− | r <= 0 && g <= 95 && b <= 255 = 11
47− | r <= 0 && g <= 135 && b <= 0 = 12
48− | r <= 0 && g <= 135 && b <= 95 = 13
49− | r <= 0 && g <= 135 && b <= 135 = 14
50− | r <= 0 && g <= 135 && b <= 175 = 15
51− | r <= 0 && g <= 135 && b <= 215 = 16
52− | r <= 0 && g <= 135 && b <= 255 = 17
53− | r <= 0 && g <= 175 && b <= 0 = 18
54− | r <= 0 && g <= 175 && b <= 95 = 19
55− | r <= 0 && g <= 175 && b <= 135 = 20
56− | r <= 0 && g <= 175 && b <= 175 = 21
57− | r <= 0 && g <= 175 && b <= 215 = 22
58− | r <= 0 && g <= 175 && b <= 255 = 23
59− | r <= 0 && g <= 215 && b <= 0 = 24
60− | r <= 0 && g <= 215 && b <= 95 = 25
61− | r <= 0 && g <= 215 && b <= 135 = 26
62− | r <= 0 && g <= 215 && b <= 175 = 27
63− | r <= 0 && g <= 215 && b <= 215 = 28
64− | r <= 0 && g <= 215 && b <= 255 = 29
65− | r <= 0 && g <= 255 && b <= 0 = 30
66− | r <= 0 && g <= 255 && b <= 95 = 31
67− | r <= 0 && g <= 255 && b <= 135 = 32
68− | r <= 0 && g <= 255 && b <= 175 = 33
69− | r <= 0 && g <= 255 && b <= 215 = 34
70− | r <= 0 && g <= 255 && b <= 255 = 35
71− | r <= 95 && g <= 0 && b <= 0 = 36
72− | r <= 95 && g <= 0 && b <= 95 = 37
73− | r <= 95 && g <= 0 && b <= 135 = 38
74− | r <= 95 && g <= 0 && b <= 175 = 39
75− | r <= 95 && g <= 0 && b <= 215 = 40
76− | r <= 95 && g <= 0 && b <= 255 = 41
77− | r <= 95 && g <= 95 && b <= 0 = 42
78− | r <= 95 && g <= 95 && b <= 95 = 43
79− | r <= 95 && g <= 95 && b <= 135 = 44
80− | r <= 95 && g <= 95 && b <= 175 = 45
81− | r <= 95 && g <= 95 && b <= 215 = 46
82− | r <= 95 && g <= 95 && b <= 255 = 47
83− | r <= 95 && g <= 135 && b <= 0 = 48
84− | r <= 95 && g <= 135 && b <= 95 = 49
85− | r <= 95 && g <= 135 && b <= 135 = 50
86− | r <= 95 && g <= 135 && b <= 175 = 51
87− | r <= 95 && g <= 135 && b <= 215 = 52
88− | r <= 95 && g <= 135 && b <= 255 = 53
89− | r <= 95 && g <= 175 && b <= 0 = 54
90− | r <= 95 && g <= 175 && b <= 95 = 55
91− | r <= 95 && g <= 175 && b <= 135 = 56
92− | r <= 95 && g <= 175 && b <= 175 = 57
93− | r <= 95 && g <= 175 && b <= 215 = 58
94− | r <= 95 && g <= 175 && b <= 255 = 59
95− | r <= 95 && g <= 215 && b <= 0 = 60
96− | r <= 95 && g <= 215 && b <= 95 = 61
97− | r <= 95 && g <= 215 && b <= 135 = 62
98− | r <= 95 && g <= 215 && b <= 175 = 63
99− | r <= 95 && g <= 215 && b <= 215 = 64
100− | r <= 95 && g <= 215 && b <= 255 = 65
101− | r <= 95 && g <= 255 && b <= 0 = 66
102− | r <= 95 && g <= 255 && b <= 95 = 67
103− | r <= 95 && g <= 255 && b <= 135 = 68
104− | r <= 95 && g <= 255 && b <= 175 = 69
105− | r <= 95 && g <= 255 && b <= 215 = 70
106− | r <= 95 && g <= 255 && b <= 255 = 71
107− | r <= 135 && g <= 0 && b <= 0 = 72
108− | r <= 135 && g <= 0 && b <= 95 = 73
109− | r <= 135 && g <= 0 && b <= 135 = 74
110− | r <= 135 && g <= 0 && b <= 175 = 75
111− | r <= 135 && g <= 0 && b <= 215 = 76
112− | r <= 135 && g <= 0 && b <= 255 = 77
113− | r <= 135 && g <= 95 && b <= 0 = 78
114− | r <= 135 && g <= 95 && b <= 95 = 79
115− | r <= 135 && g <= 95 && b <= 135 = 80
116− | r <= 135 && g <= 95 && b <= 175 = 81
117− | r <= 135 && g <= 95 && b <= 215 = 82
118− | r <= 135 && g <= 95 && b <= 255 = 83
119− | r <= 135 && g <= 135 && b <= 0 = 84
120− | r <= 135 && g <= 135 && b <= 95 = 85
121− | r <= 135 && g <= 135 && b <= 135 = 86
122− | r <= 135 && g <= 135 && b <= 175 = 87
123− | r <= 135 && g <= 135 && b <= 215 = 88
124− | r <= 135 && g <= 135 && b <= 255 = 89
125− | r <= 135 && g <= 175 && b <= 0 = 90
126− | r <= 135 && g <= 175 && b <= 95 = 91
127− | r <= 135 && g <= 175 && b <= 135 = 92
128− | r <= 135 && g <= 175 && b <= 175 = 93
129− | r <= 135 && g <= 175 && b <= 215 = 94
130− | r <= 135 && g <= 175 && b <= 255 = 95
131− | r <= 135 && g <= 215 && b <= 0 = 96
132− | r <= 135 && g <= 215 && b <= 95 = 97
133− | r <= 135 && g <= 215 && b <= 135 = 98
134− | r <= 135 && g <= 215 && b <= 175 = 99
135− | r <= 135 && g <= 215 && b <= 215 = 100
136− | r <= 135 && g <= 215 && b <= 255 = 101
137− | r <= 135 && g <= 255 && b <= 0 = 102
138− | r <= 135 && g <= 255 && b <= 95 = 103
139− | r <= 135 && g <= 255 && b <= 135 = 104
140− | r <= 135 && g <= 255 && b <= 175 = 105
141− | r <= 135 && g <= 255 && b <= 215 = 106
142− | r <= 135 && g <= 255 && b <= 255 = 107
143− | r <= 175 && g <= 0 && b <= 0 = 108
144− | r <= 175 && g <= 0 && b <= 95 = 109
145− | r <= 175 && g <= 0 && b <= 135 = 110
146− | r <= 175 && g <= 0 && b <= 175 = 111
147− | r <= 175 && g <= 0 && b <= 215 = 112
148− | r <= 175 && g <= 0 && b <= 255 = 113
149− | r <= 175 && g <= 95 && b <= 0 = 114
150− | r <= 175 && g <= 95 && b <= 95 = 115
151− | r <= 175 && g <= 95 && b <= 135 = 116
152− | r <= 175 && g <= 95 && b <= 175 = 117
153− | r <= 175 && g <= 95 && b <= 215 = 118
154− | r <= 175 && g <= 95 && b <= 255 = 119
155− | r <= 175 && g <= 135 && b <= 0 = 120
156− | r <= 175 && g <= 135 && b <= 95 = 121
157− | r <= 175 && g <= 135 && b <= 135 = 122
158− | r <= 175 && g <= 135 && b <= 175 = 123
159− | r <= 175 && g <= 135 && b <= 215 = 124
160− | r <= 175 && g <= 135 && b <= 255 = 125
161− | r <= 175 && g <= 175 && b <= 0 = 126
162− | r <= 175 && g <= 175 && b <= 95 = 127
163− | r <= 175 && g <= 175 && b <= 135 = 128
164− | r <= 175 && g <= 175 && b <= 175 = 129
165− | r <= 175 && g <= 175 && b <= 215 = 130
166− | r <= 175 && g <= 175 && b <= 255 = 131
167− | r <= 175 && g <= 215 && b <= 0 = 132
168− | r <= 175 && g <= 215 && b <= 95 = 133
169− | r <= 175 && g <= 215 && b <= 135 = 134
170− | r <= 175 && g <= 215 && b <= 175 = 135
171− | r <= 175 && g <= 215 && b <= 215 = 136
172− | r <= 175 && g <= 215 && b <= 255 = 137
173− | r <= 175 && g <= 255 && b <= 0 = 138
174− | r <= 175 && g <= 255 && b <= 95 = 139
175− | r <= 175 && g <= 255 && b <= 135 = 140
176− | r <= 175 && g <= 255 && b <= 175 = 141
177− | r <= 175 && g <= 255 && b <= 215 = 142
178− | r <= 175 && g <= 255 && b <= 255 = 143
179− | r <= 215 && g <= 0 && b <= 0 = 144
180− | r <= 215 && g <= 0 && b <= 95 = 145
181− | r <= 215 && g <= 0 && b <= 135 = 146
182− | r <= 215 && g <= 0 && b <= 175 = 147
183− | r <= 215 && g <= 0 && b <= 215 = 148
184− | r <= 215 && g <= 0 && b <= 255 = 149
185− | r <= 215 && g <= 95 && b <= 0 = 150
186− | r <= 215 && g <= 95 && b <= 95 = 151
187− | r <= 215 && g <= 95 && b <= 135 = 152
188− | r <= 215 && g <= 95 && b <= 175 = 153
189− | r <= 215 && g <= 95 && b <= 215 = 154
190− | r <= 215 && g <= 95 && b <= 255 = 155
191− | r <= 215 && g <= 135 && b <= 0 = 156
192− | r <= 215 && g <= 135 && b <= 95 = 157
193− | r <= 215 && g <= 135 && b <= 135 = 158
194− | r <= 215 && g <= 135 && b <= 175 = 159
195− | r <= 215 && g <= 135 && b <= 215 = 160
196− | r <= 215 && g <= 135 && b <= 255 = 161
197− | r <= 215 && g <= 175 && b <= 0 = 162
198− | r <= 215 && g <= 175 && b <= 95 = 163
199− | r <= 215 && g <= 175 && b <= 135 = 164
200− | r <= 215 && g <= 175 && b <= 175 = 165
201− | r <= 215 && g <= 175 && b <= 215 = 166
202− | r <= 215 && g <= 175 && b <= 255 = 167
203− | r <= 215 && g <= 215 && b <= 0 = 168
204− | r <= 215 && g <= 215 && b <= 95 = 169
205− | r <= 215 && g <= 215 && b <= 135 = 170
206− | r <= 215 && g <= 215 && b <= 175 = 171
207− | r <= 215 && g <= 215 && b <= 215 = 172
208− | r <= 215 && g <= 215 && b <= 255 = 173
209− | r <= 215 && g <= 255 && b <= 0 = 174
210− | r <= 215 && g <= 255 && b <= 95 = 175
211− | r <= 215 && g <= 255 && b <= 135 = 176
212− | r <= 215 && g <= 255 && b <= 175 = 177
213− | r <= 215 && g <= 255 && b <= 215 = 178
214− | r <= 215 && g <= 255 && b <= 255 = 179
215− | r <= 255 && g <= 0 && b <= 0 = 180
216− | r <= 255 && g <= 0 && b <= 95 = 181
217− | r <= 255 && g <= 0 && b <= 135 = 182
218− | r <= 255 && g <= 0 && b <= 175 = 183
219− | r <= 255 && g <= 0 && b <= 215 = 184
220− | r <= 255 && g <= 0 && b <= 255 = 185
221− | r <= 255 && g <= 95 && b <= 0 = 186
222− | r <= 255 && g <= 95 && b <= 95 = 187
223− | r <= 255 && g <= 95 && b <= 135 = 188
224− | r <= 255 && g <= 95 && b <= 175 = 189
225− | r <= 255 && g <= 95 && b <= 215 = 190
226− | r <= 255 && g <= 95 && b <= 255 = 191
227− | r <= 255 && g <= 135 && b <= 0 = 192
228− | r <= 255 && g <= 135 && b <= 95 = 193
229− | r <= 255 && g <= 135 && b <= 135 = 194
230− | r <= 255 && g <= 135 && b <= 175 = 195
231− | r <= 255 && g <= 135 && b <= 215 = 196
232− | r <= 255 && g <= 135 && b <= 255 = 197
233− | r <= 255 && g <= 175 && b <= 0 = 198
234− | r <= 255 && g <= 175 && b <= 95 = 199
235− | r <= 255 && g <= 175 && b <= 135 = 200
236− | r <= 255 && g <= 175 && b <= 175 = 201
237− | r <= 255 && g <= 175 && b <= 215 = 202
238− | r <= 255 && g <= 175 && b <= 255 = 203
239− | r <= 255 && g <= 215 && b <= 0 = 204
240− | r <= 255 && g <= 215 && b <= 95 = 205
241− | r <= 255 && g <= 215 && b <= 135 = 206
242− | r <= 255 && g <= 215 && b <= 175 = 207
243− | r <= 255 && g <= 215 && b <= 215 = 208
244− | r <= 255 && g <= 215 && b <= 255 = 209
245− | r <= 255 && g <= 255 && b <= 0 = 210
246− | r <= 255 && g <= 255 && b <= 95 = 211
247− | r <= 255 && g <= 255 && b <= 135 = 212
248− | r <= 255 && g <= 255 && b <= 175 = 213
249− | r <= 255 && g <= 255 && b <= 215 = 214
250− | r <= 255 && g <= 255 && b <= 255 = 215
251− | otherwise = error (printf "RGB color %d %d %d does not map to 240 palette."
252− (fromIntegral r :: Int)
253− (fromIntegral g :: Int)
254− (fromIntegral b :: Int))
255−
256−sameColor :: Int -> Int -> Int -> Bool
257−sameColor r g b = oldRgbColorToColor240 r g b == rgbColorToColor240 r g b
258−
259−genVal :: Gen Int
260−genVal = chooseInt (0, 255)
261−
262−sameColorCheck :: Property
263−sameColorCheck = forAll genVal (\r -> forAll genVal (\g -> forAll genVal (sameColor r g)))
264−
265−tests :: IO [Test]
266−tests = return
267− [ verify "check rgbColorToColor240 optimization is correct" sameColorCheck
268− ]
269−
test/VerifyEmptyImageProps.hs−1
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2module VerifyEmptyImageProps where
1module VerifyEmptyImageProps where
3
2
4import Verify
3import Verify
test/VerifyEvalTerminfoCaps.hs−1
@@ -1,6 +1,5 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE NamedFieldPuns #-}
2{-# LANGUAGE NamedFieldPuns #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4module VerifyEvalTerminfoCaps where
3module VerifyEvalTerminfoCaps where
5
4
6import Blaze.ByteString.Builder.Internal.Write (runWrite, getBound)
5import Blaze.ByteString.Builder.Internal.Write (runWrite, getBound)
test/VerifyImageOps.hs+1−2
@@ -1,4 +1,3 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2module VerifyImageOps where
1module VerifyImageOps where
3
2
4import Graphics.Vty.Attributes
3import Graphics.Vty.Attributes
@@ -137,7 +136,7 @@ cropBottomLimitsHeight :: Image -> Int -> Property
137cropBottomLimitsHeight i v = v >= 0 ==>
136cropBottomLimitsHeight i v = v >= 0 ==>
138 v >= imageHeight (cropBottom v i)
137 v >= imageHeight (cropBottom v i)
139
138
140−-- ridiculous tests just to satisfy my desire for nice code coverage :-P
139+-- rediculous tests just to satisfy my desire for nice code coverage :-P
141canShowImage :: Image -> Bool
140canShowImage :: Image -> Bool
142canShowImage i = length (show i) > 0
141canShowImage i = length (show i) > 0
143
142
test/VerifyOutput.hs+2−7
@@ -1,7 +1,6 @@
1−-- We setup the environment to invoke certain terminals of interest.
1+-- We setup the environment to envoke certain terminals of interest.
2-- This assumes appropriate definitions exist in the current environment
2-- This assumes appropriate definitions exist in the current environment
3-- for the terminals of interest.
3-- for the terminals of interest.
4−{-# LANGUAGE ScopedTypeVariables #-}
5module VerifyOutput where
4module VerifyOutput where
6
5
7import Verify
6import Verify
@@ -35,11 +34,7 @@ smokeTestTermNonMac termName i = liftIOResult $ do
35smokeTestTerm :: String -> Image -> IO Result
34smokeTestTerm :: String -> Image -> IO Result
36smokeTestTerm termName i = do
35smokeTestTerm termName i = do
37 nullOut <- openFd "/dev/null" WriteOnly Nothing defaultFileFlags
36 nullOut <- openFd "/dev/null" WriteOnly Nothing defaultFileFlags
38− t <- outputForConfig $ defaultConfig
37+ t <- outputForConfig $ defaultConfig { outputFd = Just nullOut, termName = Just termName }
39− { outputFd = Just nullOut
40− , termName = Just termName
41− , colorMode = Just NoColor
42− }
43 -- putStrLn $ "context color count: " ++ show (contextColorCount t)
38 -- putStrLn $ "context color count: " ++ show (contextColorCount t)
44 reserveDisplay t
39 reserveDisplay t
45 dc <- displayContext t (100,100)
40 dc <- displayContext t (100,100)
test/VerifyParseTerminfoCaps.hs−1
@@ -1,5 +1,4 @@
1{-# LANGUAGE NamedFieldPuns #-}
1{-# LANGUAGE NamedFieldPuns #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3module VerifyParseTerminfoCaps where
2module VerifyParseTerminfoCaps where
4
3
5import Prelude hiding ( catch )
4import Prelude hiding ( catch )
test/VerifyUsingMockInput.hs+1−4
@@ -1,6 +1,5 @@
1{-# LANGUAGE MultiParamTypeClasses #-}
1{-# LANGUAGE MultiParamTypeClasses #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4-- Generate some input bytes and delays between blocks of input bytes.
3-- Generate some input bytes and delays between blocks of input bytes.
5-- Verify the events produced are as expected.
4-- Verify the events produced are as expected.
6module Main where
5module Main where
@@ -132,9 +131,7 @@ assertEventsFromSynInput table inputSpec expectedEvents = do
132 readLoop 0 = return ()
131 readLoop 0 = return ()
133 readLoop n = do
132 readLoop n = do
134 e <- atomically $ readTChan $ input^.eventChannel
133 e <- atomically $ readTChan $ input^.eventChannel
135− case e of
136− InputEvent ev -> modifyIORef eventsRef ((:) ev)
134+ modifyIORef eventsRef ((:) e)
137− ResumeAfterSignal -> return ()
138 readLoop (n - 1)
135 readLoop (n - 1)
139 genEventsUsingIoActions maxDuration writeWaitClose readEvents
136 genEventsUsingIoActions maxDuration writeWaitClose readEvents
140 outEvents <- reverse <$> readIORef eventsRef
137 outEvents <- reverse <$> readIORef eventsRef
test/interactive_terminal_test.hs+1−1
@@ -364,7 +364,7 @@ Did the test output match the description?
364|]
364|]
365 defaultSuccessConfirmResults
365 defaultSuccessConfirmResults
366
366
367−-- Explicitly define the bytes that encode each example text.
367+-- Explicitely definethe bytes that encode each example text.
368-- This avoids any issues with how the compiler represents string literals.
368-- This avoids any issues with how the compiler represents string literals.
369--
369--
370-- This document is UTF-8 encoded so the UTF-8 string is still included for
370-- This document is UTF-8 encoded so the UTF-8 string is still included for
tools/BuildWidthTable.hs+10−61
@@ -1,65 +1,40 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
3module Main where
2module Main where
4
3
5−import qualified Control.Exception as E
6import Control.Monad (when)
4import Control.Monad (when)
7import Data.Maybe (fromMaybe)
5import Data.Maybe (fromMaybe)
8#if !(MIN_VERSION_base(4,11,0))
6#if !(MIN_VERSION_base(4,11,0))
9import Data.Semigroup ((<>))
7import Data.Semigroup ((<>))
10#endif
8#endif
11−import System.Directory (createDirectoryIfMissing)
12import System.Environment (getArgs, getProgName)
9import System.Environment (getArgs, getProgName)
13−import System.FilePath (takeDirectory)
14import System.Exit (exitFailure)
10import System.Exit (exitFailure)
15import System.Console.GetOpt
11import System.Console.GetOpt
16−import Text.Read (readMaybe)
17
12
18−import Graphics.Vty.Config ( terminalWidthTablePath, currentTerminalName
13+import Graphics.Vty.Config (terminalWidthTablePath, currentTerminalName, vtyConfigPath)
19− , vtyConfigPath, addConfigWidthMap
20− , ConfigUpdateResult(..)
21− )
22import Graphics.Vty.UnicodeWidthTable.IO
14import Graphics.Vty.UnicodeWidthTable.IO
23import Graphics.Vty.UnicodeWidthTable.Query
15import Graphics.Vty.UnicodeWidthTable.Query
24
16
25data Arg = Help
17data Arg = Help
26 | OutputPath String
18 | OutputPath String
27− | TableUpperBound String
28− | UpdateConfig
29− | VtyConfigPath String
30 deriving (Eq, Show)
19 deriving (Eq, Show)
31
20
32options :: Config -> [OptDescr Arg]
21options :: Config -> [OptDescr Arg]
33options config =
22options config =
34 [ Option "h" ["help"] (NoArg Help)
23 [ Option "h" ["help"] (NoArg Help)
35 "This help output"
24 "This help output"
36− , Option "b" ["bound"] (ReqArg TableUpperBound "MAX_CHAR")
37− ("The maximum Unicode code point to test when building the table " <>
38− "(default: " <> (show $ fromEnum $ configBound config) <> ")")
39 , Option "p" ["path"] (ReqArg OutputPath "PATH")
25 , Option "p" ["path"] (ReqArg OutputPath "PATH")
40 ("The output path to write to (default: " <>
26 ("The output path to write to (default: " <>
41 fromMaybe "<none>" (configOutputPath config) <> ")")
27 fromMaybe "<none>" (configOutputPath config) <> ")")
42− , Option "u" ["update-config"] (NoArg UpdateConfig)
43− "Create or update the Vty configuration file to use the new table (default: no)"
44− , Option "c" ["config-path"] (ReqArg VtyConfigPath "PATH")
45− ("Update the specified Vty configuration file path when -u is set (default: " <>
46− configPath config <> ")")
47 ]
28 ]
48
29
49data Config =
30data Config =
50 Config { configOutputPath :: Maybe FilePath
31 Config { configOutputPath :: Maybe FilePath
51− , configBound :: Char
52− , configUpdate :: Bool
53− , configPath :: FilePath
54 }
32 }
55 deriving (Show)
33 deriving (Show)
56
34
57mkDefaultConfig :: IO Config
35mkDefaultConfig :: IO Config
58mkDefaultConfig = do
36mkDefaultConfig = do
59 Config <$> terminalWidthTablePath
37 Config <$> terminalWidthTablePath
60− <*> pure defaultUnicodeTableUpperBound
61− <*> pure False
62− <*> vtyConfigPath
63
38
64usage :: IO ()
39usage :: IO ()
65usage = do
40usage = do
@@ -78,14 +53,6 @@ usage = do
78updateConfigFromArg :: Arg -> Config -> Config
53updateConfigFromArg :: Arg -> Config -> Config
79updateConfigFromArg Help c =
54updateConfigFromArg Help c =
80 c
55 c
81−updateConfigFromArg UpdateConfig c =
82− c { configUpdate = True }
83−updateConfigFromArg (VtyConfigPath p) c =
84− c { configPath = p }
85−updateConfigFromArg (TableUpperBound s) c =
86− case readMaybe s of
87− Nothing -> error $ "Invalid table upper bound: " <> show s
88− Just v -> c { configBound = toEnum v }
89updateConfigFromArg (OutputPath p) c =
56updateConfigFromArg (OutputPath p) c =
90 c { configOutputPath = Just p }
57 c { configOutputPath = Just p }
91
58
@@ -112,33 +79,15 @@ main = do
112 Just path -> return path
79 Just path -> return path
113
80
114 putStrLn "Querying terminal:"
81 putStrLn "Querying terminal:"
115− builtTable <- buildUnicodeWidthTable $ configBound config
82+ builtTable <- buildUnicodeWidthTable
116−
117− let dir = takeDirectory outputPath
118− createDirectoryIfMissing True dir
119 writeUnicodeWidthTable outputPath builtTable
83 writeUnicodeWidthTable outputPath builtTable
120−
121 putStrLn $ "\nOutput table written to " <> outputPath
84 putStrLn $ "\nOutput table written to " <> outputPath
122
85
123− when (configUpdate config) $ do
124− let cPath = configPath config
125− Just tName <- currentTerminalName
86+ Just tName <- currentTerminalName
126−
87+ configPath <- vtyConfigPath
127− result <- E.try $ addConfigWidthMap cPath tName outputPath
88+ putStrLn ""
128−
89+ putStrLn "To configure your Vty-based applications to use this map, add"
129− case result of
90+ putStrLn $ "the following line to " <> configPath <> ":"
130− Left (e::E.SomeException) -> do
91+ putStrLn ""
131− putStrLn $ "Error updating Vty configuration at " <> cPath <> ": " <>
92+ putStrLn $ " widthMap " <> show tName <> " " <> show outputPath
132− show e
93+ putStrLn ""
133− exitFailure
134− Right ConfigurationCreated -> do
135− putStrLn $ "Configuration file created: " <> cPath
136− Right ConfigurationModified -> do
137− putStrLn $ "Configuration file updated: " <> cPath
138− Right (ConfigurationConflict other) -> do
139− putStrLn $ "Configuration file not updated: uses a different table " <>
140− "for TERM=" <> tName <> ": " <> other
141− Right ConfigurationRedundant -> do
142− putStrLn $ "Configuration file not updated: configuration " <>
143− cPath <> " already uses table " <> outputPath <>
144− " for TERM=" <> tName
vty.cabal+39−51
@@ -1,5 +1,5 @@
1name: vty
1name: vty
2−version: 5.35.1
2+version: 5.27
3license: BSD3
3license: BSD3
4license-file: LICENSE
4license-file: LICENSE
5author: AUTHORS
5author: AUTHORS
@@ -45,7 +45,7 @@ library
45 deepseq >= 1.1 && < 1.5,
45 deepseq >= 1.1 && < 1.5,
46 directory,
46 directory,
47 filepath >= 1.0 && < 2.0,
47 filepath >= 1.0 && < 2.0,
48− microlens < 0.4.13,
48+ microlens < 0.4.12,
49 microlens-mtl,
49 microlens-mtl,
50 microlens-th,
50 microlens-th,
51 hashable >= 1.2,
51 hashable >= 1.2,
@@ -69,7 +69,6 @@ library
69 exposed-modules: Graphics.Vty
69 exposed-modules: Graphics.Vty
70 Graphics.Vty.Attributes
70 Graphics.Vty.Attributes
71 Graphics.Vty.Attributes.Color
71 Graphics.Vty.Attributes.Color
72− Graphics.Vty.Attributes.Color240
73 Graphics.Vty.Config
72 Graphics.Vty.Config
74 Graphics.Vty.Error
73 Graphics.Vty.Error
75 Graphics.Vty.Image
74 Graphics.Vty.Image
@@ -105,7 +104,8 @@ library
105 Graphics.Vty.UnicodeWidthTable.Query
104 Graphics.Vty.UnicodeWidthTable.Query
106 Graphics.Vty.UnicodeWidthTable.Install
105 Graphics.Vty.UnicodeWidthTable.Install
107
106
108− other-modules: Graphics.Vty.Debug.Image
107+ other-modules: Graphics.Vty.Attributes.Color240
108+ Graphics.Vty.Debug.Image
109 Graphics.Vty.Input.Terminfo.ANSIVT
109 Graphics.Vty.Input.Terminfo.ANSIVT
110
110
111 c-sources: cbits/gwinsz.c
111 c-sources: cbits/gwinsz.c
@@ -117,6 +117,9 @@ library
117
117
118 hs-source-dirs: src
118 hs-source-dirs: src
119
119
120+ default-extensions: ScopedTypeVariables
121+ ForeignFunctionInterface
122+
120 ghc-options: -O2 -funbox-strict-fields -Wall -fspec-constr -fspec-constr-count=10
123 ghc-options: -O2 -funbox-strict-fields -Wall -fspec-constr -fspec-constr-count=10
121
124
122 ghc-prof-options: -O2 -funbox-strict-fields -caf-all -Wall -fspec-constr -fspec-constr-count=10
125 ghc-prof-options: -O2 -funbox-strict-fields -caf-all -Wall -fspec-constr -fspec-constr-count=10
@@ -128,12 +131,7 @@ executable vty-build-width-table
128 default-language: Haskell2010
131 default-language: Haskell2010
129 ghc-options: -threaded -Wall
132 ghc-options: -threaded -Wall
130
133
131− if !impl(ghc >= 8.0)
132− build-depends: semigroups >= 0.16
133−
134 build-depends: vty,
134 build-depends: vty,
135− directory,
136− filepath,
137 base >= 4.8 && < 5
135 base >= 4.8 && < 5
138
136
139executable vty-mode-demo
137executable vty-mode-demo
@@ -141,6 +139,7 @@ executable vty-mode-demo
141 hs-source-dirs: demos
139 hs-source-dirs: demos
142
140
143 default-language: Haskell2010
141 default-language: Haskell2010
142+ default-extensions: ScopedTypeVariables
144 ghc-options: -threaded
143 ghc-options: -threaded
145
144
146 build-depends: vty,
145 build-depends: vty,
@@ -155,6 +154,7 @@ executable vty-demo
155 hs-source-dirs: demos
154 hs-source-dirs: demos
156
155
157 default-language: Haskell2010
156 default-language: Haskell2010
157+ default-extensions: ScopedTypeVariables
158 ghc-options: -threaded
158 ghc-options: -threaded
159
159
160 build-depends: vty,
160 build-depends: vty,
@@ -166,6 +166,7 @@ executable vty-demo
166
166
167test-suite verify-using-mock-terminal
167test-suite verify-using-mock-terminal
168 default-language: Haskell2010
168 default-language: Haskell2010
169+ default-extensions: ScopedTypeVariables
169
170
170 type: detailed-0.9
171 type: detailed-0.9
171
172
@@ -184,7 +185,7 @@ test-suite verify-using-mock-terminal
184 build-depends: vty,
185 build-depends: vty,
185 Cabal >= 1.20,
186 Cabal >= 1.20,
186 QuickCheck >= 2.7,
187 QuickCheck >= 2.7,
187− random >= 1.0 && < 1.3,
188+ random >= 1.0 && < 1.2,
188 base >= 4.8 && < 5,
189 base >= 4.8 && < 5,
189 bytestring,
190 bytestring,
190 containers,
191 containers,
@@ -198,6 +199,7 @@ test-suite verify-using-mock-terminal
198
199
199test-suite verify-terminal
200test-suite verify-terminal
200 default-language: Haskell2010
201 default-language: Haskell2010
202+ default-extensions: ScopedTypeVariables
201
203
202 type: detailed-0.9
204 type: detailed-0.9
203
205
@@ -216,7 +218,7 @@ test-suite verify-terminal
216 build-depends: vty,
218 build-depends: vty,
217 Cabal >= 1.20,
219 Cabal >= 1.20,
218 QuickCheck >= 2.7,
220 QuickCheck >= 2.7,
219− random >= 1.0 && < 1.3,
221+ random >= 1.0 && < 1.2,
220 base >= 4.8 && < 5,
222 base >= 4.8 && < 5,
221 bytestring,
223 bytestring,
222 containers,
224 containers,
@@ -230,6 +232,7 @@ test-suite verify-terminal
230
232
231test-suite verify-display-attributes
233test-suite verify-display-attributes
232 default-language: Haskell2010
234 default-language: Haskell2010
235+ default-extensions: ScopedTypeVariables
233
236
234 type: detailed-0.9
237 type: detailed-0.9
235
238
@@ -248,7 +251,7 @@ test-suite verify-display-attributes
248 build-depends: vty,
251 build-depends: vty,
249 Cabal >= 1.20,
252 Cabal >= 1.20,
250 QuickCheck >= 2.7,
253 QuickCheck >= 2.7,
251− random >= 1.0 && < 1.3,
254+ random >= 1.0 && < 1.2,
252 base >= 4.8 && < 5,
255 base >= 4.8 && < 5,
253 bytestring,
256 bytestring,
254 containers,
257 containers,
@@ -261,6 +264,7 @@ test-suite verify-display-attributes
261
264
262test-suite verify-empty-image-props
265test-suite verify-empty-image-props
263 default-language: Haskell2010
266 default-language: Haskell2010
267+ default-extensions: ScopedTypeVariables
264
268
265 type: detailed-0.9
269 type: detailed-0.9
266
270
@@ -273,7 +277,7 @@ test-suite verify-empty-image-props
273 build-depends: vty,
277 build-depends: vty,
274 Cabal >= 1.20,
278 Cabal >= 1.20,
275 QuickCheck >= 2.7,
279 QuickCheck >= 2.7,
276− random >= 1.0 && < 1.3,
280+ random >= 1.0 && < 1.2,
277 base >= 4.8 && < 5,
281 base >= 4.8 && < 5,
278 bytestring,
282 bytestring,
279 containers,
283 containers,
@@ -286,6 +290,7 @@ test-suite verify-empty-image-props
286
290
287test-suite verify-eval-terminfo-caps
291test-suite verify-eval-terminfo-caps
288 default-language: Haskell2010
292 default-language: Haskell2010
293+ default-extensions: ScopedTypeVariables
289
294
290 type: detailed-0.9
295 type: detailed-0.9
291
296
@@ -299,7 +304,7 @@ test-suite verify-eval-terminfo-caps
299 build-depends: vty,
304 build-depends: vty,
300 Cabal >= 1.20,
305 Cabal >= 1.20,
301 QuickCheck >= 2.7,
306 QuickCheck >= 2.7,
302− random >= 1.0 && < 1.3,
307+ random >= 1.0 && < 1.2,
303 base >= 4.8 && < 5,
308 base >= 4.8 && < 5,
304 blaze-builder >= 0.3.3.2 && < 0.5,
309 blaze-builder >= 0.3.3.2 && < 0.5,
305 bytestring,
310 bytestring,
@@ -314,6 +319,7 @@ test-suite verify-eval-terminfo-caps
314
319
315test-suite verify-image-ops
320test-suite verify-image-ops
316 default-language: Haskell2010
321 default-language: Haskell2010
322+ default-extensions: ScopedTypeVariables
317
323
318 type: detailed-0.9
324 type: detailed-0.9
319
325
@@ -328,7 +334,7 @@ test-suite verify-image-ops
328 build-depends: vty,
334 build-depends: vty,
329 Cabal >= 1.20,
335 Cabal >= 1.20,
330 QuickCheck >= 2.7,
336 QuickCheck >= 2.7,
331− random >= 1.0 && < 1.3,
337+ random >= 1.0 && < 1.2,
332 base >= 4.8 && < 5,
338 base >= 4.8 && < 5,
333 bytestring,
339 bytestring,
334 containers,
340 containers,
@@ -341,6 +347,7 @@ test-suite verify-image-ops
341
347
342test-suite verify-image-trans
348test-suite verify-image-trans
343 default-language: Haskell2010
349 default-language: Haskell2010
350+ default-extensions: ScopedTypeVariables
344
351
345 type: detailed-0.9
352 type: detailed-0.9
346
353
@@ -355,7 +362,7 @@ test-suite verify-image-trans
355 build-depends: vty,
362 build-depends: vty,
356 Cabal >= 1.20,
363 Cabal >= 1.20,
357 QuickCheck >= 2.7,
364 QuickCheck >= 2.7,
358− random >= 1.0 && < 1.3,
365+ random >= 1.0 && < 1.2,
359 base >= 4.8 && < 5,
366 base >= 4.8 && < 5,
360 bytestring,
367 bytestring,
361 containers,
368 containers,
@@ -368,6 +375,7 @@ test-suite verify-image-trans
368
375
369test-suite verify-inline
376test-suite verify-inline
370 default-language: Haskell2010
377 default-language: Haskell2010
378+ default-extensions: ScopedTypeVariables
371
379
372 type: detailed-0.9
380 type: detailed-0.9
373
381
@@ -381,7 +389,7 @@ test-suite verify-inline
381 build-depends: vty,
389 build-depends: vty,
382 Cabal >= 1.20,
390 Cabal >= 1.20,
383 QuickCheck >= 2.7,
391 QuickCheck >= 2.7,
384− random >= 1.0 && < 1.3,
392+ random >= 1.0 && < 1.2,
385 base >= 4.8 && < 5,
393 base >= 4.8 && < 5,
386 bytestring,
394 bytestring,
387 containers,
395 containers,
@@ -394,6 +402,7 @@ test-suite verify-inline
394
402
395test-suite verify-parse-terminfo-caps
403test-suite verify-parse-terminfo-caps
396 default-language: Haskell2010
404 default-language: Haskell2010
405+ default-extensions: ScopedTypeVariables
397
406
398 type: detailed-0.9
407 type: detailed-0.9
399
408
@@ -408,7 +417,7 @@ test-suite verify-parse-terminfo-caps
408 build-depends: vty,
417 build-depends: vty,
409 Cabal >= 1.20,
418 Cabal >= 1.20,
410 QuickCheck >= 2.7,
419 QuickCheck >= 2.7,
411− random >= 1.0 && < 1.3,
420+ random >= 1.0 && < 1.2,
412 base >= 4.8 && < 5,
421 base >= 4.8 && < 5,
413 bytestring,
422 bytestring,
414 containers,
423 containers,
@@ -422,6 +431,7 @@ test-suite verify-parse-terminfo-caps
422
431
423test-suite verify-simple-span-generation
432test-suite verify-simple-span-generation
424 default-language: Haskell2010
433 default-language: Haskell2010
434+ default-extensions: ScopedTypeVariables
425
435
426 type: detailed-0.9
436 type: detailed-0.9
427
437
@@ -439,7 +449,7 @@ test-suite verify-simple-span-generation
439 build-depends: vty,
449 build-depends: vty,
440 Cabal >= 1.20,
450 Cabal >= 1.20,
441 QuickCheck >= 2.7,
451 QuickCheck >= 2.7,
442− random >= 1.0 && < 1.3,
452+ random >= 1.0 && < 1.2,
443 base >= 4.8 && < 5,
453 base >= 4.8 && < 5,
444 bytestring,
454 bytestring,
445 containers,
455 containers,
@@ -453,6 +463,7 @@ test-suite verify-simple-span-generation
453
463
454test-suite verify-crop-span-generation
464test-suite verify-crop-span-generation
455 default-language: Haskell2010
465 default-language: Haskell2010
466+ default-extensions: ScopedTypeVariables
456
467
457 type: detailed-0.9
468 type: detailed-0.9
458
469
@@ -470,7 +481,7 @@ test-suite verify-crop-span-generation
470 build-depends: vty,
481 build-depends: vty,
471 Cabal >= 1.20,
482 Cabal >= 1.20,
472 QuickCheck >= 2.7,
483 QuickCheck >= 2.7,
473− random >= 1.0 && < 1.3,
484+ random >= 1.0 && < 1.2,
474 base >= 4.8 && < 5,
485 base >= 4.8 && < 5,
475 bytestring,
486 bytestring,
476 containers,
487 containers,
@@ -484,6 +495,7 @@ test-suite verify-crop-span-generation
484
495
485test-suite verify-layers-span-generation
496test-suite verify-layers-span-generation
486 default-language: Haskell2010
497 default-language: Haskell2010
498+ default-extensions: ScopedTypeVariables
487
499
488 type: detailed-0.9
500 type: detailed-0.9
489
501
@@ -501,32 +513,7 @@ test-suite verify-layers-span-generation
501 build-depends: vty,
513 build-depends: vty,
502 Cabal >= 1.20,
514 Cabal >= 1.20,
503 QuickCheck >= 2.7,
515 QuickCheck >= 2.7,
504− random >= 1.0 && < 1.3,
516+ random >= 1.0 && < 1.2,
505− base >= 4.8 && < 5,
506− bytestring,
507− containers,
508− deepseq >= 1.1 && < 1.5,
509− mtl >= 1.1.1.0 && < 2.3,
510− text >= 0.11.3,
511− unix,
512− utf8-string >= 0.3 && < 1.1,
513− vector >= 0.7
514−
515−test-suite verify-color-mapping
516− default-language: Haskell2010
517−
518− type: detailed-0.9
519−
520− hs-source-dirs: test
521−
522− test-module: VerifyColor240
523−
524− other-modules: Verify
525−
526− build-depends: vty,
527− Cabal >= 1.20,
528− QuickCheck >= 2.7,
529− random >= 1.0 && < 1.3,
530 base >= 4.8 && < 5,
517 base >= 4.8 && < 5,
531 bytestring,
518 bytestring,
532 containers,
519 containers,
@@ -539,6 +526,7 @@ test-suite verify-color-mapping
539
526
540test-suite verify-utf8-width
527test-suite verify-utf8-width
541 default-language: Haskell2010
528 default-language: Haskell2010
529+ default-extensions: ScopedTypeVariables
542
530
543 type: detailed-0.9
531 type: detailed-0.9
544
532
@@ -551,7 +539,7 @@ test-suite verify-utf8-width
551 build-depends: vty,
539 build-depends: vty,
552 Cabal >= 1.20,
540 Cabal >= 1.20,
553 QuickCheck >= 2.7,
541 QuickCheck >= 2.7,
554− random >= 1.0 && < 1.3,
542+ random >= 1.0 && < 1.2,
555 base >= 4.8 && < 5,
543 base >= 4.8 && < 5,
556 bytestring,
544 bytestring,
557 containers,
545 containers,
@@ -564,6 +552,7 @@ test-suite verify-utf8-width
564
552
565test-suite verify-using-mock-input
553test-suite verify-using-mock-input
566 default-language: Haskell2010
554 default-language: Haskell2010
555+ default-extensions: ScopedTypeVariables
567
556
568 type: exitcode-stdio-1.0
557 type: exitcode-stdio-1.0
569
558
@@ -571,8 +560,6 @@ test-suite verify-using-mock-input
571
560
572 main-is: VerifyUsingMockInput.hs
561 main-is: VerifyUsingMockInput.hs
573
562
574− other-modules: Verify.Graphics.Vty.Output
575−
576 build-depends: vty,
563 build-depends: vty,
577 Cabal >= 1.20,
564 Cabal >= 1.20,
578 QuickCheck >= 2.7,
565 QuickCheck >= 2.7,
@@ -580,7 +567,7 @@ test-suite verify-using-mock-input
580 quickcheck-assertions >= 0.1.1,
567 quickcheck-assertions >= 0.1.1,
581 test-framework == 0.8.*,
568 test-framework == 0.8.*,
582 test-framework-smallcheck == 0.2.*,
569 test-framework-smallcheck == 0.2.*,
583− random >= 1.0 && < 1.3,
570+ random >= 1.0 && < 1.2,
584 base >= 4.8 && < 5,
571 base >= 4.8 && < 5,
585 bytestring,
572 bytestring,
586 containers,
573 containers,
@@ -599,6 +586,7 @@ test-suite verify-using-mock-input
599
586
600test-suite verify-config
587test-suite verify-config
601 default-language: Haskell2010
588 default-language: Haskell2010
589+ default-extensions: ScopedTypeVariables
602
590
603 type: exitcode-stdio-1.0
591 type: exitcode-stdio-1.0
604
592
@@ -615,7 +603,7 @@ test-suite verify-config
615 test-framework == 0.8.*,
603 test-framework == 0.8.*,
616 test-framework-smallcheck == 0.2.*,
604 test-framework-smallcheck == 0.2.*,
617 test-framework-hunit,
605 test-framework-hunit,
618− random >= 1.0 && < 1.3,
606+ random >= 1.0 && < 1.2,
619 base >= 4.8 && < 5,
607 base >= 4.8 && < 5,
620 bytestring,
608 bytestring,
621 containers,
609 containers,