termplot 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +124 -54
- data/Rakefile +27 -14
- data/doc/dash.png +0 -0
- data/doc/demo.png +0 -0
- data/doc/file.png +0 -0
- data/doc/memory.png +0 -0
- data/doc/ping.png +0 -0
- data/doc/sin.png +0 -0
- data/doc/tcp.png +0 -0
- data/examples/sample.rb +17 -0
- data/lib/termplot/character_map.rb +15 -4
- data/lib/termplot/cli.rb +16 -3
- data/lib/termplot/colors.rb +7 -0
- data/lib/termplot/commands.rb +27 -0
- data/lib/termplot/consumers.rb +12 -0
- data/lib/termplot/consumers/base_consumer.rb +132 -0
- data/lib/termplot/consumers/command_consumer.rb +14 -0
- data/lib/termplot/consumers/multi_source_consumer.rb +33 -0
- data/lib/termplot/consumers/single_source_consumer.rb +36 -0
- data/lib/termplot/consumers/stdin_consumer.rb +11 -0
- data/lib/termplot/cursors/buffered_console_cursor.rb +1 -1
- data/lib/termplot/cursors/virtual_cursor.rb +4 -0
- data/lib/termplot/dsl/panels.rb +80 -0
- data/lib/termplot/dsl/widgets.rb +128 -0
- data/lib/termplot/file_config.rb +37 -0
- data/lib/termplot/message_broker.rb +108 -0
- data/lib/termplot/options.rb +100 -20
- data/lib/termplot/positioned_widget.rb +8 -0
- data/lib/termplot/producer_options.rb +3 -0
- data/lib/termplot/producers.rb +3 -3
- data/lib/termplot/producers/base_producer.rb +12 -15
- data/lib/termplot/producers/command_producer.rb +25 -9
- data/lib/termplot/producers/stdin_producer.rb +1 -4
- data/lib/termplot/renderable.rb +35 -0
- data/lib/termplot/renderer.rb +16 -257
- data/lib/termplot/renderers.rb +6 -0
- data/lib/termplot/renderers/border_renderer.rb +48 -0
- data/lib/termplot/renderers/text_renderer.rb +73 -0
- data/lib/termplot/shell.rb +13 -9
- data/lib/termplot/utils/ansi_safe_string.rb +68 -0
- data/lib/termplot/version.rb +1 -1
- data/lib/termplot/widget_dsl.rb +130 -0
- data/lib/termplot/widgets.rb +8 -0
- data/lib/termplot/widgets/base_widget.rb +79 -0
- data/lib/termplot/widgets/border.rb +6 -0
- data/lib/termplot/widgets/dataset.rb +50 -0
- data/lib/termplot/widgets/histogram_widget.rb +196 -0
- data/lib/termplot/widgets/statistics.rb +21 -0
- data/lib/termplot/widgets/statistics_widget.rb +104 -0
- data/lib/termplot/widgets/time_series_widget.rb +248 -0
- data/lib/termplot/window.rb +25 -5
- data/termplot.gemspec +1 -6
- metadata +36 -24
- data/doc/MSFT.png +0 -0
- data/doc/cpu.png +0 -0
- data/doc/demo.cast +0 -638
- data/lib/termplot/consumer.rb +0 -75
- data/lib/termplot/cursors/console_cursor.rb +0 -57
- data/lib/termplot/series.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dda87efbf9aed716a37a8ca65eab2d8f773f9e4a18ea9db6ab7aff4dc820c2ff
|
4
|
+
data.tar.gz: 82a897c92653354d77de8515cd370507aaba295f9a35425134af1a0752fb6d2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16969163d4b669fd5cf930310af369aaa6e4a83d25e16bd51ba528d1ebb71c303d1beead130f4a9ef6d39992f7c92017fc149b2dbf0fcd46be6c0df15ed9b760
|
7
|
+
data.tar.gz: d509eeb9d34180fe4b338de314bcab5060e9f25a9d63d1ad4ff04e137c4d3b282209df7ff660a74a30e82c663d2eedd96fcc3d1204d8f3e16bf88d0ea47f1e76
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -2,15 +2,13 @@
|
|
2
2
|
|
3
3
|
Termplot is a simple terminal plotting tool for visualising streaming data.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
[](https://asciinema.org/a/3rzeUSXp2fRjnErX0p3SptP5e)
|
5
|
+

|
8
6
|
|
9
7
|
## Overview
|
10
8
|
|
11
|
-
Termplot draws
|
12
|
-
|
13
|
-
|
9
|
+
Termplot draws live plots of data in your terminal. It's handy for quickly
|
10
|
+
visualising streaming data and works with any numeric data you can pipe into
|
11
|
+
stdin or otherwise obtain by running a shell command.
|
14
12
|
|
15
13
|
## Installation
|
16
14
|
|
@@ -20,87 +18,156 @@ The tool is a ruby gem and can be installed with:
|
|
20
18
|
|
21
19
|
## Usage
|
22
20
|
|
23
|
-
|
21
|
+
There are 3 ways to provide input to termplot:
|
22
|
+
- **Stdin:** Pipe data into standard input
|
23
|
+
- **Command:** Specify a command to be ran at an interval
|
24
|
+
- **Configuration file:** Read a multi-chart configuration from a file
|
24
25
|
|
26
|
+
### Pipe data into standard input
|
25
27
|
```
|
26
|
-
|
28
|
+
COMMAND | termplot [OPTIONS]
|
27
29
|
```
|
28
30
|
|
29
|
-
`
|
30
|
-
delimited by a newline.
|
31
|
-
interval to produce the data.
|
32
|
-
|
33
|
-
Options and examples are given below. All command line options are
|
34
|
-
optional.
|
31
|
+
`COMMAND` is any command that will periodically output numbers to standard out
|
32
|
+
delimited by a newline. These will be consumed by termplot and drawn to a chart.
|
35
33
|
|
34
|
+
You can specify the following options (all are optional):
|
35
|
+
```
|
36
|
+
-r, --rows ROWS Number of rows in the chart window (default: 19)
|
37
|
+
-c, --cols COLS Number of cols in the chart window (default: 100)
|
38
|
+
--full-screen Render to the full available terminal size
|
39
|
+
|
40
|
+
--type TYPE The type of chart to render.
|
41
|
+
Options are: timeseries (default), stats, hist
|
42
|
+
|
43
|
+
--timeseries Shorthand for --type timeseries
|
44
|
+
--stats Shorthand for --type stats
|
45
|
+
--hist Shorthand for --type hist
|
46
|
+
|
47
|
+
-t, --title TITLE Title of the series (default: 'Series')
|
48
|
+
--color COLOR Series color, specified as ansi 16-bit color name:
|
49
|
+
(i.e. black, light_black, red, light_red,
|
50
|
+
green (default), light_green, yellow,
|
51
|
+
light_yellow, blue, light_blue, magenta,
|
52
|
+
light_magenta, cyan, light_cyan, white,
|
53
|
+
light_white, default)
|
54
|
+
|
55
|
+
--line-style STYLE Line style.
|
56
|
+
Options are: line, heavy-line (default), dot, star, x, bar
|
36
57
|
```
|
37
|
-
Usage: termplot [OPTIONS]
|
38
|
-
-r, --rows ROWS Number of rows in the chart window (default: 19)
|
39
58
|
|
40
|
-
|
59
|
+
#### Examples
|
41
60
|
|
42
|
-
|
61
|
+
##### Plot a sine wave from standard in:
|
43
62
|
|
44
|
-
|
63
|
+
```
|
64
|
+
for i in $(seq 500); do \
|
65
|
+
echo $i | awk '{ print sin($0/10) }'; \
|
66
|
+
sleep 0.5; \
|
67
|
+
done | termplot -t "Sin(x)" --color red
|
68
|
+
```
|
69
|
+

|
45
70
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
71
|
+
##### Plot histogram of network times as reported by `ping`:
|
72
|
+
```
|
73
|
+
ping example.com |
|
74
|
+
awk '{ split($8,arr,"="); print arr[2]; fflush("/dev/stdout") }' |
|
75
|
+
termplot -t "Ping Response Times (ms)" --hist
|
76
|
+
```
|
77
|
+

|
50
78
|
|
51
|
-
|
52
|
-
|
79
|
+
##### Plot histogram of data from column 33 of a CSV file
|
80
|
+
```
|
81
|
+
cat file.csv | cut -d, -f33 | tail -n +2 |
|
82
|
+
termplot -- --hist -r30 -t "Data" --color light_black
|
83
|
+
```
|
84
|
+

|
53
85
|
|
54
|
-
--interval INTERVAL The interval at which to run the specified command in
|
55
|
-
command mode in milliseconds (default: 1000)
|
56
86
|
|
57
|
-
|
87
|
+
### Run command at an interval
|
88
|
+
To run a command at an interval, specify `--command`, and optionally
|
89
|
+
`--interval` to termplot:
|
90
|
+
```
|
91
|
+
termplot --command 'COMMAND' --interval INTERVAL [OPTIONS]
|
58
92
|
```
|
59
|
-
Note: Make sure to wrap your command in single quotes when using `--command` if
|
60
|
-
you use shell variables (e.g. `$1`) in your command.
|
61
93
|
|
62
|
-
|
94
|
+
`COMMAND` will be invoked at the specified interval in milliseconds (default:
|
95
|
+
1000) and its output will be used as the data for the chart. You can specify all
|
96
|
+
the same additional options as in stdin mode above.
|
63
97
|
|
64
|
-
####
|
98
|
+
#### Examples
|
99
|
+
##### Plot number of TCP connections over time:
|
65
100
|
|
66
101
|
```
|
67
|
-
|
68
|
-
|
69
|
-
sleep 0.5; \
|
70
|
-
done | termplot -t "Sin(x)"
|
102
|
+
termplot --command 'ss -s | head -n1 | cut -d" " -f2' \
|
103
|
+
--interval 500 -t "TCP Connections"
|
71
104
|
```
|
72
|
-

|
106
|
+
|
107
|
+
##### Plot memory usage of process with PID 4396:
|
73
108
|
|
74
|
-
#### Memory usage (%)
|
75
109
|
```
|
76
|
-
termplot --command
|
77
|
-
-t "Memory (
|
110
|
+
termplot --command "ps -q 4396 -o rss= | awk '{ print (\$0/1024.0) }'" \
|
111
|
+
-t "Process 4396 Memory (MB)" --color light_magenta
|
78
112
|
```
|
79
|
-

|
80
114
|
|
81
|
-
|
115
|
+
### Specify a multi-chart configuration
|
116
|
+
You can configure termplot to set up a multi-chart dashboard using a ruby
|
117
|
+
configuration file:
|
82
118
|
|
83
|
-
|
119
|
+
```
|
120
|
+
termplot --file FILE
|
121
|
+
```
|
84
122
|
|
123
|
+
The configuration file uses a simple ruby DSL to arrange charts into rows and
|
124
|
+
columns. Each chart will take a command and optionally an interval as well as
|
125
|
+
formatting options. Termplot will then run the command at the specified interval
|
126
|
+
and render the resulting data into the charts.
|
127
|
+
|
128
|
+
Example file (sample.rb):
|
129
|
+
```ruby
|
130
|
+
col do
|
131
|
+
row do
|
132
|
+
cpu_command =
|
133
|
+
"top -b -n 1 | awk -F',' 'NR==3{ split($4, arr, \" \"); print 100.0 - arr[1] }'"
|
134
|
+
|
135
|
+
histogram title: "CPU (%)", command: cpu_command, color: "light_cyan"
|
136
|
+
timeseries title: "CPU (%)", command: cpu_command, color: "light_cyan"
|
137
|
+
statistics title: "CPU (%)", command: cpu_command
|
138
|
+
end
|
139
|
+
|
140
|
+
row do
|
141
|
+
memory_command = "free | awk 'NR==2 { print ($3/$2) * 100 }'"
|
142
|
+
|
143
|
+
histogram title: "Memory (%)", command: memory_command, color: "light_magenta"
|
144
|
+
timeseries title: "Memory (%)", command: memory_command, color: "light_magenta"
|
145
|
+
statistics title: "Memory (%)", command: memory_command
|
146
|
+
end
|
147
|
+
end
|
148
|
+
```
|
149
|
+
Run it with:
|
85
150
|
```
|
86
|
-
termplot
|
87
|
-
--interval 10000 -t "MSFT" --color light_green
|
151
|
+
termplot -f sample.rb --cols 150 --rows 20
|
88
152
|
```
|
89
|
-
|
153
|
+
|
154
|
+
Result:
|
155
|
+

|
156
|
+
|
90
157
|
|
91
158
|
## Notes
|
92
159
|
|
93
|
-
-
|
160
|
+
- Termplot should work just fine if you have a monospaced unicode font.
|
94
161
|
Tested on linux, and should work on MacOS too. Not too sure about windows.
|
95
|
-
-
|
96
|
-
temporal spacing. So even if the time between samples is
|
97
|
-
will be plotted with the same amount of space between them.
|
162
|
+
- On timeseries plots, samples received are plotted in sequence order, and there
|
163
|
+
is no notion of temporal spacing. So even if the time between samples is
|
164
|
+
inconsistent, they will be plotted with the same amount of space between them.
|
98
165
|
|
99
|
-
## Background
|
166
|
+
## Background
|
100
167
|
|
101
|
-
I
|
102
|
-
linux machine. I could get the data I needed from `ss` with some text
|
103
|
-
but I didn't have a quick and easy way to eyeball the overall trend.
|
168
|
+
A while back I needed to be able to monitor the number of open TCP connections
|
169
|
+
on my linux machine. I could get the data I needed from `ss` with some text
|
170
|
+
processing but I didn't have a quick and easy way to eyeball the overall trend.
|
104
171
|
|
105
172
|
I mainly work with ruby, so taking
|
106
173
|
inspiration from fantastic libraries like [Unicode Plots
|
@@ -116,6 +183,9 @@ termplot --command 'ss -s | head -n1 | cut -d" " -f2' --interval 500 -t "TCP Con
|
|
116
183
|
|
117
184
|

|
118
185
|
|
186
|
+
In the end termplot turned out to be useful for all sorts of command line
|
187
|
+
visualisation tasks.
|
188
|
+
|
119
189
|
## Development
|
120
190
|
|
121
191
|
After checking out the repo, run `bin/setup` to install dependencies. There are
|
data/Rakefile
CHANGED
@@ -1,20 +1,33 @@
|
|
1
|
+
require_relative "./lib/termplot/commands"
|
1
2
|
require "bundler/gem_tasks"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
end
|
4
|
+
extend Termplot::Commands
|
5
|
+
extend Termplot::StdinCommands
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
do
|
11
|
-
echo $i | awk '{ print sin($0/10)* 10; fflush("/dev/stdout") }';
|
12
|
-
sleep 0.1;
|
13
|
-
done | ruby -Ilib bin/termplot -- -t 'sin(x)'
|
14
|
-
CMD
|
15
|
-
exec cmd
|
7
|
+
SAMPLE_FILES_PATH = "examples"
|
8
|
+
def termplot_binary
|
9
|
+
"ruby -Ilib bin/termplot"
|
16
10
|
end
|
17
11
|
|
18
|
-
|
19
|
-
|
12
|
+
namespace :test do
|
13
|
+
task :bin do
|
14
|
+
exec "ruby", "-Ilib", "bin/termplot", *ARGV[2..-1]
|
15
|
+
end
|
16
|
+
|
17
|
+
task :file do
|
18
|
+
cmd = %( #{termplot_binary} -f #{File.join(SAMPLE_FILES_PATH, ARGV[2])} #{ARGV[3..-1].join(" ")})
|
19
|
+
exec cmd
|
20
|
+
end
|
21
|
+
|
22
|
+
namespace :timeseries do
|
23
|
+
task :sin do
|
24
|
+
cmd = "#{sin(500)} | #{termplot_binary} -t 'sin(x)'"
|
25
|
+
exec cmd
|
26
|
+
end
|
27
|
+
|
28
|
+
task :random do
|
29
|
+
cmd = %( #{termplot_binary} --command '#{random}' --interval 900% )
|
30
|
+
exec cmd
|
31
|
+
end
|
32
|
+
end
|
20
33
|
end
|
data/doc/dash.png
ADDED
Binary file
|
data/doc/demo.png
ADDED
Binary file
|
data/doc/file.png
ADDED
Binary file
|
data/doc/memory.png
CHANGED
Binary file
|
data/doc/ping.png
ADDED
Binary file
|
data/doc/sin.png
CHANGED
Binary file
|
data/doc/tcp.png
CHANGED
Binary file
|
data/examples/sample.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
col do
|
2
|
+
row do
|
3
|
+
cpu_command = "top -b -n 1 | awk -F',' 'NR==3{ split($4, arr, \" \"); print 100.0 - arr[1] }'"
|
4
|
+
|
5
|
+
histogram title: "CPU (%)", command: cpu_command, color: "light_cyan"
|
6
|
+
timeseries title: "CPU (%)", command: cpu_command, color: "light_cyan"
|
7
|
+
statistics title: "CPU (%)", command: cpu_command
|
8
|
+
end
|
9
|
+
|
10
|
+
row do
|
11
|
+
memory_command = "free | awk 'NR==2 { print ($3/$2) * 100 }'"
|
12
|
+
|
13
|
+
histogram title: "Memory (%)", command: memory_command, color: "light_magenta"
|
14
|
+
timeseries title: "Memory (%)", command: memory_command, color: "light_magenta"
|
15
|
+
statistics title: "Memory (%)", command: memory_command
|
16
|
+
end
|
17
|
+
end
|
@@ -12,7 +12,9 @@ module Termplot
|
|
12
12
|
top_left: "┌",
|
13
13
|
bot_right: "┘",
|
14
14
|
tick_right: "┤",
|
15
|
-
|
15
|
+
tick_left: "├",
|
16
|
+
extended: true,
|
17
|
+
filled: false
|
16
18
|
}
|
17
19
|
DEFAULT = LINE
|
18
20
|
|
@@ -26,13 +28,15 @@ module Termplot
|
|
26
28
|
top_right: "┓",
|
27
29
|
top_left: "┏",
|
28
30
|
bot_right: "┛",
|
29
|
-
tick_right: "┫"
|
31
|
+
tick_right: "┫",
|
32
|
+
tick_left: "┣",
|
30
33
|
)
|
31
34
|
|
32
35
|
BASIC = {
|
33
36
|
empty: " ",
|
34
37
|
point: "•",
|
35
|
-
extended: false
|
38
|
+
extended: false,
|
39
|
+
filled: false
|
36
40
|
}
|
37
41
|
DOTS = BASIC
|
38
42
|
|
@@ -44,12 +48,19 @@ module Termplot
|
|
44
48
|
point: "*"
|
45
49
|
)
|
46
50
|
|
51
|
+
BAR = LINE.merge(
|
52
|
+
point: "▄",
|
53
|
+
extended: false,
|
54
|
+
filled: true
|
55
|
+
)
|
56
|
+
|
47
57
|
LINE_STYLES = {
|
48
58
|
"line" => LINE,
|
49
59
|
"heavy-line" => HEAVY_LINE,
|
50
60
|
"dot" => DOTS,
|
51
61
|
"star" => STAR,
|
52
|
-
"x" => X
|
62
|
+
"x" => X,
|
63
|
+
"bar" => BAR,
|
53
64
|
}
|
54
65
|
end
|
55
66
|
end
|
data/lib/termplot/cli.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "termplot/options"
|
3
|
-
require "termplot/
|
3
|
+
require "termplot/consumers"
|
4
4
|
|
5
5
|
module Termplot
|
6
6
|
class CLI
|
7
7
|
def self.run
|
8
|
-
|
9
|
-
|
8
|
+
options = Termplot::Options.new
|
9
|
+
options.parse_options!
|
10
|
+
run_consumer(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
CONSUMERS = {
|
16
|
+
file: "Termplot::Consumers::MultiSourceConsumer",
|
17
|
+
command: "Termplot::Consumers::CommandConsumer",
|
18
|
+
stdin: "Termplot::Consumers::StdinConsumer",
|
19
|
+
}
|
20
|
+
def self.run_consumer(options)
|
21
|
+
consumer = Object.const_get(CONSUMERS[options.input_mode])
|
22
|
+
consumer.new(options).run
|
10
23
|
end
|
11
24
|
end
|
12
25
|
end
|
data/lib/termplot/colors.rb
CHANGED
@@ -35,6 +35,9 @@ module Termplot
|
|
35
35
|
define_method(color) do |str|
|
36
36
|
escape_color(color) + str + escape_mode(:default)
|
37
37
|
end
|
38
|
+
define_method("#{color}_bg") do |str|
|
39
|
+
escape_bg_color(color) + str + escape_mode(:default)
|
40
|
+
end
|
38
41
|
end
|
39
42
|
|
40
43
|
def fetch(color, default)
|
@@ -47,6 +50,10 @@ module Termplot
|
|
47
50
|
"\e[#{COLORS[color] + 30}m"
|
48
51
|
end
|
49
52
|
|
53
|
+
def escape_bg_color(color)
|
54
|
+
"\e[#{COLORS[color] + 40}m"
|
55
|
+
end
|
56
|
+
|
50
57
|
def escape_mode(mode)
|
51
58
|
"\e[#{MODES[mode]}m"
|
52
59
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Termplot
|
2
|
+
module Commands
|
3
|
+
def random
|
4
|
+
"echo $RANDOM"
|
5
|
+
end
|
6
|
+
|
7
|
+
def memory
|
8
|
+
"free | awk 'NR==2 { print ($3/$2) * 100 }'"
|
9
|
+
end
|
10
|
+
|
11
|
+
def cpu
|
12
|
+
"top -b -n 1 | awk -F',' 'NR==3{ split($4, arr, \" \"); print 100.0 - arr[1] }'"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module StdinCommands
|
17
|
+
def sin(n)
|
18
|
+
<<-CMD.chomp
|
19
|
+
for i in $(seq #{n});
|
20
|
+
do
|
21
|
+
echo $i | awk '{ print sin($0/10)* 10; fflush("/dev/stdout") }';
|
22
|
+
sleep 0.1;
|
23
|
+
done
|
24
|
+
CMD
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|