refract some code

* change some comments ## to #
* [code-reuse] use inv to print volume
* remove procedure brackets
This commit is contained in:
Anton 2024-04-16 18:36:51 +05:30
parent 26f9538661
commit be71b5ba8a
7 changed files with 111 additions and 140 deletions

View file

@ -1,4 +1,4 @@
import os, terminal, src/[ui, menu] import os, src/menu
if not dirExists getAppDir() / "assets": if not dirExists getAppDir() / "assets":
error "data or config files dont exist" error "data or config files dont exist"

View file

@ -167,71 +167,73 @@ type #enums
ctx.setProperty("property", formatNone, addr value) ctx.setProperty("property", formatNone, addr value)
]## ]##
fmtNodeArray = 7, ##used with Node (not directly!) fmtNodeArray = 7, #used with Node (not directly!)
fmtNodeMap = 8, ##see formatNodeArray fmtNodeMap = 8, #see formatNodeArray
fmtByteArray = 9 ##raw, untyped byteArray, used with Node (used for fmtByteArray = 9 #raw, untyped byteArray, used with Node (used for
##screenshot-raw command) #screenshot-raw command)
EventID* = enum ##Event type EventID* = enum #Event type
IDNone = 0, ##nothing happened (when timeouts or IDNone = 0, #nothing happened (when timeouts or
##sporadic wakeups) ##sporadic wakeups)
IDShutdown = 1, ##[ when player quits, it tries to IDShutdown = 1, #[ when player quits, it tries to
disconnect all clients but most requests to player will fail, so disconnect all clients but most requests to player will fail, so
client should quit with destroy() client should quit with destroy()
]## ]##
IDLogMessage = 2, ##see requestLogMessages() IDLogMessage = 2, #see requestLogMessages()
IDGetPropertyReply = 3, ##reply to getPropertyAsync(), IDGetPropertyReply = 3, #reply to getPropertyAsync(),
##(see Event, EventProperty) #(see Event, EventProperty)
IDSetPropertyReply = 4, ##reply to setPropertyAsync(), IDSetPropertyReply = 4, #reply to setPropertyAsync(),
##EventProperty is not used #EventProperty is not used
IDCommandReply = 5, ##reply to commandAsync() or IDCommandReply = 5, #reply to commandAsync() or
##commandNodeAsync() (see EventID, EventCmd) #commandNodeAsync() (see EventID, EventCmd)
IDStartFile = 6, ##notification before playback start of IDStartFile = 6, #notification before playback start of
##file (before loading) #file (before loading)
IDEndFile = 7, ##notification after playback ends,after IDEndFile = 7, #notification after playback ends,after
##unloading, see EventID #unloading, see EventID
IDFileLoaded = 8, ##notification when file has been IDFileLoaded = 8, #notification when file has been
##loaded (headers read..) #loaded (headers read..)
IDClientMessage = 16, ##[ IDClientMessage = 16, #[
triggered by script-message input command, it uses first argument triggered by script-message input command, it uses first argument
of command as clientName (see getclientName()). to dispatch mesage. of command as clientName (see getclientName()). to dispatch mesage.
passes all arguments from second arguemnt as strings. passes all arguments from second arguemnt as strings.
(see Event, ecentClientMessage) (see Event, ecentClientMessage)
]## ]#
IDVideoReConfig = 17, ##[ IDVideoReConfig = 17, #[
happens when video gets changed. resolution, pixel format or video happens when video gets changed. resolution, pixel format or video
filter changes. Event is sent after video filters & VO are filter changes. Event is sent after video filters & VO are
reconfigured. if using mpv window, app should listen this Event reconfigured. if using mpv window, app should listen this Event
so to resize window if needed. this can happen sporadically and so to resize window if needed. this can happen sporadically and
should manually check if video parameters changed should manually check if video parameters changed
]## ]#
IDAudioReConfig = 18, ##similar as EventIDVideoReConfig IDAudioReConfig = 18, #similar as EventIDVideoReConfig
IDSeek = 20, ##happens when a seek was initiated IDSeek = 20, #[
##and will resume using EventIDPlaybackRestart when seek is finished happens when a seek was initiated and will resume
using EventIDPlaybackRestart when seek is finished
]#
IDPlayBackRestart = 21, ##[ IDPlayBackRestart = 21, #[
there was discontinuity like a seek, so playback was reinitialized there was discontinuity like a seek, so playback was reinitialized
(happens after seeking, chapter switches). mainly allows client (happens after seeking, chapter switches). mainly allows client
to detect if seek is finished to detect if seek is finished
]## ]#
IDEventPropertyChange = 22, ##Event sent due to observeProperty().m IDEventPropertyChange = 22, #Event sent due to observeProperty().m
##see Event,EventProperty #see Event,EventProperty
IDQueueOverFlow = 24, ##[ IDQueueOverFlow = 24, #[
happens if internal Handle ringBuffer OverFlows, then atleast 1 happens if internal Handle ringBuffer OverFlows, then atleast 1
Event has to be dropped, this can happen if client doesnt read Event has to be dropped, this can happen if client doesnt read
Event queue quickly with waitEvent() or client makes very large Event queue quickly with waitEvent() or client makes very large
number of asynchronous calls at once. every delivery will continue number of asynchronous calls at once. every delivery will continue
normally once Event gets returned, this forces client to empty queue normally once Event gets returned, this forces client to empty queue
]## ]#
IDEventHook = 25 ##[ IDEventHook = 25 #[
triggered if hook Handler was registered with hookAdd() triggered if hook Handler was registered with hookAdd()
and hook is invoked. this must be manually Handled and continue and hook is invoked. this must be manually Handled and continue
hook with hookContinue() (see Event, EventHook) hook with hookContinue() (see Event, EventHook)
@ -259,12 +261,12 @@ type #enums
llDebug = 60, ##more noisy verbose info llDebug = 60, ##more noisy verbose info
llTrace = 70 ##extermely verbose llTrace = 70 ##extermely verbose
{.push bycopy.}
type
#non-enum type objects #non-enum type objects
Handle* = distinct pointer ##(private) basic type, used by api to Handle* = distinct pointer ##(private) basic type, used by api to
##infer the context ##infer the context
{.push bycopy.}
type
ClientUnionType* {.union.} = object ClientUnionType* {.union.} = object
str*: cstring str*: cstring
flag*, int*: cint flag*, int*: cint
@ -329,7 +331,6 @@ using
proc abortAsyncCmd*(ctx; replyUserData) proc abortAsyncCmd*(ctx; replyUserData)
{.importc: "mpv_abort_async_command".} {.importc: "mpv_abort_async_command".}
#{.push discardable.}
proc cmd*(ctx; argsArr): cint proc cmd*(ctx; argsArr): cint
{.importc: "mpv_command".} {.importc: "mpv_command".}
@ -348,16 +349,15 @@ proc cmdRet*(ctx; argsArr; result): cint
proc cmdString*(ctx; argsStr): cint proc cmdString*(ctx; argsStr): cint
{.importc: "mpv_command_string".} {.importc: "mpv_command_string".}
#{.pop.}
proc create*: ptr Handle proc create*: ptr Handle
{.importc: "mpv_create".} ##[ {.importc: "mpv_create".} #[
create and return a Handle used to control the instance create and return a Handle used to control the instance
instance is in preinitialized state. and needs more initialisation instance is in preinitialized state. and needs more initialisation
for use with other procs. (see errUnitialised, libmpv/examples/simple.c) for use with other procs. (see errUnitialised, libmpv/examples/simple.c)
this gives more control over configuration. (see more..) this gives more control over configuration. (see more..)
NO concurrent accesses on uninitialised Handle. NO concurrent accesses on uninitialised Handle.
returns nil when out of memory returns nil when out of memory
]## ]#
proc createClient*(ctx; name): ptr Handle proc createClient*(ctx; name): ptr Handle
{.importc: "mpv_create_client".} {.importc: "mpv_create_client".}
@ -367,30 +367,30 @@ proc createWeakClient*(ctx; name): ptr Handle
proc destroy*(ctx) proc destroy*(ctx)
{.importc: "mpv_destroy".} {.importc: "mpv_destroy".}
##finish the Handle, ctx will be deallocated. #finish the Handle, ctx will be deallocated.
proc errorString*(error): cstring proc errorString*(error): cstring
{.importc: "mpv_error_string".} ##[ {.importc: "mpv_error_string".} #[
return string describing error, if unknown: returns "unknown string", return string describing error, if unknown: returns "unknown string",
isStaticConst, (see error: enum) isStaticConst, (see error: enum)
]## ]#
proc eventName*(Event: EventID): cstring proc eventName*(Event: EventID): cstring
{.importc: "mpv_event_name".} {.importc: "mpv_event_name".}
proc free*(data) proc free*(data)
{.importc: "mpv_free".} ##[ {.importc: "mpv_free".} #[
general proc to dealloc() returned by api procs. !!explicitly used!!, general proc to dealloc() returned by api procs. !!explicitly used!!,
if called on not mpv's memory: undefined behavoiur happens if called on not mpv's memory: undefined behavoiur happens
valid pointer returned or nil valid pointer returned or nil
]## ]#
proc freeNodeContents*(node) proc freeNodeContents*(node)
{.importc: "mpv_free_node_contents".} {.importc: "mpv_free_node_contents".}
proc getClientApiVersion*: culong proc getClientApiVersion*: culong
{.importc: "mpv_client_api_version".} {.importc: "mpv_client_api_version".}
##return api version of libmpv #return api version of libmpv
proc getClientName*(ctx): cstring proc getClientName*(ctx): cstring
{.importc: "mpv_client_name".} {.importc: "mpv_client_name".}
@ -423,8 +423,6 @@ proc initialize*(ctx): cint
very important proc for usage if used create() to preinit very important proc for usage if used create() to preinit
]## ]##
#{.push discardable.}
proc loadConfigFile*(ctx; filename: cstring): cint proc loadConfigFile*(ctx; filename: cstring): cint
{.importc: "mpv_load_config_file".} {.importc: "mpv_load_config_file".}
@ -461,7 +459,6 @@ proc terminateDestroy*(ctx)
proc unobserveProperty*(ctx; registeredReplyUserData: uint64): cint proc unobserveProperty*(ctx; registeredReplyUserData: uint64): cint
{.importc: "mpv_unobserve_property".} {.importc: "mpv_unobserve_property".}
#{.pop.}
proc waitAsyncRequests*(ctx) proc waitAsyncRequests*(ctx)
{.importc: "mpv_wait_async_requests".} {.importc: "mpv_wait_async_requests".}

