Guest User

Untitled

a guest
Aug 17th, 2023
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Nim 4.49 KB | Source Code | 0 0
  1. import std/[os, osproc, strutils, sequtils, times, threadpool, parseopt]
  2. import jsony
  3.  
  4. type
  5.   Color = distinct string
  6. const
  7.   ColorRed = Color("#FB4934")
  8.   ColorYellow = Color("#FABD2F")
  9.   ColorGreen = Color("#B8BB26")
  10.   ColorWhite = Color("#FBF1C7")
  11.  
  12. type
  13.   CommandType = enum
  14.     Custom, Time, CpuUsage, FreeMem
  15.   Command = ref object
  16.     cmdType = Custom
  17.     title, cmd, display, align: string
  18.     color = ColorWhite
  19.     pos = -1
  20.     width: int
  21.     interval: int = 1000
  22.   Status = object
  23.     name, color, full_text, align: string
  24.     min_width: int
  25.  
  26. proc dumplog(s: string) =
  27.   let log = open("/home/archargelod/Fluffy/log/n3status.log", fmAppend)
  28.   log.writeLine(s)
  29.   log.close()
  30.   discard
  31.  
  32. func isColor(s: string): bool =  s.len > 0 and s.len <= 9 and s.startsWith('#')
  33. func `$`(c: Color): string = string(c)
  34.  
  35. proc getOptionCommands(): seq[Command] =
  36.   var position = 0
  37.   var opt = initOptParser("", shortNoVal = {'h'})
  38.  
  39.   while true:
  40.     opt.next()
  41.     if opt.kind == cmdShortOption:
  42.       case opt.key:
  43.         of "p":
  44.           position = parseInt(opt.val)
  45.         of "c":
  46.           result.add Command(cmd: opt.val, pos: position)
  47.           position += 1
  48.         of "h":
  49.           quit("Usage: n3status [-p:POSITION] -c:COMMAND", 0)
  50.         else:
  51.           quit("Usage: n3status [-p:POSITION] -c:COMMAND", 1)
  52.     else: break
  53.  
  54. proc exec_cmd(c: Command) {.raises: [IOError, OSError], thread.} =
  55.   while true:
  56.     try:
  57.       let
  58.         (stdout, _) = execCmdEx(c.cmd)
  59.         parsed = stdout.strip().split('\n', 1)
  60.       c.display = parsed[0]
  61.       if parsed.len > 1 and parsed[1].isColor(): c.color = Color(parsed[1])
  62.     except IOError, OSError:
  63.       dumplog($getTime() & " " & c.cmd & " Failed! MSG: " & getCurrentException().msg)
  64.     sleep(c.interval)
  65.  
  66. proc loopTime(c: Command) {.thread.} =
  67.   const RussianLocale = DateTimeLocale(
  68.     MMM: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг","сен", "окт", "ноя", "дек"],
  69.     ddd: ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"]
  70.   )
  71.  
  72.   while true:
  73.     c.display = now().format("ddd d-MM HH:mm:ss", RussianLocale)
  74.     sleep(c.interval)
  75.  
  76. proc cpuUsageLoop(c: Command) {.thread.} =
  77.   const statFile = "/proc/stat"
  78.   var pastTotal, pastIdle: int
  79.  
  80.   while true:
  81.     let f = open(statFile, fmRead)
  82.     let line = f.readLine()
  83.     f.close()
  84.  
  85.     let
  86.       cpu = line.splitWhitespace()[1..10].mapIt(parseInt(it))
  87.       total = cpu.foldl(a+b)
  88.       idle = cpu[3]
  89.       usage = (1 - (idle - pastIdle) / (total - pastTotal)) * 100
  90.  
  91.     c.color = if usage > 80: ColorRed elif usage > 50: ColorYellow else: ColorGreen
  92.     c.display = usage.formatFloat(ffDecimal, 2) & '%'
  93.     pastTotal = total
  94.     pastIdle = idle
  95.     sleep(c.interval)
  96.  
  97. proc memAvailLoop(c: Command) {.thread.} =
  98.   const statFile = "/proc/meminfo"
  99.   while true:
  100.     let available = readFile(statFile)
  101.                       .splitLines()[2]
  102.                       .splitWhitespace()[1]
  103.                       .parseInt() / 1_048_576
  104.     c.color = if available < 0.5: ColorRed elif available < 1.5: ColorYellow else: ColorGreen
  105.     c.display = available.formatFloat(ffDecimal, 1) & 'G'
  106.     sleep(c.interval)
  107.  
  108. proc echoStatusLoop(commands: var seq[Command], interval: int) =
  109.   echo {"version": 1}.toJson
  110.   echo "["
  111.   while true:
  112.     var jList: seq[string]
  113.  
  114.     for c in commands:
  115.       let status = Status(
  116.         name: c.title,
  117.         color: $c.color,
  118.         min_width: c.width,
  119.         align: c.align,
  120.         full_text: c.title & c.display,
  121.       )
  122.       jList.insert(status.toJson, if c.pos >= 0: c.pos else: jList.len)
  123.  
  124.     echo "[", jList.join(","), "],"
  125.     sleep(interval)
  126.  
  127. when isMainModule:
  128.   var commands = @[
  129.     Command(cmd: "get_window.sh", interval: 1000),
  130.     Command(title: "#", cmd: "get_space.sh /",     width: 20, interval: 10000),
  131.     Command(title: "~", cmd: "get_space.sh /home", width: 20, interval: 10000),
  132.     Command(cmd: "get_wifi.sh", interval: 3000),
  133.     Command(title: "Ram:", cmdType: FreeMem, interval: 3000),
  134.     Command(title: "Cpu:", cmdType: CpuUsage, interval: 3000),
  135.     Command(cmdType: Time),
  136.   ]
  137.   commands.add getOptionCommands()
  138.   setMinPoolSize(commands.len)
  139.  
  140.   for c in commands:
  141.     case c.cmdType:
  142.     of Time:
  143.       spawn c.loopTime()
  144.     of CpuUsage:
  145.       spawn c.cpuUsageLoop()
  146.     of FreeMem:
  147.       spawn c.memAvailLoop()
  148.     of Custom:
  149.       if c.cmd.len > 0:
  150.         spawn c.exec_cmd()
  151.  
  152.   echoStatusLoop(commands, 1000)
  153.  
Advertisement
Add Comment
Please, Sign In to add comment