summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/collections/sequtils.nim59
-rw-r--r--lib/pure/events.nim83
2 files changed, 142 insertions, 0 deletions
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
new file mode 100644
index 000000000..59d0d2658
--- /dev/null
+++ b/lib/pure/collections/sequtils.nim
@@ -0,0 +1,59 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Alex Mitchell
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## :Author: Alex Mitchell
+##
+## This module implements operations for the built-in `seq`:idx: type
+## which were inspired by functional programming languages.
+
+proc concat*[T](seqs: openarray[seq[T]]): seq[T] =
+  ## Takes several sequences' items and returns them inside of one sequence.
+  var L = 0
+  for seqitm in items(seqs): inc(L, len(seqitm))
+  newSeq(result, L)
+  var i = 0
+  for s in items(seqs):
+    for itm in items(s):
+      result[i] = itm
+      inc(i)
+
+proc distnct*[T](seq1: seq[T]): seq[T] =
+  ## Removes duplicates from a sequence and returns it.
+  result = @[]
+  for itm in items(seq1):
+    if not result.contains(itm): result.add(itm)
+    
+proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
+  ## Combines two sequences. If one sequence is too short,
+  ## the remaining items in the longer sequence are discarded.
+  var m = min(seq1.len, seq2.len)
+  newSeq(result, m)
+  for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
+
+iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool): T =
+  ## Iterates through a sequence and yields every item that fulfills the
+  ## predicate.
+  for i in countup(0, len(seq1) -1):
+    var item = seq1[i]
+    if pred(item): yield seq1[i]
+
+proc filter*[T](seq1: seq[T], pred: proc(item: T): bool): seq[T] =
+  ## Returns all items in a sequence that fulfilled the predicate.
+  accumulateResult(filter(seq1, pred))
+
+template filterIt*(seq1, pred: expr): expr =
+  ## Finds a specific item in a sequence as long as the 
+  ## predicate returns true. The predicate needs to be an expression
+  ## containing ``it``: ``filterIt("abcxyz", it == 'x')``.
+  block:
+    var result: type(seq1) = @[]
+    for it in items(seq1):
+      if pred: result.add(it)
+    result
+
diff --git a/lib/pure/events.nim b/lib/pure/events.nim
new file mode 100644
index 000000000..00d6797d2
--- /dev/null
+++ b/lib/pure/events.nim
@@ -0,0 +1,83 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Alex Mitchell
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## :Author: Alex Mitchell
+##
+## This module implements an event system that is not dependant on external
+## graphical toolkits. It was originally called ``NimEE`` because 
+## it was inspired by Ptyhon's PyEE module.
+
+type
+  TEventArgs* = object of TObject ## Base object for event arguments
+                                  ## that are passed to callback functions.
+  TEventHandler = tuple[name: string, handlers: seq[proc(e:TEventArgs)]]
+  PEventHandler* = ref TEventHandler ## An eventhandler for an event.
+
+type
+  TEventEmitter = object {.pure, final.}
+    s: seq[PEventHandler]
+  PEventEmitter* = ref TEventEmitter ## An object that fires events and 
+                                     ## holds event handlers for an object.
+  EInvalidEvent* = object of EInvalidValue
+    
+proc newEventHandler*(name: string): PEventHandler =
+  ## Initializes an EventHandler with the specified name and returns it.
+  new(result)
+  result.handlers = @[]
+  result.name = name
+
+proc addHandler*(handler: PEventHandler, func: proc(e: TEventArgs)) =
+  ## Adds the callback to the specified event handler.
+  handler.handlers.add(func)
+
+proc removeHandler*(handler: PEventHandler, func: proc(e: TEventArgs)) =
+  ## Removes the callback from the specified event handler.
+  for i in countup(0, len(handler.handlers) -1):
+    if func == handler.handlers[i]:
+      handler.handlers.del(i)
+      break
+    
+proc clearHandlers*(handler: PEventHandler) =
+  ## Clears all of the callbacks from the event handler.
+  setLen(handler.handlers, 0)
+
+proc getEventhandler(emitter: PEventEmitter, event: string): int =
+  for k in 0..high(emitter.s):
+    if emitter.s[k].name == event: return k
+  return -1
+
+proc on*(emitter: PEventEmitter, event: string, func: proc(e: TEventArgs)) =
+  ## Assigns a event handler with the specified callback. If the event
+  ## doesn't exist, it will be created.
+  var i = getEventHandler(emitter, event)
+  if i < 0:
+    var eh = newEventHandler(event)
+    addHandler(eh, func)
+    emitter.s.add(eh)
+  else:
+    addHandler(emitter.s[i], func)
+  
+proc emit*(emitter: PEventEmitter, eventhandler: PEventHandler, 
+           args: TEventArgs) =
+  ## Fires an event handler with specified event arguments.
+  for func in items(eventhandler.handlers): func(args)
+
+proc emit*(emitter: PEventEmitter, event: string, args: TEventArgs) =
+  ## Fires an event handler with specified event arguments.
+  var i = getEventHandler(emitter, event)
+  if i >= 0:
+    emit(emitter, emitter.s[i], args)
+  else:
+    raise newException(EInvalidEvent, "invalid event: " & event)
+
+proc newEventEmitter*(): PEventEmitter =
+  ## Creates and returns a new EventEmitter.
+  new(result)
+  result.s = @[]
+