View file

@ -6,7 +6,7 @@ import terminal
when not defined windows: import unicode, macros, os when not defined windows: import unicode, macros, os
type type
Key* {.pure.} = enum ## Supported single key presses and key combinations Key* {.pure.} = enum #Supported single key presses and key combinations
None = (-1, "None"), None = (-1, "None"),
# Special ASCII characters # Special ASCII characters
@ -239,7 +239,7 @@ when defined(windows):
var gOldConsoleModeInput: DWORD var gOldConsoleModeInput: DWORD
var gOldConsoleMode: DWORD var gOldConsoleMode: DWORD
proc consoleInit() = proc consoleInit =
discard getConsoleMode(getStdHandle(STD_INPUT_HANDLE), gOldConsoleModeInput.addr) discard getConsoleMode(getStdHandle(STD_INPUT_HANDLE), gOldConsoleModeInput.addr)
if gFullScreen: if gFullScreen:
if getConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode.addr) != 0: if getConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode.addr) != 0:
@ -248,7 +248,7 @@ when defined(windows):
else: else:
discard getConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode.addr) discard getConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode.addr)
proc consoleDeinit() = proc consoleDeinit =
if gOldConsoleMode != 0: if gOldConsoleMode != 0:
discard setConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode) discard setConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), gOldConsoleMode)
@ -341,7 +341,7 @@ else: # OS X & Linux
consoleInit() consoleInit()
hideCursor() hideCursor()
proc installSignalHandlers() = proc installSignalHandlers =
signal(SIGCONT, SIGCONT_handler) signal(SIGCONT, SIGCONT_handler)
signal(SIGTSTP, SIGTSTP_handler) signal(SIGTSTP, SIGTSTP_handler)
@ -376,11 +376,11 @@ else: # OS X & Linux
discard select(STDIN_FILENO+1, fds.addr, nil, nil, tv.addr) discard select(STDIN_FILENO+1, fds.addr, nil, nil, tv.addr)
return FD_ISSET(STDIN_FILENO, fds) return FD_ISSET(STDIN_FILENO, fds)
proc consoleInit() = proc consoleInit =
nonblock(true) nonblock(true)
installSignalHandlers() installSignalHandlers()
proc consoleDeinit() = proc consoleDeinit =
nonblock(false) nonblock(false)
# surely a 100 char buffer is more than enough; the longest # surely a 100 char buffer is more than enough; the longest
@ -437,7 +437,7 @@ when defined(posix):
XtermColor = "xterm-color" XtermColor = "xterm-color"
Xterm256Color = "xterm-256color" Xterm256Color = "xterm-256color"
proc enterFullScreen() = proc enterFullScreen =
## Enters full-screen mode (clears the terminal). ## Enters full-screen mode (clears the terminal).
when defined(posix): when defined(posix):
case getEnv("TERM"): case getEnv("TERM"):
@ -450,7 +450,7 @@ proc enterFullScreen() =
else: else:
eraseScreen() eraseScreen()
proc exitFullScreen() = proc exitFullScreen =
## Exits full-screen mode (restores the previous contents of the terminal). ## Exits full-screen mode (restores the previous contents of the terminal).
when defined(posix): when defined(posix):
case getEnv("TERM"): case getEnv("TERM"):
@ -474,11 +474,11 @@ proc illwillInit*(fullScreen = true) =
gIllwillInitialised = true gIllwillInitialised = true
resetAttributes() resetAttributes()
proc checkInit() = proc checkInit =
if not gIllwillInitialised: if not gIllwillInitialised:
raise newException(IllwillError, "Illwill not initialised") raise newException(IllwillError, "Illwill not initialised")
proc illwillDeinit*() = proc illwillDeinit* =
checkInit() checkInit()
if gFullScreen: exitFullScreen() if gFullScreen: exitFullScreen()
consoleDeinit() consoleDeinit()
@ -486,7 +486,7 @@ proc illwillDeinit*() =
resetAttributes() resetAttributes()
showCursor() showCursor()
proc getKey*(): Key = proc getKey*: Key =
## Reads the next keystroke in a non-blocking manner. If there are no ## Reads the next keystroke in a non-blocking manner. If there are no
## keypress events in the buffer, `Key.None` is returned. ## keypress events in the buffer, `Key.None` is returned.
## If the module is not intialised, `IllwillError` is raised. ## If the module is not intialised, `IllwillError` is raised.

