A Go port of Free Vision, the Turbo-Vision-derived console UI framework originally from Free Pascal. Based on the modernized Delphi version at oldwired/fv-delphi-modern, not the original Free Pascal sources.
Status: full vertical slice up to and including an embedded VT terminal emulator. macOS / Linux first-class; Windows builds clean (ConPTY-backed terminal, otherwise feature-parity).
View, Group, Window (drag/resize/zoom/close),
Frame, ScrollBar, Scroller, ListViewer, Background,
SplitGroup.Program / Application / Desktop, idle loop with
dirty-tracking, anim ticker, pre-flush hook for SIXEL z-order,
wake-channel so async data (PTY output) doesn't wait for the next
keystroke.MenuBar, MenuBox (nested submenus, hotkeys, Alt+letter,
Left/Right cycling between top-level menus), StatusLine.Dialog, Button, InputLine, Cluster (radio /
check), ListBox / StringListBox, Label, StaticText,
ParamText, History, CheckListBox, InputLong.msgbox, classic single-pane stddlg.Show
(file/save/changeDir), modern split-pane stddlg.ShowModern with
lazy-loaded directory tree + file-info pane.OnExpand), AsciiTab, SpinnerView,
TaskProgress, Breadcrumb, Calendar, ColorSel.EditorGutter for line numbers /
breakpoints / bookmarks; pluggable syntax highlighting via
widgets/syntax), HexEdit, Grid, MarkdownView, LogViewer,
FuzzyFinder.Sampler callback so the framework stays
portable.pkg/fv/sixel realtime (216-cube) + quality
(median-cut + Floyd-Steinberg) encoders, cell-pixel-size probe via
CSI 16t, ImageView (PNG/JPEG/GIF/BMP/TIFF/WebP) and
SixelCanvasView (programmable pixel canvas with line/rect/fill
primitives). Half-block fallback on terminals without SIXEL.widgets/terminal. PTY-backed shell via
creack/pty on Unix and ConPTY on Windows. VT100 + xterm parser
covering plain text + UTF-8, the C0 set, CSI cursor/erase/SGR/scroll,
DEC private modes (autowrap, cursor vis, alt screen), OSC 0/1/2
titles. 2000-line scrollback with /-search; drag-to-select +
clipboard copy; mouse forwarding when the inner program asks for it.package main
import (
"github.com/oldwired/fv-go/pkg/fv/app"
"github.com/oldwired/fv-go/pkg/fv/consts"
"github.com/oldwired/fv-go/pkg/fv/dialogs"
"github.com/oldwired/fv-go/pkg/fv/drivers"
"github.com/oldwired/fv-go/pkg/fv/geom"
"github.com/oldwired/fv-go/pkg/fv/menus"
"github.com/oldwired/fv-go/pkg/fv/views"
)
func main() {
a, err := app.NewApplication()
if err != nil {
panic(err)
}
defer a.Done()
cols := a.BaseView().Size.X
a.SetMenuBar(menus.NewMenuBar(geom.NewRect(0, 0, cols, 1),
menus.NewMenu(
&menus.Item{Name: "~F~ile", Sub: menus.NewMenu(
&menus.Item{Name: "~Q~uit", Command: consts.CmQuitApp},
)},
)))
a.OnCommand = func(cmd uint16, ev *drivers.Event) bool {
// Custom commands land here.
return false
}
// Open a window with a button. NewWindow's third arg is the
// number badge in the frame title — 0 means no badge.
win := views.NewWindow(geom.NewRect(5, 3, 40, 10), "Hello", 0)
win.Insert(dialogs.NewButton(geom.NewRect(2, 2, 16, 3), "~C~lick me",
consts.CmOK, dialogs.BfDefault))
a.Desktop.InsertWindow(win)
a.Run()
}
See docs/QUICKSTART.md for a deeper tour and cmd/fvdemo/ for a
fully-loaded demo exercising every widget.
go run ./cmd/fvdemo
The demo opens with a menu bar; explore via Test → Widgets /
Test → Apps for the widget showcases. On a SIXEL-capable terminal
(iTerm2, WezTerm, kitty, Windows Terminal ≥ 1.22), Apps → Image View (Open...) and Apps → Sixel Canvas render true pixel graphics.
Application: app.Application / app.Program / app.Desktop (app/)
Widgets: Dialog, Button, InputLine, ListBox, … (dialogs/, widgets/*)
Views: View, Group, Window, Frame, ScrollBar, Scroller (views/)
Drivers: Event queue, keyboard, mouse (drivers/)
Console output, VT/SGR, SIXEL (term/, sixel/)
Foundation: Cell types, geom, unicode width, profile (types/, geom/, unicode/, utf8/, profile/)
The layering matches the Delphi reference: each layer only depends on
the ones below it. The four cross-cutting interfaces from Pascal
(IFVDrawable, IFVEventHandler, IFVDataAware, ISerializable)
become Go interfaces satisfied structurally by views.View.
These are the non-obvious mappings the original PORTING.md won't give
you:
TGroup : TView, TWindow : TGroup,
etc. are rewritten with embedding + interface satisfaction. Virtual
dispatch goes through a self View back-pointer set by SetSelf
during construction.InitGroup, InitWindow, InitDialog
exist alongside the NewX constructors to avoid the struct-copy bug
that orphans child Owner pointers — initialize via these whenever
you embed a Group / Window / Dialog by value._AddRef/_Release plumbing.TFVStream → io.Reader/io.Writer for streaming;
persistence-with-type-tags maps cleanly to encoding/json + a type
registry (pkg/fv/serial).FVUnicodeWidth.pas) is data, not logic — ported
verbatim into pkg/fv/unicode. Emoji and CJK rendering depends on
the wide / zero-width / combining classification.FVScreen.pas (Windows
Console API) and FVClipboard.pas (Win32 clipboard) are replaced by
the hand-rolled VT/SGR writer in pkg/fv/term and OSC 52 clipboard
in pkg/fv/clipboard. Cross-platform from day one.Inherits the Free Vision / Free Pascal license:
LICENSE — GNU Lesser General Public License, version 2.1.FPC-EXCEPTION.txt — Free Pascal library linking exception, which
permits linking against modified versions without forcing the
linked work to be LGPL.SPDX-License-Identifier: LGPL-2.1-or-later WITH FPC-modified-LGPL-exception
The practical effect of the FPC exception is that you may distribute
statically linked binaries without needing to make your application's
source available, provided you preserve the fv-go license headers
and provide notice that the library may be replaced or recompiled.
See FPC-EXCEPTION.txt for the exact terms. Original-author
copyright headers are preserved inside each ported unit.
Each tagged GitHub Release ships a CycloneDX SBOM
(fv-go-vX.Y.Z.cdx.json) describing the module's declared dependency
graph and the detected license of every component. Generated by
cyclonedx-gomod in
CI on tag push — see .github/workflows/release.yml.
gh release download vX.Y.Z -p '*.cdx.json'
47 commits
Go
100.0%
A Go port of Free Vision, the Turbo-Vision-derived console UI framework originally from Free Pascal. Based on the modernized Delphi version at oldwired/fv-delphi-modern, not the original Free Pascal sources.
Status: full vertical slice up to and including an embedded VT terminal emulator. macOS / Linux first-class; Windows builds clean (ConPTY-backed terminal, otherwise feature-parity).
View, Group, Window (drag/resize/zoom/close),
Frame, ScrollBar, Scroller, ListViewer, Background,
SplitGroup.Program / Application / Desktop, idle loop with
dirty-tracking, anim ticker, pre-flush hook for SIXEL z-order,
wake-channel so async data (PTY output) doesn't wait for the next
keystroke.MenuBar, MenuBox (nested submenus, hotkeys, Alt+letter,
Left/Right cycling between top-level menus), StatusLine.Dialog, Button, InputLine, Cluster (radio /
check), ListBox / StringListBox, Label, StaticText,
ParamText, History, CheckListBox, InputLong.msgbox, classic single-pane stddlg.Show
(file/save/changeDir), modern split-pane stddlg.ShowModern with
lazy-loaded directory tree + file-info pane.OnExpand), AsciiTab, SpinnerView,
TaskProgress, Breadcrumb, Calendar, ColorSel.EditorGutter for line numbers /
breakpoints / bookmarks; pluggable syntax highlighting via
widgets/syntax), HexEdit, Grid, MarkdownView, LogViewer,
FuzzyFinder.Sampler callback so the framework stays
portable.pkg/fv/sixel realtime (216-cube) + quality
(median-cut + Floyd-Steinberg) encoders, cell-pixel-size probe via
CSI 16t, ImageView (PNG/JPEG/GIF/BMP/TIFF/WebP) and
SixelCanvasView (programmable pixel canvas with line/rect/fill
primitives). Half-block fallback on terminals without SIXEL.widgets/terminal. PTY-backed shell via
creack/pty on Unix and ConPTY on Windows. VT100 + xterm parser
covering plain text + UTF-8, the C0 set, CSI cursor/erase/SGR/scroll,
DEC private modes (autowrap, cursor vis, alt screen), OSC 0/1/2
titles. 2000-line scrollback with /-search; drag-to-select +
clipboard copy; mouse forwarding when the inner program asks for it.package main
import (
"github.com/oldwired/fv-go/pkg/fv/app"
"github.com/oldwired/fv-go/pkg/fv/consts"
"github.com/oldwired/fv-go/pkg/fv/dialogs"
"github.com/oldwired/fv-go/pkg/fv/drivers"
"github.com/oldwired/fv-go/pkg/fv/geom"
"github.com/oldwired/fv-go/pkg/fv/menus"
"github.com/oldwired/fv-go/pkg/fv/views"
)
func main() {
a, err := app.NewApplication()
if err != nil {
panic(err)
}
defer a.Done()
cols := a.BaseView().Size.X
a.SetMenuBar(menus.NewMenuBar(geom.NewRect(0, 0, cols, 1),
menus.NewMenu(
&menus.Item{Name: "~F~ile", Sub: menus.NewMenu(
&menus.Item{Name: "~Q~uit", Command: consts.CmQuitApp},
)},
)))
a.OnCommand = func(cmd uint16, ev *drivers.Event) bool {
// Custom commands land here.
return false
}
// Open a window with a button. NewWindow's third arg is the
// number badge in the frame title — 0 means no badge.
win := views.NewWindow(geom.NewRect(5, 3, 40, 10), "Hello", 0)
win.Insert(dialogs.NewButton(geom.NewRect(2, 2, 16, 3), "~C~lick me",
consts.CmOK, dialogs.BfDefault))
a.Desktop.InsertWindow(win)
a.Run()
}
See docs/QUICKSTART.md for a deeper tour and cmd/fvdemo/ for a
fully-loaded demo exercising every widget.
go run ./cmd/fvdemo
The demo opens with a menu bar; explore via Test → Widgets /
Test → Apps for the widget showcases. On a SIXEL-capable terminal
(iTerm2, WezTerm, kitty, Windows Terminal ≥ 1.22), Apps → Image View (Open...) and Apps → Sixel Canvas render true pixel graphics.
Application: app.Application / app.Program / app.Desktop (app/)
Widgets: Dialog, Button, InputLine, ListBox, … (dialogs/, widgets/*)
Views: View, Group, Window, Frame, ScrollBar, Scroller (views/)
Drivers: Event queue, keyboard, mouse (drivers/)
Console output, VT/SGR, SIXEL (term/, sixel/)
Foundation: Cell types, geom, unicode width, profile (types/, geom/, unicode/, utf8/, profile/)
The layering matches the Delphi reference: each layer only depends on
the ones below it. The four cross-cutting interfaces from Pascal
(IFVDrawable, IFVEventHandler, IFVDataAware, ISerializable)
become Go interfaces satisfied structurally by views.View.
These are the non-obvious mappings the original PORTING.md won't give
you:
TGroup : TView, TWindow : TGroup,
etc. are rewritten with embedding + interface satisfaction. Virtual
dispatch goes through a self View back-pointer set by SetSelf
during construction.InitGroup, InitWindow, InitDialog
exist alongside the NewX constructors to avoid the struct-copy bug
that orphans child Owner pointers — initialize via these whenever
you embed a Group / Window / Dialog by value._AddRef/_Release plumbing.TFVStream → io.Reader/io.Writer for streaming;
persistence-with-type-tags maps cleanly to encoding/json + a type
registry (pkg/fv/serial).FVUnicodeWidth.pas) is data, not logic — ported
verbatim into pkg/fv/unicode. Emoji and CJK rendering depends on
the wide / zero-width / combining classification.FVScreen.pas (Windows
Console API) and FVClipboard.pas (Win32 clipboard) are replaced by
the hand-rolled VT/SGR writer in pkg/fv/term and OSC 52 clipboard
in pkg/fv/clipboard. Cross-platform from day one.Inherits the Free Vision / Free Pascal license:
LICENSE — GNU Lesser General Public License, version 2.1.FPC-EXCEPTION.txt — Free Pascal library linking exception, which
permits linking against modified versions without forcing the
linked work to be LGPL.SPDX-License-Identifier: LGPL-2.1-or-later WITH FPC-modified-LGPL-exception
The practical effect of the FPC exception is that you may distribute
statically linked binaries without needing to make your application's
source available, provided you preserve the fv-go license headers
and provide notice that the library may be replaced or recompiled.
See FPC-EXCEPTION.txt for the exact terms. Original-author
copyright headers are preserved inside each ported unit.
Each tagged GitHub Release ships a CycloneDX SBOM
(fv-go-vX.Y.Z.cdx.json) describing the module's declared dependency
graph and the detected license of every component. Generated by
cyclonedx-gomod in
CI on tag push — see .github/workflows/release.yml.
gh release download vX.Y.Z -p '*.cdx.json'
47 commits
Go
100.0%