aboutsummaryrefslogtreecommitdiff
path: root/main.nim
blob: e93e1446aaaa00386deb18bee6f9d9cdde20fa24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# tickwatch
# Author: Euxane TRAN-GIRARD
# Licence: EUPL-1.2

import std/sugar
import std/math
import std/times
import std/net
import std/posix
import std/paths
import std/strutils
import std/parseopt

import file
import ping
import logger


const
  NAME = "tickwatch"
  VERSION = staticExec("""
    command -v git >/dev/null && git describe --tags --always || echo $VERSION
  """).strip()
  HELP_TEXT =
    staticRead("readme.md")
      .split("```helptext", 1)[1]
      .split("```", 1)[0]
      .strip()

proc registerTerminationHandlers() =
  proc terminationHandler(sig: cint) {.noconv.} = flushAndQuit()
  var action = SigAction(sa_handler: terminationHandler)
  for signal in [SIGTERM, SIGHUP, SIGQUIT, SIGINT]:
    discard sigaction(signal, action)

proc main() =
  var
    scale: Scale = log2
    symbols = UNICODE_SYMBOLS
    (min, max) = (0, 1000)
    probe: (timeout: Duration) -> int

  for optKind, key, val in getopt():
    if optKind notin {cmdLongOption, cmdShortOption}:
      raise newException(ValueError, "Invalid argument: " & key)

    case key:

    of "help", "h":
      echo HELP_TEXT
      quit(0)

    of "version", "v":
      echo NAME & " " & VERSION
      quit(0)

    of "scale":
      case val:
      of "logarithmic", "log", "log2": scale = log2
      of "log10": scale = log10
      of "ln": scale = ln
      of "linear", "lin": scale = (val: float) => val

    of "symbols":
      case val:
      of "unicode", "utf8", "utf-8": symbols = UNICODE_SYMBOLS
      of "numeric", "ascii": symbols = NUMERIC_SYMBOLS

    of "min": min = parseInt(val)
    of "max": max = parseInt(val)

    of "ping":
      let targetIp = resolve(val)
      let mon = initPingMonitor(targetIp, procIdent())
      probe = (timeout: Duration) => mon.ping(timeout).inMilliseconds.int

    of "value":
      let mon = initFileValueMonitor(Path val)
      probe = (timeout: Duration) => mon.readValue()

    of "change":
      let mon = initFileChangeMonitor(Path val)
      probe = (timeout: Duration) => mon.readValue()

  if probe == nil:
    raise newException(ValueError, "Missing monitor argument")

  loop(probe, (val: int) => symbols.indicator(min, max, val, scale))


when not defined(test):
  try:
    registerTerminationHandlers()
    main()
  except CatchableError as err:
    stderr.writeLine err.msg
    quit(1)