Skip to content

Commit

Permalink
Cleanup event pragma
Browse files Browse the repository at this point in the history
* Move getting events to top of file so `event` pragma can use it

* Perform check that event is correctly named

Properly retain line info for better autocomplete

* Clean up how line info is copied
  • Loading branch information
ire4ever1190 authored Feb 17, 2024
1 parent 4b4f0ec commit 0ba8315
Showing 1 changed file with 41 additions and 32 deletions.
73 changes: 41 additions & 32 deletions dimscord/helpers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,41 @@ import typetraits, json
import std/[macros, macrocache]
include ./helpers/[channel, guild, message, user]

const
procsTable = macrocache.CacheTable"dimscord.handlerTypes"
## Stores a mapping of EventName -> parameters for event
## Note:: The shared parameter is removed from them
dimscordEvents = macrocache.CacheTable"dimscord.eventNames"
## Stores names of events that exist. Basically
## a HashSet

# Build up the procsTable
static:
# getTypleImpl returns `ref ObjSym` so we need to get the impl of ObjSym
let impl = Events.getTypeImpl()[0].getImpl()
for identDefs in impl[2][2]:
var typ = identDefs[^2]

# Desym all the parameters
var params = newSeq[NimNode]()
# Skip return type and shard parameter
for identDef in typ[0][2 .. ^1]:
var newDef = nnkIdentDefs.newTree()
for param in identDef[0 ..< ^2]:
newDef &= ident $param
newDef &= identDef[^2]
newDef &= identDef[^1]
params &= newDef

for field in identDefs[0 ..< ^2]:
# Not exported so just ignore it
if field.kind == nnkIdent: continue
# Remove the on_ prefix for some events
let origName = $field[1]
let name = if origName == "on_dispatch": "unknown"
else: dup(origName, removePrefix("on_"))
procsTable[name] = newStmtList(params).copy()
dimscordEvents[origName.nimIdentNormalize()] = newEmptyNode()

macro event*(discord: DiscordClient, fn: untyped): untyped =
## Sugar for registering an event handler.
Expand All @@ -33,9 +68,14 @@ macro event*(discord: DiscordClient, fn: untyped): untyped =

if pragmas.findChild(it.strVal == "async").kind == nnkNilLit:
anonFn.addPragma ident("async")
# Check the event is valid, give proper error if it isn't
if eventName.strVal.nimIdentNormalize() notin dimscordEvents:
fmt"'{eventName}' is not a valid dimscord event".error(eventName)

quote:
result = quote:
`discord`.events.`eventName` = `anonFn`
# Make sure the `anonFn` keeps its line info
result[1].copyLineInfo(fn)

proc defaultAvatarUrl*(u: User): string =
## Returns the default avatar for a user.
Expand Down Expand Up @@ -463,37 +503,6 @@ proc add*(component: var MessageComponent, item: SelectMenuOption) =

# Event Handlers

const procsTable = macrocache.CacheTable"dimscord.handlerTypes"
## Stores a mapping of EventName -> parameters for event
## Note:: The shared parameter is removed from them

# Build up the procsTable
static:
# getTypleImpl returns `ref ObjSym` so we need to get the impl of ObjSym
let impl = Events.getTypeImpl()[0].getImpl()
for identDefs in impl[2][2]:
var typ = identDefs[^2]

# Desym all the parameters
var params = newSeq[NimNode]()
# Skip return type and shard parameter
for identDef in typ[0][2 .. ^1]:
var newDef = nnkIdentDefs.newTree()
for param in identDef[0 ..< ^2]:
newDef &= ident $param
newDef &= identDef[^2]
newDef &= identDef[^1]
params &= newDef

for field in identDefs[0 ..< ^2]:
# Not exported so just ignore it
if field.kind == nnkIdent: continue
# Remove the on_ prefix for some events
let origName = $field[1]
let name = if origName == "on_dispatch": "unknown"
else: dup(origName, removePrefix("on_"))
procsTable[name] = newStmtList(params).copy()

proc params(event: DispatchEvent): NimNode =
## Returns the proc type stored for an event
var evt = toLowerAscii($event)
Expand Down

0 comments on commit 0ba8315

Please sign in to comment.