View file

@ -1,4 +1,4 @@
import strutils, #[json,]# httpclient, net, ui import strutils, httpclient, net, ui
proc cleanLink(str: string): string = proc cleanLink(str: string): string =
var link = str var link = str

View file

@ -9,10 +9,15 @@ template nowStreaming =
say "Now Streaming: " & currentSong, fgGreen say "Now Streaming: " & currentSong, fgGreen
cursorUp() cursorUp()
template endThisCall(str: string) = template endThisCall(str: string, ret = false) =
warn str warn str
terminateDestroy ctx when ret: return
break else:
terminateDestroy ctx
break
proc volumeNotify(volumeUp: bool, val: int) =
inv((if volumeUp: "Volume+: " else: "Volume-: " ) & $val)
proc notifyplayerState(isPaused, isMuted: bool) = proc notifyplayerState(isPaused, isMuted: bool) =
cursorDown() cursorDown()
@ -20,17 +25,14 @@ proc notifyplayerState(isPaused, isMuted: bool) =
if not isPaused: if not isPaused:
if isMuted: warn "Muted" if isMuted: warn "Muted"
else: say "Playing", fgGreen else: say "Playing", fgGreen
else: else: warn if isMuted: "paused and muted"
if isMuted: warn "paused and muted" else: "Paused"
else: warn "Paused"
proc call(sub: string; sect = ""; stat, link: string) = proc call(sub: string; sect = ""; stat, link: string) =
if link == "": if link == "":
warn "link empty" endThisCall "link empty", ret = true
return
elif link.contains " ": elif link.contains " ":
warn "link dont exist or is invalid" endThisCall "link dont exist or is invalid", ret = true
return
clear() clear()
if sect == "": say (("PNimRP > " & sub) & (" > " & stat)) if sect == "": say (("PNimRP > " & sub) & (" > " & stat))
@ -39,20 +41,17 @@ proc call(sub: string; sect = ""; stat, link: string) =
sayTermDraw12() sayTermDraw12()
if not doesLinkWork link: if not doesLinkWork link:
warn "no link work" endThisCall "no link work", ret = true
return
var ctx = create() var ctx = create()
ctx.init link ctx.init link
var var
event = ctx.waitEvent event = ctx.waitEvent
isPaused = false isPaused, isMuted, isSetToObserve = false
isMuted = false
isSetToObserve = false
currentSong: string currentSong: string
counter: uint8 counter: uint8
try: illwillinit false try: illwillinit false
except IllWillError: discard except: discard
cursorDown() cursorDown()
say "Playing", fgGreen say "Playing", fgGreen
@ -78,51 +77,32 @@ proc call(sub: string; sect = ""; stat, link: string) =
counter = 0 counter = 0
counter += 1 counter += 1
case getKeyWithTimeout(25): #highcpuUsage; use timeout case getKeyWithTimeout(25): #highcpuUsage; use timeout
of Key.P: of Key.P:
if isPaused: if isPaused:
isPaused = false isPaused = false
ctx.pause false ctx.pause false
notifyPlayerState(isPaused, isMuted)
else: else:
ctx.pause true ctx.pause true
isPaused = true isPaused = true
notifyPlayerState(isPaused, isMuted) notifyPlayerState(isPaused, isMuted)
of Key.M: of Key.M:
if isMuted: if isMuted:
ctx.mute false ctx.mute false
isMuted = false isMuted = false
notifyPlayerState(isPaused, isMuted)
else: else:
ctx.mute true ctx.mute true
isMuted = true isMuted = true
notifyPlayerState(isPaused, isMuted) notifyPlayerState(isPaused, isMuted)
of Key.Slash, Key.Plus: of Key.Slash, Key.Plus:
let volumeIncreased = ctx.volume true volumeNotify true, ctx.volume true
cursorDown()
cursorDown()
warn "Volume+: " & $volumeIncreased
cursorUp()
eraseLine()
cursorUp()
cursorUp()
of Key.Asterisk, Key.Minus: of Key.Asterisk, Key.Minus:
let volumeDecreased = ctx.volume false volumeNotify true, ctx.volume false
cursorDown()
cursorDown()
warn "Volume-: " & $volumeDecreased
cursorUp()
eraseLine()
cursorUp()
cursorUp()
of Key.R: of Key.R:
if not isPaused: terminateDestroy ctx if not isPaused: terminateDestroy ctx
@ -197,7 +177,7 @@ proc menu(sub, file: string; sect = "") =
while true: while true:
try: try:
case getch(): case getch():
of '1': call sub, sect, n[0], l[0]; break of '1': call sub, sect, n[1], l[1]; break
of '2': call sub, sect, n[1], l[1]; break of '2': call sub, sect, n[1], l[1]; break
of '3': call sub, sect, n[2], l[2]; break of '3': call sub, sect, n[2], l[2]; break
of '4': call sub, sect, n[3], l[3]; break of '4': call sub, sect, n[3], l[3]; break
@ -214,7 +194,6 @@ proc menu(sub, file: string; sect = "") =
of 'F', 'f': call sub, sect, n[14], l[14]; break of 'F', 'f': call sub, sect, n[14], l[14]; break
of 'R', 'r': of 'R', 'r':
returnBack = true returnBack = true
#writeStackTrace()
break break
of 'Q', 'q': exitEcho() of 'Q', 'q': exitEcho()
else: inv() else: inv()
@ -234,7 +213,6 @@ proc drawMainMenu*(dir = getAppDir() / "assets") =
sayIter names, ret = if dir != getAppDir() / "assets": true else: false sayIter names, ret = if dir != getAppDir() / "assets": true else: false
try: try:
while true: while true:
#var getch = getch()
case getch(): case getch():
of '1': menu names[0], files[0]; break of '1': menu names[0], files[0]; break
of '2': menu names[1], files[1]; break of '2': menu names[1], files[1]; break
@ -263,13 +241,8 @@ proc drawMainMenu*(dir = getAppDir() / "assets") =
break break
else: inv() else: inv()
of 'q', 'Q': exitEcho() of 'q', 'Q': exitEcho()
else: else: inv()
#echo getch except IndexDefect: inv()
inv()
except IndexDefect:
#warn "indexdefect"
inv()
if returnBack: break if returnBack: break
export hideCursor, error export hideCursor, error

