Browse Source

add implementation of zipper (not fully functional yet)

master
Wesley Kerfoot 4 years ago
parent
commit
21123c2195
  1. 66
      src/nimwin.nim

66
src/nimwin.nim

@ -1,5 +1,5 @@
import x11/xlib, x11/xutil, x11/x, x11/keysym
import threadpool, osproc, tables, sequtils, posix, strformat, os, sugar, options, strutils
import threadpool, osproc, tables, sequtils, posix, strformat, os, sugar, options, strutils, algorithm
var root : TWindow
@ -48,6 +48,59 @@ type Window = ref object of RootObj
screen : PScreen
props : seq[WinProp]
type Zipper[T] = tuple[
lhs: seq[T],
rhs: seq[T]
]
proc zipperFocus[T](zipper: Zipper[T]) : Option[T] =
if zipper.rhs.len > 0:
some(zipper.rhs[0])
else:
none(T)
proc zipperMove[T](zipper: Zipper[T], direction: string) : Zipper[T] =
# This implements a "zipper" data structure
# A zipper is a data structure with a "focus"
# i.e. a pointer into a particular position
# in this case we have a zipper of a list, so we have
# a list with a focus that lets us move left or right
# and it will wrap around to the other side in either direction
#
# This function will always allocate a new structure (or leave it untouched)
# and won't mutate the original, as this is an immutable data structure
if zipper.rhs.len == 0 and zipper.lhs.len == 0:
return zipper
if direction == "right" and zipper.rhs.len == 1:
result.lhs = @[]
result.rhs = zipper.lhs.reversed & zipper.rhs # append head(rhs) to lhs
return
if direction == "right":
result.lhs = @[zipper.rhs[0]] & zipper.lhs # cons head(rhs) onto lhs
result.rhs = zipper.rhs[1..^1] # drop head of rhs
if direction == "left" and zipper.lhs.len == 0:
result.lhs = zipper.rhs.reversed[1..^1] # make lhs = tail of rhs
result.rhs = @[zipper.rhs.reversed[0]] # make the focus be the last item in the rhs
return
if direction == "left":
result.lhs = zipper.lhs[1..^1] # drop the head of the lhs
result.rhs = @[zipper.lhs[0]] & zipper.rhs # move the focus left
proc zipperInsert[T](zipper: Zipper[T], item: T) : Zipper[T] =
# insert a new item before as the current focus
result.lhs = zipper.lhs
result.rhs = @[item] & zipper.rhs
proc zipperRemove[T](zipper: Zipper[T], item: T) : Zipper[T] =
# find and delete an item in the zipper
result.lhs = filter(zipper.lhs, (x) => x != item)
result.rhs = filter(zipper.rhs, (x) => x != item)
proc unpackPropValue(typeFormat : int,
nItems : int,
buf : ptr cuchar) : seq[uint] =
@ -400,6 +453,17 @@ when isMainModule:
var openProcesses = initTable[int, Process]() # hashset of processes
var windowZipper : Zipper[TWindow]
# When a window is opened: goes on the top of the rhs stack, focus is moved to it
# When a window is destroyed:
# if it is the current focus:
# remove it from the zipper and focus on the next rhs window, or move the the start of the lhs, or do nothing if no other windows
# if it is not the current focus:
# remove it from the zipper, and keep the current focus
# When focus is changed:
# simply move the focus pointer right, wrapping around if necessary
discard XSetErrorHandler(handleBadWindow)
discard XSetIOErrorHandler(handleIOError)

Loading…
Cancel
Save