nodectl 0.2.4
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +4 -0
- data/README.md +3 -0
- data/Rakefile +1 -0
- data/TODO.md +7 -0
- data/assets/javascript/application.coffee +22 -0
- data/assets/javascript/bootstrap.js +2006 -0
- data/assets/javascript/controllers/application_controller.coffee +73 -0
- data/assets/javascript/controllers/service_controller.coffee +62 -0
- data/assets/javascript/event_handler.coffee +51 -0
- data/assets/javascript/models/action.coffee +28 -0
- data/assets/javascript/models/instance.coffee +7 -0
- data/assets/javascript/models/service.coffee +75 -0
- data/assets/javascript/models/version.coffee +3 -0
- data/assets/javascript/notifier.coffee +64 -0
- data/assets/javascript/router.coffee +3 -0
- data/assets/javascript/routes/application.coffee +6 -0
- data/assets/javascript/routes/log.coffee +4 -0
- data/assets/javascript/routes/service.coffee +3 -0
- data/assets/javascript/store.coffee +32 -0
- data/assets/javascript/templates/application.hbs +82 -0
- data/assets/javascript/templates/index.hbs +1 -0
- data/assets/javascript/templates/log.hbs +1 -0
- data/assets/javascript/templates/service.hbs +110 -0
- data/assets/javascript/templates/views/action.hbs +20 -0
- data/assets/javascript/templates/views/actions_list.hbs +26 -0
- data/assets/javascript/templates/views/environments_list.hbs +9 -0
- data/assets/javascript/templates/views/install_button.hbs +1 -0
- data/assets/javascript/templates/views/mass_run.hbs +30 -0
- data/assets/javascript/templates/views/notifier_control.hbs +7 -0
- data/assets/javascript/templates/views/param.hbs +6 -0
- data/assets/javascript/templates/views/terminal.hbs +8 -0
- data/assets/javascript/ui.coffee +24 -0
- data/assets/javascript/vendor/ansiparse.js +186 -0
- data/assets/javascript/vendor/audio.min.js +24 -0
- data/assets/javascript/vendor/audiojs.swf +0 -0
- data/assets/javascript/vendor/ember-data.js +10528 -0
- data/assets/javascript/vendor/ember.js +40583 -0
- data/assets/javascript/vendor/handlebars.js +2746 -0
- data/assets/javascript/vendor/jquery.js +8829 -0
- data/assets/javascript/vendor/ladda.js +157 -0
- data/assets/javascript/vendor/moment.min.js +6 -0
- data/assets/javascript/vendor/notify-osd.js +319 -0
- data/assets/javascript/vendor/player-graphics.gif +0 -0
- data/assets/javascript/vendor/spin.js +218 -0
- data/assets/javascript/views/action_view.coffee +18 -0
- data/assets/javascript/views/actions_list_view.coffee +2 -0
- data/assets/javascript/views/environments_list_view.coffee +2 -0
- data/assets/javascript/views/install_button_view.coffee +34 -0
- data/assets/javascript/views/mass_run_view.coffee +107 -0
- data/assets/javascript/views/notifier_control_view.coffee +29 -0
- data/assets/javascript/views/terminal_view.coffee +56 -0
- data/assets/stylesheets/application.css +137 -0
- data/assets/stylesheets/bootstrap-theme.css +347 -0
- data/assets/stylesheets/bootstrap.css +5785 -0
- data/assets/stylesheets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/assets/stylesheets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/assets/stylesheets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/assets/stylesheets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/assets/stylesheets/ladda-themeless.css +330 -0
- data/assets/stylesheets/ladda.css +392 -0
- data/assets/stylesheets/notify-osd.css +49 -0
- data/assets/stylesheets/terminal.css +12 -0
- data/bin/nodectl +4 -0
- data/lib/nodectl.rb +137 -0
- data/lib/nodectl/action.rb +80 -0
- data/lib/nodectl/binding.rb +13 -0
- data/lib/nodectl/cli.rb +123 -0
- data/lib/nodectl/context.rb +34 -0
- data/lib/nodectl/database.rb +55 -0
- data/lib/nodectl/generators/init.rb +22 -0
- data/lib/nodectl/generators/templates/init/.gitignore +5 -0
- data/lib/nodectl/generators/templates/init/config/manifest.yml +1 -0
- data/lib/nodectl/generators/templates/init/config/server.yml +7 -0
- data/lib/nodectl/instance.rb +100 -0
- data/lib/nodectl/log.rb +13 -0
- data/lib/nodectl/manager.rb +71 -0
- data/lib/nodectl/multi_io.rb +16 -0
- data/lib/nodectl/options.rb +47 -0
- data/lib/nodectl/process.rb +145 -0
- data/lib/nodectl/promised_file.rb +37 -0
- data/lib/nodectl/recipe.rb +197 -0
- data/lib/nodectl/repository.rb +80 -0
- data/lib/nodectl/server.rb +103 -0
- data/lib/nodectl/service.rb +126 -0
- data/lib/nodectl/stream/buffer.rb +44 -0
- data/lib/nodectl/stream/events_session.rb +39 -0
- data/lib/nodectl/stream/file.rb +69 -0
- data/lib/nodectl/stream/file_session.rb +35 -0
- data/lib/nodectl/stream/file_with_memory.rb +17 -0
- data/lib/nodectl/stream/websocket.rb +90 -0
- data/lib/nodectl/version.rb +3 -0
- data/lib/nodectl/watchdog.rb +17 -0
- data/lib/nodectl/webapp/actions.rb +21 -0
- data/lib/nodectl/webapp/base.rb +29 -0
- data/lib/nodectl/webapp/instances.rb +46 -0
- data/lib/nodectl/webapp/public/sounds/alert.mp3 +0 -0
- data/lib/nodectl/webapp/public/sounds/error.mp3 +0 -0
- data/lib/nodectl/webapp/public/sounds/question.mp3 +0 -0
- data/lib/nodectl/webapp/services.rb +39 -0
- data/lib/nodectl/webapp/settings.rb +7 -0
- data/lib/nodectl/webapp/ui.rb +19 -0
- data/lib/nodectl/webapp/versions.rb +12 -0
- data/lib/nodectl/webapp/views/ui.haml +20 -0
- data/nodectl.gemspec +35 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/stream/buffer_spec.rb +33 -0
- metadata +365 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hello world
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{view UI.TerminalView path=path}}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{{#if isInstalled}}
|
|
2
|
+
<div class="page-header">
|
|
3
|
+
<h2>{{id}} <small>powered by {{recipe_name}} recipe</small></h2>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
{{#if version_id}}
|
|
7
|
+
|
|
8
|
+
<p>
|
|
9
|
+
<span class="label label-primary">{{version_id}}</span> <small><b>{{version_timestamp}}</b> {{version_message}}</small>
|
|
10
|
+
</p>
|
|
11
|
+
<p>
|
|
12
|
+
<button class="btn btn-success btn-xs" {{action 'setLatestVersion' }}>Upgrade to latest</button>
|
|
13
|
+
<button class="btn btn-default btn-xs" {{action 'versions_toggle'}}>Show all versions</button>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
{{#if versions_opened}}
|
|
17
|
+
<ul>
|
|
18
|
+
{{#each versions}}
|
|
19
|
+
<li><small><button class="btn btn-success btn-xs" {{action 'setVersion' id }}>{{id}}</button> <em>({{timestamp}}) -- {{message}}</em></small></li>
|
|
20
|
+
{{/each}}
|
|
21
|
+
</ul>
|
|
22
|
+
{{/if}}
|
|
23
|
+
|
|
24
|
+
<hr>
|
|
25
|
+
{{/if}}
|
|
26
|
+
|
|
27
|
+
<div class="panel panel-default">
|
|
28
|
+
<div class="panel-heading">
|
|
29
|
+
<h4 class="panel-title">Actions</h4>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="panel-body">
|
|
33
|
+
<div class="btn-group">
|
|
34
|
+
{{#each supported_actions}}
|
|
35
|
+
<button class="btn btn-default btn-xs" {{action 'run_action' this }}>{{this}}</button>
|
|
36
|
+
{{/each}}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<hr>
|
|
42
|
+
|
|
43
|
+
{{#if start_supported}}
|
|
44
|
+
|
|
45
|
+
<div class="panel panel-default">
|
|
46
|
+
<div class="panel-heading">
|
|
47
|
+
<h4 class="panel-title pull-left">Instances</h4> <button class="btn btn-success btn-xs pull-right" {{action 'startInstance'}}>start</button>
|
|
48
|
+
<div class="clearfix"></div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="panel-body">
|
|
52
|
+
|
|
53
|
+
<table class="table table-condensed table-hover instances-table">
|
|
54
|
+
<thead>
|
|
55
|
+
<tr>
|
|
56
|
+
<th class="instances-table-pid">PID</td>
|
|
57
|
+
<th class="instances-table-status">Status</td>
|
|
58
|
+
<th class="instances-table-environment">Environment</td>
|
|
59
|
+
<th class="instances-table-actions">Actions</td>
|
|
60
|
+
</tr>
|
|
61
|
+
</thead>
|
|
62
|
+
<tbody>
|
|
63
|
+
{{#each instances}}
|
|
64
|
+
<tr {{bind-attr class=status}}>
|
|
65
|
+
<td>{{id}}</td>
|
|
66
|
+
<td>{{status}}</td>
|
|
67
|
+
<td>{{options.env}}</td>
|
|
68
|
+
<td>
|
|
69
|
+
{{#if service.stop_supported}}
|
|
70
|
+
<button class="btn btn-primary btn-xs" {{action 'stopInstance' this}}>stop</button>
|
|
71
|
+
<button class="btn btn-warning btn-xs" {{action 'restartInstance' this}}>restart</button>
|
|
72
|
+
<button class="btn btn-danger btn-xs" {{action 'killInstance' this}}>kill</button>
|
|
73
|
+
{{/if}}
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
{{/each}}
|
|
77
|
+
</tbody>
|
|
78
|
+
</table>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
{{/if}}
|
|
82
|
+
|
|
83
|
+
<div class="panel panel-default">
|
|
84
|
+
<div class="panel-heading">
|
|
85
|
+
<h4 class="panel-title">Logs</h4>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="panel-body">
|
|
89
|
+
<ul class="nav nav-pills">
|
|
90
|
+
{{#each logs}}
|
|
91
|
+
{{#link-to 'log' name tagName="li"}}
|
|
92
|
+
<!-- TODO: fix bug with assign 'active' class on page update -->
|
|
93
|
+
{{#link-to 'log' name}}{{name}}{{/link-to}}
|
|
94
|
+
{{/link-to}}
|
|
95
|
+
{{/each}}
|
|
96
|
+
</ul>
|
|
97
|
+
|
|
98
|
+
{{outlet}}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
{{else}}
|
|
103
|
+
|
|
104
|
+
<div class="jumbotron">
|
|
105
|
+
<h1>{{id}} <small>powered by {{recipe_name}} recipe</small></h1>
|
|
106
|
+
<p>This service is not installed yet.</p>
|
|
107
|
+
<p><button class="btn btn-primary btn-lg" role="button" {{action 'installService'}}>Install</button></p>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
{{/if}}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<div class="modal-window-content">
|
|
2
|
+
<p>
|
|
3
|
+
<span class="label label-primary">{{view.action.name}} for service {{view.action.service.id}}</span>
|
|
4
|
+
{{#if view.action.result}}
|
|
5
|
+
{{#if view.action.isSucceed}}
|
|
6
|
+
<span class="label label-success">succeed</span>
|
|
7
|
+
{{else}}
|
|
8
|
+
<span class="label label-danger">failed</span>
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{else}}
|
|
11
|
+
<span class="label label-default">running</span>
|
|
12
|
+
{{/if}}
|
|
13
|
+
<small>{{view.action.started_at_formatted}}</small>
|
|
14
|
+
</p>
|
|
15
|
+
<div class="terminal-wrapper">
|
|
16
|
+
{{#if view.action.ws}}
|
|
17
|
+
{{view UI.TerminalView path=view.action.ws class="action-terminal"}}
|
|
18
|
+
{{/if}}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
|
2
|
+
<span class="glyphicon glyphicon-th-large"></span> actions <b class="caret"></b>
|
|
3
|
+
</a>
|
|
4
|
+
|
|
5
|
+
<ul class="dropdown-menu">
|
|
6
|
+
<!-- TODO
|
|
7
|
+
<li>
|
|
8
|
+
<div class="btn-group btn-group-justified btn-group-actions">
|
|
9
|
+
<div class="btn-group btn-group-xs">
|
|
10
|
+
<button type="button" class="btn btn-default">Clear</button>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="btn-group btn-group-xs">
|
|
13
|
+
<button type="button" class="btn btn-default">Read all</button>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
</li>
|
|
18
|
+
-->
|
|
19
|
+
|
|
20
|
+
{{#each running_actions}}
|
|
21
|
+
<li {{bind-attr class=":action-list-item isSucceed:action-list-item-succeed isFailed:action-list-item-failed"}}><a href="#" {{action 'openAction' this}}><span class="label label-default">{{started_at_formatted}}</span> {{service.id}}: {{name}}</a></li>
|
|
22
|
+
{{else}}
|
|
23
|
+
<li>No actions yet</li>
|
|
24
|
+
{{/each}}
|
|
25
|
+
</ul>
|
|
26
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
|
2
|
+
<span class="glyphicon glyphicon-th-large"></span> {{UI.currentEnvironment}} <b class="caret"></b>
|
|
3
|
+
</a>
|
|
4
|
+
|
|
5
|
+
<ul class="dropdown-menu">
|
|
6
|
+
{{#each environments}}
|
|
7
|
+
<li><a href="#" {{action 'setEnvironment' this}}>{{this}}</a></li>
|
|
8
|
+
{{/each}}
|
|
9
|
+
</ul>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<button class="btn btn-success btn-xs ladda-button" data-size="xs" data-style="expand-left" {{action 'installService' target=view}}>Install{{#unless view.service}} all{{/unless}}</button>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<div class="list-group-item list-group-item-service mass-run-list-item list-group-item-service-controlls">
|
|
2
|
+
<div class="btn-group">
|
|
3
|
+
<button class="btn btn-success btn-xs" {{action "runSelected" target=view}}>Run!</button>
|
|
4
|
+
<button class="btn btn-primary btn-xs" {{action "selectIdle" target=view}}>Select idle</button>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
{{view view.selectAllCheckbox class="checkbox" list=view.servicesSelected services=view.servicesRunnable parent=view}}
|
|
8
|
+
|
|
9
|
+
<button class="btn btn-danger btn-xs pull-right" {{action 'toggleMassRunOpened'}}>Cancel</button>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
{{#each view.services}}
|
|
13
|
+
<label {{bind-attr class=":list-group-item :list-group-item-service :mass-run-list-item isRunning"}}>
|
|
14
|
+
{{#if isRunning}}
|
|
15
|
+
<div class="service-run-indicator"> </div>
|
|
16
|
+
{{/if}}
|
|
17
|
+
|
|
18
|
+
{{#if start_supported}}
|
|
19
|
+
{{view view.runCheckbox service=this list=view.servicesSelected class="checkbox"}}
|
|
20
|
+
{{/if}}
|
|
21
|
+
|
|
22
|
+
<div class="sidebar-services-id">
|
|
23
|
+
{{id}}
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
{{#if start_supported}}
|
|
27
|
+
<span class="badge">{{instances.length}}</span>
|
|
28
|
+
{{/if}}
|
|
29
|
+
</label>
|
|
30
|
+
{{/each}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<li>
|
|
2
|
+
<a href="#" {{action "toggleSound" target="view"}} {{bind-attr class="view.soundEnabled::notify-control-disabled"}}><span {{bind-attr class=":glyphicon view.soundEnabled:glyphicon-ok:glyphicon-remove"}}></span> Sounds</b></a>
|
|
3
|
+
</li>
|
|
4
|
+
|
|
5
|
+
<li>
|
|
6
|
+
<a href="#" {{action "togglePopup" target="view"}} {{bind-attr class="view.popupEnabled::notify-control-disabled"}}><span {{bind-attr class=":glyphicon view.popupEnabled:glyphicon-ok:glyphicon-remove"}}></span> Popups</b></a>
|
|
7
|
+
</li>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
{{#if choices }}
|
|
3
|
+
{{view Ember.Select content=view.inst_options.choices optionValuePath="content" optionLabelPath="content" value=view.value selection=view.inst_options.default class="form-control input-sm"}}
|
|
4
|
+
{{else}}
|
|
5
|
+
<input class="form-control input-sm" {{bind-attr 'placeholer' name}}>
|
|
6
|
+
{{/if}}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#= require ./vendor/jquery
|
|
2
|
+
#= require ./vendor/handlebars
|
|
3
|
+
#= require ./vendor/ember
|
|
4
|
+
#= require ./vendor/ember-data
|
|
5
|
+
#= require ./vendor/ansiparse
|
|
6
|
+
#= require ./vendor/spin
|
|
7
|
+
#= require ./vendor/ladda
|
|
8
|
+
#= require ./vendor/moment.min
|
|
9
|
+
#= require ./vendor/audio.min
|
|
10
|
+
#= require ./vendor/notify-osd
|
|
11
|
+
|
|
12
|
+
#= require ./application
|
|
13
|
+
#= require ./store
|
|
14
|
+
#= require ./router
|
|
15
|
+
|
|
16
|
+
#= require_tree ./templates
|
|
17
|
+
#= require_tree ./models
|
|
18
|
+
#= require_tree ./controllers
|
|
19
|
+
#= require_tree ./routes
|
|
20
|
+
#= require_tree ./views
|
|
21
|
+
|
|
22
|
+
#= require ./bootstrap
|
|
23
|
+
#= require ./event_handler
|
|
24
|
+
#= require ./notifier
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
ansiparse = function (str) {
|
|
2
|
+
//
|
|
3
|
+
// I'm terrible at writing parsers.
|
|
4
|
+
//
|
|
5
|
+
var matchingControl = null,
|
|
6
|
+
matchingData = null,
|
|
7
|
+
matchingText = '',
|
|
8
|
+
ansiState = [],
|
|
9
|
+
result = [],
|
|
10
|
+
state = {},
|
|
11
|
+
eraseChar;
|
|
12
|
+
|
|
13
|
+
//
|
|
14
|
+
// General workflow for this thing is:
|
|
15
|
+
// \033\[33mText
|
|
16
|
+
// | | |
|
|
17
|
+
// | | matchingText
|
|
18
|
+
// | matchingData
|
|
19
|
+
// matchingControl
|
|
20
|
+
//
|
|
21
|
+
// In further steps we hope it's all going to be fine. It usually is.
|
|
22
|
+
//
|
|
23
|
+
|
|
24
|
+
//
|
|
25
|
+
// Erases a char from the output
|
|
26
|
+
//
|
|
27
|
+
eraseChar = function () {
|
|
28
|
+
var index, text;
|
|
29
|
+
if (matchingText.length) {
|
|
30
|
+
matchingText = matchingText.substr(0, matchingText.length - 1);
|
|
31
|
+
}
|
|
32
|
+
else if (result.length) {
|
|
33
|
+
index = result.length - 1;
|
|
34
|
+
text = result[index].text;
|
|
35
|
+
if (text.length === 1) {
|
|
36
|
+
//
|
|
37
|
+
// A result bit was fully deleted, pop it out to simplify the final output
|
|
38
|
+
//
|
|
39
|
+
result.pop();
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
result[index].text = text.substr(0, text.length - 1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
for (var i = 0; i < str.length; i++) {
|
|
48
|
+
if (matchingControl != null) {
|
|
49
|
+
if (matchingControl == '\033' && str[i] == '\[') {
|
|
50
|
+
//
|
|
51
|
+
// We've matched full control code. Lets start matching formating data.
|
|
52
|
+
//
|
|
53
|
+
|
|
54
|
+
//
|
|
55
|
+
// "emit" matched text with correct state
|
|
56
|
+
//
|
|
57
|
+
if (matchingText) {
|
|
58
|
+
state.text = matchingText;
|
|
59
|
+
result.push(state);
|
|
60
|
+
state = {};
|
|
61
|
+
matchingText = "";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
matchingControl = null;
|
|
65
|
+
matchingData = '';
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
//
|
|
69
|
+
// We failed to match anything - most likely a bad control code. We
|
|
70
|
+
// go back to matching regular strings.
|
|
71
|
+
//
|
|
72
|
+
matchingText += matchingControl + str[i];
|
|
73
|
+
matchingControl = null;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
else if (matchingData != null) {
|
|
78
|
+
if (str[i] == ';') {
|
|
79
|
+
//
|
|
80
|
+
// `;` separates many formatting codes, for example: `\033[33;43m`
|
|
81
|
+
// means that both `33` and `43` should be applied.
|
|
82
|
+
//
|
|
83
|
+
// TODO: this can be simplified by modifying state here.
|
|
84
|
+
//
|
|
85
|
+
ansiState.push(matchingData);
|
|
86
|
+
matchingData = '';
|
|
87
|
+
}
|
|
88
|
+
else if (str[i] == 'm') {
|
|
89
|
+
//
|
|
90
|
+
// `m` finished whole formatting code. We can proceed to matching
|
|
91
|
+
// formatted text.
|
|
92
|
+
//
|
|
93
|
+
ansiState.push(matchingData);
|
|
94
|
+
matchingData = null;
|
|
95
|
+
matchingText = '';
|
|
96
|
+
|
|
97
|
+
//
|
|
98
|
+
// Convert matched formatting data into user-friendly state object.
|
|
99
|
+
//
|
|
100
|
+
// TODO: DRY.
|
|
101
|
+
//
|
|
102
|
+
ansiState.forEach(function (ansiCode) {
|
|
103
|
+
if (ansiparse.foregroundColors[ansiCode]) {
|
|
104
|
+
state.foreground = ansiparse.foregroundColors[ansiCode];
|
|
105
|
+
}
|
|
106
|
+
else if (ansiparse.backgroundColors[ansiCode]) {
|
|
107
|
+
state.background = ansiparse.backgroundColors[ansiCode];
|
|
108
|
+
}
|
|
109
|
+
else if (ansiCode == 39) {
|
|
110
|
+
delete state.foreground;
|
|
111
|
+
}
|
|
112
|
+
else if (ansiCode == 49) {
|
|
113
|
+
delete state.background;
|
|
114
|
+
}
|
|
115
|
+
else if (ansiparse.styles[ansiCode]) {
|
|
116
|
+
state[ansiparse.styles[ansiCode]] = true;
|
|
117
|
+
}
|
|
118
|
+
else if (ansiCode == 22) {
|
|
119
|
+
state.bold = false;
|
|
120
|
+
}
|
|
121
|
+
else if (ansiCode == 23) {
|
|
122
|
+
state.italic = false;
|
|
123
|
+
}
|
|
124
|
+
else if (ansiCode == 24) {
|
|
125
|
+
state.underline = false;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
ansiState = [];
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
matchingData += str[i];
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (str[i] == '\033') {
|
|
137
|
+
matchingControl = str[i];
|
|
138
|
+
}
|
|
139
|
+
else if (str[i] == '\u0008') {
|
|
140
|
+
eraseChar();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
matchingText += str[i];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (matchingText) {
|
|
148
|
+
state.text = matchingText + (matchingControl ? matchingControl : '');
|
|
149
|
+
result.push(state);
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
ansiparse.foregroundColors = {
|
|
155
|
+
'30': 'black',
|
|
156
|
+
'31': 'red',
|
|
157
|
+
'32': 'green',
|
|
158
|
+
'33': 'yellow',
|
|
159
|
+
'34': 'blue',
|
|
160
|
+
'35': 'magenta',
|
|
161
|
+
'36': 'cyan',
|
|
162
|
+
'37': 'white',
|
|
163
|
+
'90': 'grey'
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
ansiparse.backgroundColors = {
|
|
167
|
+
'40': 'black',
|
|
168
|
+
'41': 'red',
|
|
169
|
+
'42': 'green',
|
|
170
|
+
'43': 'yellow',
|
|
171
|
+
'44': 'blue',
|
|
172
|
+
'45': 'magenta',
|
|
173
|
+
'46': 'cyan',
|
|
174
|
+
'47': 'white'
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
ansiparse.styles = {
|
|
178
|
+
'1': 'bold',
|
|
179
|
+
'3': 'italic',
|
|
180
|
+
'4': 'underline'
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
if (typeof module == "object" && typeof window == "undefined") {
|
|
184
|
+
module.exports = ansiparse;
|
|
185
|
+
}
|
|
186
|
+
|