View file

@ -2,6 +2,7 @@ import client
using using
ctx: ptr Handle ctx: ptr Handle
val: bool
proc init*(ctx; parm: string) = proc init*(ctx; parm: string) =
let file = allocCStringArray ["loadfile", parm] #couldbe file,link,parm let file = allocCStringArray ["loadfile", parm] #couldbe file,link,parm
@ -10,19 +11,19 @@ proc init*(ctx; parm: string) =
cE initialize ctx cE initialize ctx
cE ctx.cmd file cE ctx.cmd file
proc pause*(ctx; a: bool) = proc pause*(ctx; val) =
var val: cint = if a: 1 else: 0 var val = cint val
cE ctx.setProperty("pause", fmtFlag, addr val) cE ctx.setProperty("pause", fmtFlag, addr val)
proc mute*(ctx; a: bool) = proc mute*(ctx; val) =
var val: cint = if a: 1 else: 0 var val = cint val
cE ctx.setProperty("mute", fmtFlag, addr val) cE ctx.setProperty("mute", fmtFlag, addr val)
proc volume*(ctx; a: bool): int = proc volume*(ctx; val): int =
var volumeChanged: int var volumeChanged: int
cE ctx.getProperty("volume", fmtInt64, cE ctx.getProperty("volume", fmtInt64,
addr volumeChanged) addr volumeChanged)
if a: volumeChanged += 5 else: volumeChanged -= 5 if val: volumeChanged += 5 else: volumeChanged -= 5
cE ctx.setProperty("volume", fmtInt64, addr volumeChanged) cE ctx.setProperty("volume", fmtInt64, addr volumeChanged)
volumeChanged volumeChanged

