diff --git a/nimble.lock b/nimble.lock index a422fb6..f0a214e 100644 --- a/nimble.lock +++ b/nimble.lock @@ -11,6 +11,16 @@ "sha1": "b338433f9a7a1b788b7583674c2b14096ced29ee" } }, + "cligen": { + "version": "1.7.0", + "vcsRevision": "4193f802796f15559c81c6dd56724d6f20345917", + "url": "https://github.com/c-blake/cligen.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "300bd7fdb6e48d2d98e34ed0661206b50331e99c" + } + }, "illwill": { "version": "0.4.1", "vcsRevision": "99a120f7f69868b94f5d35ce7e21dd12535de70c", @@ -21,24 +31,14 @@ "sha1": "9c58351502f89a16caf031cbd1992ad3fdfd3c67" } }, - "usu": { - "version": "0.1.0", - "vcsRevision": "25574d165bb7f60900b36590bc49f3d90e47cea4", - "url": "https://github.com/usu-dev/usu-nim", + "yaml": { + "version": "2.1.1", + "vcsRevision": "48a90e36e82bd97457dae87e86efe423dcd3bb40", + "url": "https://github.com/flyx/NimYAML", "downloadMethod": "git", "dependencies": [], "checksums": { - "sha1": "61a8c13946e3eea9dbe04a6141ed93811563026c" - } - }, - "cligen": { - "version": "1.7.0", - "vcsRevision": "4193f802796f15559c81c6dd56724d6f20345917", - "url": "https://github.com/c-blake/cligen.git", - "downloadMethod": "git", - "dependencies": [], - "checksums": { - "sha1": "300bd7fdb6e48d2d98e34ed0661206b50331e99c" + "sha1": "302727fcd74c79d0697a4e909d26455d61a5b979" } } }, diff --git a/src/config.nim b/src/config.nim index c4984fd..2d7dac8 100644 --- a/src/config.nim +++ b/src/config.nim @@ -1,5 +1,6 @@ -import std/[os, tables, strutils] -import usu +import std/[os, streams, strformat, strutils] +import yaml +import term type TsmConfig* = object @@ -9,19 +10,16 @@ type Session = object name*, dir*: string -# TODO: update when the API for usu is complete proc loadConfigFile(): TsmConfig = - let configPath = getEnv("TSM_CONFIG", getConfigDir() / "tsm" / "config.usu") - if fileExists configPath: - let usuNode = parseUsu(readFile configPath) - let topFields = usuNode.fields - if "dirs" in topFields: - for dir in usuNode.fields["dirs"].elems: - result.dirs.add dir.value - if "sessions" in topFields: - for session in usuNode.fields["sessions"].elems: - result.sessions.add Session(name: session.fields["name"].value, - dir: session.fields["dir"].value) + let configPath = getEnv("TSM_CONFIG", getConfigDir() / "tsm" / "config.yml") + try: + var s = newFileStream(configPath) + load(s, result) + s.close() + except: + termError fmt( + "failed to load config file\npath: {configPath}\nmessage: {getCurrentExceptionMsg()}" + ) proc loadTsmConfig*(): TsmConfig = result = loadConfigFile() @@ -31,4 +29,3 @@ proc loadTsmConfig*(): TsmConfig = when isMainModule: echo loadConfigFile() - diff --git a/src/project.nim b/src/project.nim index 26b6434..3c498e6 100644 --- a/src/project.nim +++ b/src/project.nim @@ -12,8 +12,12 @@ type proc pathToName(path: string): string = splitPath(path)[1].replace(".", "_") -proc newProject(path: string, open: bool, name = "", - named: bool = false): Project = +proc newProject( + path: string, + open: bool, + name = "", + named: bool = false +): Project = result.location = path result.name = if name != "": name @@ -78,19 +82,23 @@ proc findProjects*(open: bool = false): seq[Project] = for session in tsmConfig.sessions: if session.name notin sessions: - result.add newProject(path = session.dir, open = false, - name = session.name, named = true) + result.add newProject( + path = session.dir, + open = false, + name = session.name, + named = true + ) if open: result = result.filterIt(it.open) - # favor open projects then by update time + # default order + # open -> configured -> mod time result.sort do (x, y: Project) -> int: result = cmp(y.open, x.open) if result == 0: result = cmp(y.updated, x.updated) - if sessions.len > 0: result = sessions.toSeq().mapIt(newUnknownProject(it)) & result diff --git a/src/selector.nim b/src/selector.nim index d8d2964..e486979 100644 --- a/src/selector.nim +++ b/src/selector.nim @@ -1,9 +1,6 @@ import std/[enumerate, os, strformat, strutils, terminal] - from illwill import illwillDeinit, illwillInit, getKey, Key -import term - -import project +import term, project func toStr(k: Key): string = $chr(ord(k)) @@ -75,8 +72,8 @@ proc scrollUp() = dec state.projectIdx proc scrollDown() = - if (state.projects.len - state.projectIdx) > (state.buffer.height - - state.buffer.inputPad): + if (state.projects.len - state.projectIdx) > + (state.buffer.height - state.buffer.inputPad): inc state.projectIdx proc up() = @@ -143,7 +140,7 @@ proc addProject(b: var Buffer, project: Project, selected: bool) = var displayName = fmt"[red]{input}[/]" if input.len < name.len: # bbansi missing add(string, bbstring) interface - displayName = displayName & fmt"[{project.highlight}]{name[input.len..^1]}[/{project.highlight}]" + displayName &= fmt"[{project.highlight}]{name[input.len..^1]}[/{project.highlight}]" b.addLine(cur & $displayName.bb) else: b.addLine(cur & $name.bb(project.highlight)) @@ -152,6 +149,7 @@ proc addProjectCount(b: var Buffer) = let maxNumProjects = state.buffer.height - state.buffer.inputPad numProjects = state.projects.len + # TODO: use variables here for readability b.addLine $(fmt"[[{state.projectIdx+1}-{state.projectIdx + min(maxNumProjects, numProjects)}/{numProjects}]".bb("faint")) proc addProjects(b: var Buffer) = @@ -201,9 +199,9 @@ proc exitProc() {.noconv.} = state.buffer.clear showCursor() -proc selectProject*(open: bool = false): Project = +proc selectProject*(projects: seq[Project]): Project = - state.projects = findProjects(open) + state.projects = projects illwillInit(fullscreen = false) setControlCHook(quitProc) hideCursor() @@ -217,10 +215,8 @@ proc selectProject*(open: bool = false): Project = of Key.Enter: exitProc() return getProject() - of Key.Up: - up() - of Key.Down: - down() + of Key.Up: up() + of Key.Down: down() of Key.CtrlA..Key.CtrlL, Key.CtrlN..Key.CtrlZ, Key.CtrlRightBracket, Key.CtrlBackslash, Key.Right..Key.F12: state.lastKey = key @@ -240,6 +236,7 @@ proc selectProject*(open: bool = false): Project = when isMainModule: - let selected = selectProject() + projects = findProjects(open) + let selected = selectProject(projects) echo "selected project -> " & $selected.name diff --git a/src/tsm.nim b/src/tsm.nim index 21a7e3e..22b065a 100644 --- a/src/tsm.nim +++ b/src/tsm.nim @@ -5,11 +5,12 @@ import selector, project, tmuxutils # TODO: add option to only opened configured sessions proc tsm(open: bool = false) = let - project = selectProject(open) + projects = findProjects(open) + project = selectProject projects selected = project.name if selected notin tmux.sessions: - tmux.new project.name, project.location + tmux.new(project.name, project.location) else: tmux.attach project.name @@ -19,10 +20,22 @@ when isMainModule: clCfg.version = vsn if clCfg.helpAttr.len == 0: - clCfg.helpAttr = {"cmd": "\e[1;36m", "clDescrip": "", "clDflVal": "\e[33m", - "clOptKeys": "\e[32m", "clValType": "\e[31m", "args": "\e[3m"}.toTable - clCfg.helpAttrOff = {"cmd": "\e[m", "clDescrip": "\e[m", "clDflVal": "\e[m", - "clOptKeys": "\e[m", "clValType": "\e[m", "args": "\e[m"}.toTable + clCfg.helpAttr = { + "cmd" : "\e[1;36m", + "clDescrip": "", + "clDflVal" : "\e[33m", + "clOptKeys": "\e[32m", + "clValType": "\e[31m", + "args" : "\e[3m" + }.toTable + clCfg.helpAttrOff = { + "cmd" : "\e[m", + "clDescrip": "\e[m", + "clDflVal" : "\e[m", + "clOptKeys": "\e[m", + "clValType": "\e[m", + "args" : "\e[m" + }.toTable dispatch( tsm, diff --git a/tsm.nimble b/tsm.nimble index e77e7d1..a4fe0ff 100644 --- a/tsm.nimble +++ b/tsm.nimble @@ -14,5 +14,5 @@ requires "nim >= 2.0.0" requires "illwill >= 0.4.1" requires "cligen" requires "https://github.com/daylinmorgan/bbansi >= 0.1.1" -requires "https://github.com/usu-dev/usu-nim" +requires "yaml"