diff --git a/README.md b/README.md index 154d29b..258b2b2 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,9 @@ BASICS ====== Getting a `procs` config going *should* be as easy as (on Debian): ``` -apt install nim #(https://nim-lang.org/ has other options) -nimble install procs -$HOME/.nimble/bin/procs #gives a help message -(cd $HOME/.nimble/bin; ln -s procs pd) -# Here is one way to get a fancier config going: -git clone https://github.com/c-blake/procs -cp -r procs/configs/cb0 $HOME/.config/procs +apt install nim # See also https://nim-lang.org/ +nimble install procs # Also installs $HOME/etc/procs conf +$HOME/.nimble/bin/procs # gives a help message ``` The Nim experience can sometimes have fairly rough-hewn edges, though. So far, though, something like the above has worked for me on Gentoo Linux, Debian, and diff --git a/procs.nim b/procs.nim index 99d3287..7ccb093 100644 --- a/procs.nim +++ b/procs.nim @@ -1913,6 +1913,8 @@ proc scrollSys*(cf: var ScCf) = when isMainModule: ### DRIVE COMMAND-LINE INTERFACE import cligen, cligen/cfUt + const procsEtc {.strdefine.} = "" # Allow -d:procsEtc= override of auto etc/ + let argv {.importc: "cmdLine".}: cstringArray #NOTE MUST be in main module proc mergeParams(cmdNames: seq[string], cmdLine=os.commandLineParams()): seq[string] = @@ -1926,10 +1928,15 @@ when isMainModule: ### DRIVE COMMAND-LINE INTERFACE elif bn == "pw": result.add [ "find", "-await" ] return result & cmdLine let underJoin = strutils.toUpperAscii(cmdNames.join("_")) - var cfPath = os.getEnv(underJoin & "_CONFIG") #See if cfg file redirect + var cfPath = getEnv(cmdNames[0].toUpperAscii&"_CONFIG") #cf redirect,ifAny if cfPath.len == 0: #..else use getConfigDir cfPath = os.getConfigDir() / cmdNames[0] / "config" #See if dir w/cfg - if not fileExists(cfPath): cfPath = cfPath[0..^8] #..else use file + if not fileExists(cfPath): + cfPath = cfPath[0..^8] #..else try file + if not dirExists(cfPath): #..else fall back + cfPath = if procsEtc.len > 0: procsEtc #..to CT default + else: argv.findAssociated("etc/procs") #..or assoc dir| + if fileExists(cfPath / "config"): cfPath = cfPath / "config" #..file result.add cfToCL(cfPath, if cmdNames.len > 1: cmdNames[1] else: "", quiet=true, noRaise=true) result.add envToCL(underJoin) #Finally add $PROCS_DISPLAY $PROCS_FIND.. diff --git a/procs.nimble b/procs.nimble index 2622cf6..01e11e1 100644 --- a/procs.nimble +++ b/procs.nimble @@ -1,10 +1,69 @@ # Package -version = "0.5.8" +version = "0.6.0" author = "Charles Blake" -description = "Unix process&system query&formatting library&multi-command CLI in Nim" +description = "Unix process&system query&format lib&multi-command CLI in Nim" license = "MIT/ISC" -bin = @[ "procs" ] +bin = @["procs"] +installDirs = @["configs"] # Dependencies requires "nim >= 1.6.0", "cligen >= 1.6.13" skipDirs = @["configs"] + +import os, strutils #XXX from os import parentDir, getEnv, dirExists fails +proc getNimbleDir: string = + result = getEnv("NIMBLE_DIR", getEnv("nimbleDir", "")) + if result.len > 0: return + if (let (installDir, ex) = gorgeEx("nimble path procs"); ex == 0): + result = installDir.strip.parentDir.parentDir # Hopefully .ini nimbleDir + +# Next bits populate an `etc/procs/` directory used by `procs` If a user gives +# neither config nor CLI options. `procs` finds this from /proc/PID | $0 which +# may not work in all OS/shells (then users just do not get a fallback config). +proc getEtcDir: string = + result = getEnv("ETC_DIR", getEnv("ETCDIR", getEnv("etcDir", ""))) + if result.len > 0: return + let nD = getNimbleDir() + if nD.len == 0: return + let etc = nD & "/../etc" # $(HOME|/opt)/etc + result = if etc.dirExists: etc & "/procs" else: nD & "/../etc/procs" + +task installConf, "install the default config in \".../etc/procs/\"": + let cD = getEtcDir() # .../etc/procs + if cD.dirExists or cD.fileExists: + echo "\n", cD, " ALREADY EXISTS\nRename/Remove/uninstallConf & try again" + elif cD.len > 0: + exec "umask 022 && mkdir -p " & cD & " && install -m644 configs/cb0/* " & cD + else: echo """ERROR: Could not infer ETC_DIR; +Try doing `nimble install procs` first +or try `ETC_DIR=/x/y/etc nimble installConf`"""; return + +task uninstallConf, "uninstall the default config from \".../etc/procs/\"": + let cD = getEtcDir(); let pD = cD.parentDir # rmdir in case we spammed $HOME + if dirExists(cD): exec "rm -vr " & cD & " && rmdir -v " & pD & ";:" + +task installData, "installConf": installConfTask() +task uninstallData, "uninstallConf": uninstallConfTask() + +# On a barely responsive system "pk X" can be VERY nice cmp to "procs f -ak X", +# especially killing can restore responsiveness, but shell aliases also exist. +task makeLinks, "make symlinks to \".../bin/procs\"": + let nB = getNimbleDir() / "bin" + echo "making symlinks in ", nB + for base in ["pd", "pf", "pk", "pw", "sc"]: + exec "cd " & nB & " && ln -s procs " & base & " || :" + +task unmakeLinks, "unmake symlinks to \".../bin/procs\"": + let nB = getNimbleDir() / "bin" + for base in ["pd", "pf", "pk", "pw", "sc"]: + exec "[ \"$(readlink " & (nB/base) & ")\" = procs ] && rm -fv " & (nB/base) + +# Allow nimble to drive both man & conf installation if it has permission. +proc absent(evs: openArray[string]): bool = # True if *NONE* of evs + result = true + for ev in evs: result = result and not ev.existsEnv #..is set to anything. + +after install: # Evidently, `after uninstall:` is not honored + if ["NIMBLE_MINI","mini"].absent: + if ["NIMBLE_NOLN","noln"].absent: makeLinksTask() + if ["NIMBLE_NOETC","noetc","NIMBLE_NOCONF","noconf"].absent: installConfTask()