View file

@ -2,18 +2,21 @@ import
terminal, client, random, terminal, client, random,
json, strutils, os json, strutils, os
using
str: string
proc clear* = proc clear* =
eraseScreen() eraseScreen()
setCursorPos 0, 0 setCursorPos 0, 0
proc error*(str: string) = proc error*(str) =
styledEcho fgRed, "Error: ", str styledEcho fgRed, "Error: ", str
quit QuitFailure quit QuitFailure
proc parseJArray*(file: string): seq[string] = proc parseJArray*(str): seq[string] =
try: try:
result = to( result = to(
parseJson(readFile(file)){"pnimrp"}, parseJson(readFile(str)){"pnimrp"},
seq[string] seq[string]
) )
except IOError: error "base assets dont exist?" except IOError: error "base assets dont exist?"
@ -55,16 +58,16 @@ proc exitEcho* =
quit QuitSuccess quit QuitSuccess
proc say*(txt: string; color = fgYellow; x = 5; echo = true) = proc say*(str; color = fgYellow; x = 5; echo = true) =
if color == fgBlue: setCursorXPos x if color == fgBlue: setCursorXPos x
if color == fgGreen: if color == fgGreen:
setCursorXPos x setCursorXPos x
if echo: styledEcho fgGreen, txt if echo: styledEcho fgGreen, str
else: stdout.styledWrite fgGreen, txt else: stdout.styledWrite fgGreen, str
else: styledEcho color, txt #fgBlue would get true here else: styledEcho color, str #fgBlue would get true here
proc sayIter(txt: string) = proc sayIter(str) =
for f in splitLines txt: for f in splitLines str:
say f, fgBlue say f, fgBlue
proc sayIter*(txt: seq[string]; ret = true) = proc sayIter*(txt: seq[string]; ret = true) =
@ -86,28 +89,25 @@ proc sayIter*(txt: seq[string]; ret = true) =
if ret: say "R Return", fgBlue if ret: say "R Return", fgBlue
say "Q Quit", fgBlue say "Q Quit", fgBlue
proc warn*(txt: string; x = 4; colour = fgRed) = proc warn*(str; x = 4; colour = fgRed) =
if x != -1: setCursorXPos x if x != -1: setCursorXPos x
styledEcho colour, txt styledEcho colour, str
#if echo == false: stdout.styledWrite fgRed,txt
#default Args dosent seem to be working?
sleep 750 sleep 750
proc inv* = proc inv*(str = "INVALID CHOICE") =
cursorDown() cursorDown()
cursorDown() cursorDown()
warn "INVALID CHOICE" warn str
cursorUp() cursorUp()
eraseLine() eraseLine()
cursorUp() cursorUp()
cursorUp() cursorUp()
proc sayTermDraw8* =
template sayTermDraw8*() =
say "Poor Mans Radio Player in Nim-lang " & say "Poor Mans Radio Player in Nim-lang " &
'-'.repeat int terminalWidth() / 8 '-'.repeat int terminalWidth() / 8
proc sayTermDraw12*() = proc sayTermDraw12* =
say('-'.repeat((terminalWidth()/8).int) & say('-'.repeat((terminalWidth()/8).int) &
'>'.repeat int terminalWidth() / 12, fgGreen, x = 2) '>'.repeat int terminalWidth() / 12, fgGreen, x = 2)