flammarion 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -21,7 +21,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  THE SOFTWARE.
22
22
 
23
23
 
24
- # Font Awesome
24
+ # External Packages
25
+
26
+ Flammarion is bundled with a number of 3rd party packages:
27
+
28
+ ## Font Awesome
25
29
 
26
30
  This software incorporates
27
31
  [Font Awesome by Dave Gandy - http://fontawesome.io](http://fontawesome.io). The
@@ -30,3 +34,60 @@ fonts in Font Awesome are licensed under the
30
34
  licensed under the [MIT License](http://opensource.org/licenses/mit-license.html)
31
35
 
32
36
  C.f. https://fortawesome.github.io/Font-Awesome/license/
37
+
38
+ ## JQuery
39
+
40
+ jQuery Foundation projects are released under the terms of the license specified in the project's repository or if not specified, under the [MIT license](https://tldrlegal.com/license/mit-license)
41
+
42
+ ## Highlight JS
43
+
44
+ Copyright (c) 2006, Ivan Sagalaev
45
+ All rights reserved.
46
+ Redistribution and use in source and binary forms, with or without
47
+ modification, are permitted provided that the following conditions are met:
48
+
49
+ * Redistributions of source code must retain the above copyright
50
+ notice, this list of conditions and the following disclaimer.
51
+ * Redistributions in binary form must reproduce the above copyright
52
+ notice, this list of conditions and the following disclaimer in the
53
+ documentation and/or other materials provided with the distribution.
54
+ * Neither the name of highlight.js nor the names of its contributors
55
+ may be used to endorse or promote products derived from this software
56
+ without specific prior written permission.
57
+
58
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
59
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
60
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61
+ DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
62
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
63
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
64
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
65
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
67
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68
+
69
+ ## Leaflet
70
+
71
+ Copyright (c) 2010-2015, Vladimir Agafonkin
72
+ Copyright (c) 2010-2011, CloudMade
73
+ All rights reserved.
74
+
75
+ Redistribution and use in source and binary forms, with or without modification, are
76
+ permitted provided that the following conditions are met:
77
+
78
+ 1. Redistributions of source code must retain the above copyright notice, this list of
79
+ conditions and the following disclaimer.
80
+
81
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
82
+ of conditions and the following disclaimer in the documentation and/or other materials
83
+ provided with the distribution.
84
+
85
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
86
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
87
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
88
+ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
89
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
90
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
92
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
93
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Readme.md CHANGED
@@ -11,6 +11,15 @@ It is not intended to be a full fledged application development toolkit. It is
11
11
  intended instead for small scripts where you just want to show some information
12
12
  without going through too much trouble.
13
13
 
14
+ ## Installation
15
+
16
+ First you need to install [electron](http://electron.atom.io/)
17
+ and make sure it's in your path. Then you can install the gem:
18
+
19
+ `gem install flammarion`
20
+
21
+ or add it to your Gemfile.
22
+
14
23
  ## Documentation
15
24
 
16
25
  The easiest way to use Flammarion, is similar to how you might use STDOUT:
@@ -61,16 +70,93 @@ f.input("Placeholder > ") {|msg| f.puts "You wrote: #{msg['text'].light_magenta}
61
70
 
62
71
  There's lots more, too. I'll write more documentation eventually.
63
72
 
64
- ## Installation
73
+ ## Screenshots / Samples
65
74
 
66
- First you need to install [Google Chrome](https://www.google.com/chrome/browser/desktop/index.html)
67
- and make sure it's in your path. Then you can install the gem:
75
+ ### Message Composer with Address Book
68
76
 
69
- `gem install flammarion`
77
+ ```ruby
78
+ f = Flammarion::Engraving.new
79
+ f.orientation = :horizontal
80
+ recipient = f.subpane("number").input("Phone Number")
81
+ text = f.input("Body", multiline:true)
82
+ f.button("Send") { send_message(recipient.to_s, text.to_s); f.status("Message Sent!")}
83
+ f.pane("contacts").puts("Contacts", replace:true)
84
+ icons = %w[thumbs-up meh-o bicycle gears star-o star] + [nil] * 5
85
+ 30.times do |i|
86
+ name = Faker::Name.name
87
+ f.pane("contacts").button(name, right_icon:icons.sample, left_icon:icons.sample) do
88
+ recipient = name
89
+ f.subpane("numer").replace(name)
90
+ end
91
+ end
92
+ ```
93
+
94
+ ![Message Sample](http://zach-capalbo.github.io/flammarion/img/messagesample.png)
95
+
96
+ ### Rake Task Runner
97
+
98
+ ```ruby
99
+ f = Flammarion::Engraving.new(exit_on_disconnect:true)
100
+ f.title "frake #{Dir.pwd}"
101
+
102
+ def run(task)
103
+ f2 = Flammarion::Engraving.new
104
+ f2.title task
105
+ f2.puts "Running #{task.light_magenta}"
106
+ Open3.popen3(task) do |i,o,e,t|
107
+ Thread.new {e.each_line{|l| f2.print l.red}}
108
+ o.each_line {|l| f2.print l}
109
+ f2.status t.value.success? ? "Done!".light_green : "Failed!".light_red
110
+ end
111
+ end
112
+
113
+ f.markdown "# Rake Tasks: "
114
+ `rake -T`.each_line do |l|
115
+ f.break
116
+ parts = l.split("#")
117
+ task = parts[0]
118
+ desc = parts[1]
119
+ f.puts desc
120
+ f.button(task) do
121
+ run(task)
122
+ end
123
+ end
124
+
125
+ f.wait_until_closed
126
+ ```
127
+
128
+ ![Frake](http://zach-capalbo.github.io/flammarion/img/frake.png)
129
+
130
+ ### Tables
131
+
132
+ ```ruby
133
+ f = Flammerion::Engraving.new
134
+ f.orientation = :horizontal
135
+ f.table([["Id", "Name", "Address"].map{|h| h.light_magenta}] + 20.times.map do |i|
136
+ [i, Faker::Name.name, Faker::Address.street_address]
137
+ end)
138
+ f.pane("sidebar").pane("side1").puts Faker::Hipster.paragraph.red
139
+ f.pane("sidebar").pane("side2").puts Faker::Hipster.paragraph.green
140
+
141
+ 3.times { f.status(Faker::Hipster.sentence.light_green)}
142
+ ```
143
+
144
+ ![Table Sample](http://zach-capalbo.github.io/flammarion/img/table.png)
70
145
 
71
- or add it to your Gemfile.
72
146
 
73
147
  ## Behind the scenes
74
148
 
75
149
  Flammarion uses Chrome to display a simple html page, and WebSockets to communicate
76
150
  between the Javascript and ruby.
151
+
152
+ # Bundled Packages
153
+
154
+ Flammarion is distributed with a bunch of useful tools to make everyone's life easier.
155
+ They are:
156
+
157
+ * [ansi up](https://github.com/drudru/ansi_up)
158
+ * [highlihgt.js](https://highlightjs.org/)
159
+ * [jquery](https://jquery.com/)
160
+ * [jquery transit](http://ricostacruz.com/jquery.transit/)
161
+ * [leaflet](http://leafletjs.com/)
162
+ * [font awesome](https://fortawesome.github.io/Font-Awesome/)
@@ -1,7 +1,5 @@
1
1
  window.$remote = require('remote')
2
2
 
3
- window.$search_for = (str) ->
4
- if window.find(str, 0, 0, 1)
5
- anchor = window.getSelection().anchorNode
6
- anchor = anchor.parentNode unless anchor.nodeType == 1
7
- anchor.scrollIntoView()
3
+ window.onkeyup = (e) ->
4
+ if e.ctrlKey and e.keyCode is 70
5
+ window.show_search_bar()
@@ -2,4 +2,10 @@
2
2
  (function() {
3
3
  window.$remote = require('remote');
4
4
 
5
+ window.onkeyup = function(e) {
6
+ if (e.ctrlKey && e.keyCode === 70) {
7
+ return window.show_search_bar();
8
+ }
9
+ };
10
+
5
11
  }).call(this);
@@ -113,12 +113,6 @@ module Flammarion
113
113
  nil
114
114
  end
115
115
 
116
- # Creates a new pane, and resizes the existing panes to fit it.
117
- # @param name [String] The name of the pane.
118
- def pane(name)
119
- return Pane.new(self, name)
120
- end
121
-
122
116
  def alert(text)
123
117
  send_json(action:'alert', text:text)
124
118
  end
@@ -3,6 +3,9 @@ module Flammarion
3
3
  f = Engraving.new(close_on_exit:true)
4
4
  f.title "Flammarion #{VERSION}"
5
5
  readme = "#{File.absolute_path(File.dirname(__FILE__))}/../../Readme.md"
6
+ license = "#{File.absolute_path(File.dirname(__FILE__))}/../../LICENSE"
6
7
  f.markdown(File.read(readme))
8
+ f.break
9
+ f.markdown(File.read(license))
7
10
  end
8
11
  end
@@ -4,9 +4,10 @@ module Flammarion
4
4
  class Pane
5
5
  attr_reader :pane_name
6
6
  include Writeable
7
- def initialize(front_end, name)
7
+ def initialize(front_end, name, options = {})
8
8
  @front_end = front_end
9
9
  @pane_name = name
10
+ @options = {}
10
11
  end
11
12
  end
12
13
  end
@@ -1,3 +1,3 @@
1
- module Flammarion
2
- VERSION = "0.0.11"
3
- end
1
+ module Flammarion
2
+ VERSION = "0.0.12"
3
+ end
@@ -176,6 +176,8 @@ module Flammarion
176
176
  # @option options [Boolean] :autoclear (false) Automatically clears the
177
177
  # input field every time the user changes the value. The callback will only
178
178
  # be called for user initiated changes, not for auto-clear changes.
179
+ # @option options [Boolean] :history (false) Keeps track of entered values,
180
+ # letting the user choose betwen them with the up and down keys.
179
181
  # @option options [String] :value Sets the starting value of the field and
180
182
  # the returned +DeferredValue+.
181
183
  # @option options [Boolean] :once (false) If true, then the input box will
@@ -299,8 +301,8 @@ module Flammarion
299
301
  return Pane.new(@front_end, name)
300
302
  end
301
303
 
302
- def pane(name)
303
- send_json({action:'addpane', name:name})
304
+ def pane(name, options = {})
305
+ send_json({action:'addpane', name:name}.merge(options))
304
306
  return Pane.new(@front_end, name)
305
307
  end
306
308
 
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type" /><meta charset="utf-8" /><meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1.0" name="viewport" /><title>Flammarion</title><link href="stylesheets/all.css" rel="stylesheet" type="text/css" /><script src="javascripts/all.js" type="text/javascript"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div class="hidden" id="toolbar"><a class="tool-button" href="#">Open</a><a class="tool-button" href="#">Save</a></div><div id="panes"><pre class="pane" id="console-default" style="height:100%"></pre></div><div class="hidden" id="dialog"><div id="content"><pre id="message">Hi World</pre><a class="full-button" href="#" id="ok">Ok</a></div></div><div id="status"><div class="left"></div><div class="center"></div><div class="right"></div></div></body></html>
1
+ <!DOCTYPE html><html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type" /><meta charset="utf-8" /><meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1.0" name="viewport" /><title>Flammarion</title><link href="stylesheets/all.css" rel="stylesheet" type="text/css" /><script src="javascripts/all.js" type="text/javascript"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div class="hidden" id="toolbar"><a class="tool-button" href="#">Open</a><a class="tool-button" href="#">Save</a></div><div id="panes"><pre class="pane" id="console-default" style="height:100%"></pre></div><div class="hidden" id="dialog"><div id="content"><pre id="message">Hi World</pre><a class="full-button" href="#" id="ok">Ok</a></div></div><div id="status"><div class="left"></div><div class="center"></div><div class="right"></div></div><div class="hidden" id="searchbar"><i class="fa fa-search"></i><input /></div></body></html>
@@ -110,28 +110,41 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
110
110
  };
111
111
 
112
112
  WSClient.prototype.resize_panes = function(data) {
113
- var allPanes, height, i, len, orientation, pane, results, target;
113
+ var allPanes, i, j, len, orientation, p_height, pane, results, target, total_weight;
114
114
  if (data.target) {
115
115
  target = this.check_target(data);
116
116
  } else {
117
117
  target = $('#panes');
118
118
  }
119
119
  allPanes = target.find('> .pane');
120
- height = (100.0 / allPanes.size()).toFixed(0) + "%";
121
120
  if (target.hasClass('horizontal')) {
122
121
  orientation = 'horizontal';
123
122
  } else {
124
123
  orientation = 'vertical';
125
124
  }
126
- console.log(target, allPanes.size(), 100.0 / allPanes.size(), height, orientation);
125
+ total_weight = ((function() {
126
+ var j, len, results;
127
+ results = [];
128
+ for (j = 0, len = allPanes.length; j < len; j++) {
129
+ i = allPanes[j];
130
+ results.push(parseFloat($(i).attr('pane-weight') || 1.0));
131
+ }
132
+ return results;
133
+ })()).reduce(function(t, s) {
134
+ return t + s;
135
+ });
136
+ p_height = function(pane) {
137
+ return (parseFloat($(pane).attr('pane-weight') || 1.0) / total_weight * 100).toFixed(0) + "%";
138
+ };
139
+ console.log(target, allPanes.size(), 100.0 / allPanes.size(), total_weight, orientation);
127
140
  results = [];
128
- for (i = 0, len = allPanes.length; i < len; i++) {
129
- pane = allPanes[i];
141
+ for (j = 0, len = allPanes.length; j < len; j++) {
142
+ pane = allPanes[j];
130
143
  if (orientation === 'horizontal') {
131
- $(pane).css("width", height);
144
+ $(pane).css("width", p_height(pane));
132
145
  results.push($(pane).css("height", '100%'));
133
146
  } else {
134
- $(pane).css("height", height);
147
+ $(pane).css("height", p_height(pane));
135
148
  results.push($(pane).css("width", '100%'));
136
149
  }
137
150
  }
@@ -224,14 +237,16 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
224
237
  return $("#console-" + data.target).html("");
225
238
  },
226
239
  addpane: function(data) {
227
- var target;
240
+ var element, target;
228
241
  if (data.target) {
229
242
  target = this.__parent.check_target(data);
230
243
  } else {
231
244
  target = $('#panes');
232
245
  }
233
246
  if (target.find("#console-" + data.name).size() === 0) {
234
- target.append("<pre class='pane full-pane' id='console-" + data.name + "'><pre>");
247
+ element = $("<pre class='pane full-pane' id='console-" + data.name + "'><pre>");
248
+ element.attr('pane-weight', data.weight || 1);
249
+ target.append(element);
235
250
  }
236
251
  return this.__parent.resize_panes(data);
237
252
  },
@@ -297,42 +312,6 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
297
312
  }
298
313
  return results;
299
314
  },
300
- button: function(data) {
301
- var class_name, element, left_icon, right_icon, target;
302
- target = this.__parent.check_target(data);
303
- class_name = data.inline ? 'inline-button' : 'full-button';
304
- left_icon = "";
305
- data.right_icon || (data.right_icon = data.icon);
306
- if (data.left_icon) {
307
- left_icon = "<i class='fa fa-" + data.left_icon + " label-icon-left'></i>";
308
- }
309
- right_icon = "";
310
- if (data.right_icon) {
311
- right_icon = "<i class='fa fa-" + data.right_icon + " label-icon-right'></i>";
312
- }
313
- element = $("<a href='#' class='" + class_name + "'>" + left_icon + (this.__parent.escape(data.label, data)) + right_icon + "</a>");
314
- element.click((function(_this) {
315
- return function() {
316
- return _this.__parent.send({
317
- id: data.id,
318
- action: 'callback',
319
- source: 'button',
320
- original_msg: data
321
- });
322
- };
323
- })(this));
324
- return target.append(element);
325
- },
326
- buttonbox: function(data) {
327
- var element, target;
328
- target = this.__parent.check_target(data);
329
- element = target.find("#console-" + data.name);
330
- if (element.size() === 0) {
331
- return target.prepend("<pre class='button-box' id='console-" + data.name + "'></pre>");
332
- } else {
333
- return element.addClass('button-box');
334
- }
335
- },
336
315
  "break": function(data) {
337
316
  var code, target;
338
317
  target = this.__parent.check_target(data);
@@ -350,104 +329,6 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
350
329
  return target.append("<pre id='console-" + data.name + "' class='subpane pane " + other_classes + "'></pre>");
351
330
  }
352
331
  },
353
- input: function(data) {
354
- var element, target;
355
- target = this.__parent.check_target(data);
356
- if (data.multiline) {
357
- element = $("<textarea placeholder='" + data.label + "' class='inline-text-input'></textarea>");
358
- } else {
359
- element = $("<input type='text' placeholder='" + data.label + "' class='inline-text-input'>");
360
- }
361
- if (data.value) {
362
- element[0].value = data.value;
363
- }
364
- element.change((function(_this) {
365
- return function() {
366
- var replaceText;
367
- if (!element.hasClass("unclicked")) {
368
- _this.__parent.send({
369
- id: data.id,
370
- action: 'callback',
371
- source: 'input',
372
- text: element[0].value,
373
- original_msg: data
374
- });
375
- if (data.once) {
376
- replaceText = _this.__parent.escape(element[0].value + "\n");
377
- if (data.keep_label) {
378
- replaceText = "" + data.label + replaceText;
379
- }
380
- element.replaceWith(replaceText);
381
- }
382
- if (data.autoclear) {
383
- return element[0].value = "";
384
- }
385
- }
386
- };
387
- })(this));
388
- target.append(element);
389
- if (data.focus) {
390
- return element.focus();
391
- }
392
- },
393
- checkbox: function(data) {
394
- var element, target;
395
- target = this.__parent.check_target(data);
396
- element = $("<label class='inline-checkbox'><input type='checkbox'><span>" + (this.__parent.escape(data.label, data)) + "</span></label>'");
397
- if (data.value) {
398
- element.find('input').attr("checked", true);
399
- element.addClass("checked");
400
- }
401
- element.change((function(_this) {
402
- return function(e) {
403
- element.toggleClass("checked", element.find('input').prop('checked'));
404
- return _this.__parent.send({
405
- id: data.id,
406
- action: 'callback',
407
- source: 'input',
408
- checked: element.find('input').prop('checked'),
409
- original_msg: data
410
- });
411
- };
412
- })(this));
413
- element.click((function(_this) {
414
- return function(e) {
415
- var all_boxes, start, stop;
416
- if (e.shiftKey && _this.__lastChecked) {
417
- all_boxes = $('.inline-checkbox');
418
- start = all_boxes.index(_this.__lastChecked);
419
- stop = all_boxes.index(element);
420
- console.log(start, stop);
421
- all_boxes.slice(Math.min(start, stop), Math.max(start, stop) + 1).find('input').prop("checked", _this.__lastChecked.find('input').prop("checked"));
422
- return all_boxes.change();
423
- } else {
424
- return _this.__lastChecked = element;
425
- }
426
- };
427
- })(this));
428
- return target.append(element);
429
- },
430
- dropdown: function(data) {
431
- var element, i, item, len, ref, target;
432
- target = this.__parent.check_target(data);
433
- element = $("<select class='inline-dropdown' name='" + data.id + "'></select>");
434
- ref = data.options;
435
- for (i = 0, len = ref.length; i < len; i++) {
436
- item = ref[i];
437
- element.append($("<option>" + item + "</option>"));
438
- }
439
- element.change((function(_this) {
440
- return function(e) {
441
- return _this.__parent.send({
442
- id: data.id,
443
- action: 'callback',
444
- source: 'dropdown',
445
- text: element.find('option:selected').text()
446
- });
447
- };
448
- })(this));
449
- return this.__parent.add(element, target, data);
450
- },
451
332
  alert: function(data) {
452
333
  return alert(data.text);
453
334
  },