famalam 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bd3085fa8fcb3bf78f3b7f9f431e799db0e1565d40a1c6502f1e5306f619917
4
- data.tar.gz: 2d2f4038b3192754fd2f7021c13aecc756d82d5d1861bf2ef1f8f124716adfa4
3
+ metadata.gz: 15842d54b4123e74f02c913e6075cc9d74bcbd71fdb449883e74cf7c00e3236b
4
+ data.tar.gz: 89521d9e9c1894ae915b8cd6ac7c071efadd20357a4b62de3c877ab484111738
5
5
  SHA512:
6
- metadata.gz: b4779f52a32333cff91752a526d74a451c642f83b66e0a78c744eadf39056cf4f035373174d6fd357e3d8960baa543f15b0abe92b1921604737281402310b8b3
7
- data.tar.gz: 6e0ea7f5efe9c30a7f9e965e4f1911fcfff9fc89dcecd7ed110b2dd454612e29d71c5ae22f05570723f496bc092eae72688811c31088ab77516850a07dde9ca8
6
+ metadata.gz: 0e4efdebbd3dd701108b0330a983077bdfac247e1a0946d9e66c91d9240c1064d13091b95856ae6b857cb6f16916a29e41cda954fb5a17ca148aea14512d4d0e
7
+ data.tar.gz: 932b9e080668bc7c146f2bfff9ed47992ed44ebdd39fa7a54e0a839952a6dee27f3f2683eeb432c46dc4766e3146e10990d260b3de908c7e4dbccf4b68a4f38f
data/README.md CHANGED
@@ -1,2 +1,5 @@
1
1
  # FAMalam
2
- FAMalam is a front end web interface for FAM
2
+ > FAMalam is a front end web interface for FAM
3
+
4
+ Still a work in progress, not very responsive.
5
+ ![](./screenshot.png)
@@ -1,10 +1,12 @@
1
+ require 'fam'
2
+ require 'haml'
3
+
1
4
  module FAMalam
2
- VERSIONS = { :major => 0, :minor => 0, :tiny => 1 }
5
+ VERSIONS = { :major => 0, :minor => 1, :tiny => 0 }
3
6
 
4
7
  def self.version *args
5
8
  VERSIONS.flatten.select.with_index { |val, i| i.odd? }.join '.'
6
9
  end
7
10
  end
8
11
 
9
- Dir["#{File.dirname __FILE__}/fam/*.rb"].each { |f| require f }
10
- Dir["#{File.dirname __FILE__}/fam/**/*.rb"].each { |f| require f }
12
+ Dir["#{File.dirname __FILE__}/famalam/*.rb"].each { |f| require f }
@@ -0,0 +1,33 @@
1
+ FAM::Machine::CPU.class_eval do
2
+ def cpu_output out, ascii
3
+ ascii == :PLAIN ? out.to_s : out.chr
4
+ end
5
+
6
+ def inject_input i
7
+ @inject = i
8
+ end
9
+
10
+ def cpu_input
11
+ @inject || -1
12
+ end
13
+
14
+ def step parsed
15
+ @parsed = parsed
16
+ return {:state => 'done'} if @tree_index >= parsed.tree.size || @halted
17
+ @tree_index += 1
18
+ node = parsed[@tree_index]
19
+ if parsed[@tree_index].base_name == 'InNode' && !@rerun
20
+ @tree_index -= 1
21
+ @rerun = true
22
+ return {:state => 'running', :input => true, :output => @outputting}
23
+ end
24
+
25
+ @rerun = false
26
+ status = execute node
27
+ if status == :STOP
28
+ @halted = true
29
+ return {:state => 'done'}
30
+ end
31
+ {:state => 'running', :input => false, :output => @outputting}
32
+ end
33
+ end
@@ -0,0 +1,112 @@
1
+ const pad = (n, width, char) => {
2
+ char = char || '0';
3
+ n = n + '';
4
+ return n.length >= width ? n : new Array(width - n.length + 1).join(char) + n;
5
+ }
6
+
7
+ const draw_step = (step) => {
8
+ if (step['ERROR']) {
9
+ $('#alloc').removeAttr('disabled');
10
+ return;
11
+ }
12
+ $('#alloc').prop('disabled', true);
13
+ for (let i = 0; i < step['ram'].length; i++) {
14
+ let elem = $('.address:nth-child(' + (i + 1) + ') > .value')
15
+ if (elem.html() != '' + step['ram'][i]) {
16
+ elem.empty();
17
+ elem.html(step['ram'][i])
18
+ elem.stop().css({ backgroundColor: '#ffff9c' });
19
+ elem.animate({ backgroundColor: '#ffffff' }, 3200 / get_clock());
20
+ }
21
+ }
22
+
23
+ let reg_elem = $('.cpu .registers');
24
+ reg_elem.empty();
25
+ for (let i = 0; i < Object.keys(step['registers']).length; i++) {
26
+ reg_elem.append(
27
+ `<div class="register">
28
+ <div class="name">`
29
+ + Object.keys(step['registers'])[i]
30
+ + `</div>
31
+ <div class="value">`
32
+ + Object.values(step['registers'])[i]
33
+ + `</div>
34
+ </div>`);
35
+ }
36
+
37
+ let out_elem = $('.cpu .output');
38
+ if (step['output'] != '') {
39
+ out_elem.append(`<div>` + step['output'] + `</div>`);
40
+ out_elem.animate({ scrollTop: out_elem.prop("scrollHeight")}, 100);
41
+ }
42
+ }
43
+
44
+ let get_alloc = () => {
45
+ return $('#alloc').val() - 0;
46
+ }
47
+
48
+ draw_ram = () => {
49
+ let alloc = get_alloc();
50
+ $('.ram').empty();
51
+ for (let i = 0; i < get_alloc(); i++) {
52
+ $('.ram').append(`
53
+ <div class="address">
54
+ <div class="number">` + pad(i, 3) + `</div>
55
+ <div class="value">NULL</div>
56
+ </div>
57
+ `);
58
+ $('.address:nth-child(' + (i + 1) + ') .value').css({
59
+ width: (500 / alloc) + 'em'
60
+ });
61
+ $('.address:nth-child(' + (i + 1) + ') .number').css({
62
+ width: (200 / alloc) + 'em'
63
+ });
64
+ }
65
+ }
66
+ $('#alloc').change(draw_ram);
67
+
68
+ $(document).ready(() => {
69
+ // disable inputs
70
+ $('input[name=input]').prop('disabled', true);
71
+ // Initiate RAM
72
+ draw_ram();
73
+ });
74
+
75
+ // Textbox tab handling
76
+ let tab_level = 0;
77
+ $(document).delegate('#code', 'keydown', function(e) {
78
+ let tab = " ";
79
+
80
+ let key_code = e.keyCode || e.which;
81
+ if (key_code == 9 && tab) { // Tab key
82
+ let start = this.selectionStart;
83
+ let end = this.selectionEnd;
84
+ $(this).val($(this).val().substring(0, start)
85
+ + tab
86
+ + $(this).val().substring(end));
87
+ this.selectionStart = this.selectionEnd = start + tab.length;
88
+ tab_level++;
89
+ return false
90
+ }
91
+ if (key_code == 13) { // Autotab on enter
92
+ let start = this.selectionStart;
93
+ let end = this.selectionEnd;
94
+ $(this).val($(this).val().substring(0, start)
95
+ + "\n"
96
+ + (new Array(tab.length * tab_level + 1).join(tab))
97
+ + $(this).val().substring(end));
98
+ this.selectionStart = this.selectionEnd = 1 + start + tab.length * tab_level;
99
+ return false;
100
+ }
101
+ if (key_code == 8) { // Backspace key
102
+ let start = this.selectionStart;
103
+ let end = this.selectionEnd;
104
+ if ($(this).val().substring(start, start - tab.length) == tab) {
105
+ $(this).val($(this).val().substring(0, start-tab.length)
106
+ + $(this).val().substring(end));
107
+ this.selectionStart = this.selectionEnd = start - tab.length;
108
+ if (tab_level > 0) { tab_level--; }
109
+ return false;
110
+ }
111
+ }
112
+ });
@@ -0,0 +1,99 @@
1
+ const get_clock = () => {
2
+ let c = Math.abs($('input[name=clock]').val() - 0) + 0.001;
3
+ if (c > 21) {
4
+ $('input[name=clock]').val("20");
5
+ get_clock();
6
+ }
7
+ return c;
8
+ }
9
+
10
+ const handle_input = interval => {
11
+ interval.disable();
12
+ let input_box = $('input[name=input]')
13
+ input_box.prop('disabled', false);
14
+ input_box.focus();
15
+
16
+ let input;
17
+ const wait = () => {
18
+ console.log('waiting...');
19
+ if (!input_box.val()) window.setTimeout(wait, 5);
20
+ else {
21
+ input = input_box.val();
22
+ interval.enable();
23
+ input_box
24
+ .val('')
25
+ .attr('placeholder', input)
26
+ .blur()
27
+ .prop('disabled', true);
28
+
29
+ $.ajax({
30
+ type: 'POST',
31
+ url: '/program/input',
32
+ async: false,
33
+ data: { input: input + " ...in" },
34
+ error: (s, e) => {
35
+ console.log(
36
+ 'An error occured in posting input!\nERROR: ',
37
+ s, '\n\n', e
38
+ );
39
+ }
40
+ });
41
+ return;
42
+ }
43
+ }
44
+ wait();
45
+ input_box.attr('placeholder', '');
46
+ return input;
47
+ }
48
+
49
+ class ClockInterval {
50
+ constructor(f, speed) {
51
+ this.lambda = f;
52
+ this.speed = speed;
53
+ this.interval = null;
54
+ }
55
+ enable(speed=this.speed) {
56
+ this.speed = speed;
57
+ this.interval = window.setInterval(this.lambda, (1.0 / speed) * 1000);
58
+ }
59
+ disable() {
60
+ window.clearInterval(this.interval);
61
+ }
62
+ }
63
+
64
+
65
+ const stepper = () => {
66
+ let clock = get_clock();
67
+ let step_interval;
68
+
69
+ const response = () => {
70
+ let step = {};
71
+ $.ajax({
72
+ url: "/program/step.json",
73
+ async: false,
74
+ dataType: 'json',
75
+ success: (data) => {
76
+ step = data;
77
+ }
78
+ });
79
+ if (step['ERROR']) step_interval.disable();
80
+ if (step['inputting']) handle_input(step_interval);
81
+ return step;
82
+ }
83
+
84
+ const update = () => {
85
+ let step = response();
86
+ console.log("Errors: ", step['ERROR']);
87
+ console.log("Step: ", step);
88
+ draw_step(step);
89
+ }
90
+
91
+
92
+ step_interval = new ClockInterval(update, clock)
93
+ step_interval.enable();
94
+ $('input[name=clock]').on("change paste keyup", () => {
95
+ clock = get_clock();
96
+ step_interval.disable();
97
+ step_interval.enable(clock);
98
+ });
99
+ }
@@ -0,0 +1,28 @@
1
+ $(document).ready(() => {
2
+ let clock = get_clock();
3
+
4
+ $('form').submit(() => {
5
+ $.ajax({
6
+ type: 'POST',
7
+ url: '/program',
8
+ async: false,
9
+ data: {
10
+ title: $('input[name=title]').val(),
11
+ code: $('textarea[name=code]').val(),
12
+ alloc: get_alloc(),
13
+ clock: clock,
14
+ },
15
+ error: () => {
16
+ console.log('Code could not be sent!');
17
+ },
18
+ success: (m) => {
19
+ stepper();
20
+ }
21
+ });
22
+ return false;
23
+ });
24
+ $('#submit').click(() => {
25
+ $('form').submit();
26
+ return false;
27
+ });
28
+ })
@@ -0,0 +1,68 @@
1
+ .cpu {
2
+ float: left;
3
+ width: 10em;
4
+ border: 1px dotted #ccc;
5
+ border-radius: 4px;
6
+ padding: 1em;
7
+ }
8
+
9
+ .cpu .input, .cpu .input input {
10
+ width: 100%;
11
+ padding: 0;
12
+ margin: 0;
13
+ }
14
+ .cpu .CU {
15
+ width: calc(100% - 8px);
16
+ padding: 4px;
17
+ margin: 5px 0;
18
+ border: 1px solid #e1e1e1;
19
+ border-radius: 4px;
20
+ min-height: 1em;
21
+ }
22
+
23
+ .cpu .registers, .cpu .output {
24
+ margin: 5px 0;
25
+ padding: 0 3px;
26
+ border: 1px solid #e1e1e1;
27
+ border-radius: 4px;
28
+ min-height: 1em;
29
+ }
30
+ .cpu .register {
31
+ margin: 4px 0;
32
+ border: 1px solid #e1e1e1;
33
+ border-radius: 3px;
34
+ padding: 0;
35
+ font-family: 'FantasqueSansMonoRegular', monospace;
36
+ }
37
+ .cpu .register .name {
38
+ display: inline-block;
39
+ text-align: right;
40
+ padding: 2px 4px 2px 0;
41
+ border-right: 1px solid #e1e1e1;
42
+ width: 2.4em;
43
+ }
44
+ .cpu .register .value {
45
+ display: inline-block;
46
+ }
47
+
48
+ .cpu .output {
49
+ overflow-y: scroll;
50
+ padding: 0;
51
+ min-height: 2em;
52
+ max-height: 4em;
53
+ }
54
+ .cpu .output div {
55
+ padding: 0 0.5em;
56
+ font-family: 'FantasqueSansMonoRegular', monospace;
57
+ }
58
+ .cpu .output div:nth-child(2n) {
59
+ background: #f4f4f4;
60
+ }
61
+
62
+ .cpu .input input {
63
+ width: calc(100% - 4px);
64
+ margin: 5px 0 0 0;
65
+ padding: 3px 2px;
66
+ border: 1px solid #e1e1e1;
67
+ border-radius: 4px;
68
+ }
@@ -0,0 +1,29 @@
1
+ @import url('https://fontlibrary.org/face/fantasque-sans-mono');
2
+ @import url('https://fonts.googleapis.com/css?family=Rubik:400,400i,700');
3
+
4
+ * { outline: none; }
5
+ body, html {
6
+ padding: 0;
7
+ margin: 0;
8
+ overflow-y: hidden;
9
+ font-size: 16px;
10
+ font-weight: 400;
11
+ font-family: 'Rubik', sans-serif;
12
+ color: #222;
13
+ }
14
+
15
+
16
+ #post, .computer {
17
+ height: calc(100vh - 5rem);
18
+ margin: 1em;
19
+ }
20
+
21
+ #post {
22
+ width: 14em;
23
+ float: left;
24
+ padding: 1.5em;
25
+ }
26
+ .computer {
27
+ width: 44em;
28
+ float: right;
29
+ }
@@ -0,0 +1,33 @@
1
+ .ram {
2
+ width: 31em;
3
+ background: none;
4
+ padding: 5px;
5
+ float: right;
6
+ overflow: auto;
7
+ text-align: right;
8
+ }
9
+ .address {
10
+ display: inline-block;
11
+ background-color: rgba(255, 255, 255, 0.8);
12
+ border: 1px solid #ccc;
13
+ border-radius: 3px;
14
+ margin: 3px 1px;
15
+ font-size: 0.6em;
16
+ font-family: 'FantasqueSansMonoRegular', monospace;
17
+ text-align: center;
18
+ }
19
+
20
+ .address .value, .address .number {
21
+ padding: 4px;
22
+ display: inline-block;
23
+ }
24
+
25
+ .address .number {
26
+ float: left;
27
+ border-right: 1px solid #ccc;
28
+ }
29
+
30
+ .address .value {
31
+ border-top-right-radius: 4px;
32
+ border-bottom-right-radius: 4px;
33
+ }
@@ -0,0 +1,53 @@
1
+ #post {
2
+ display: inline-block;
3
+ border: 1px solid #ccc;
4
+ border-radius: 5px;
5
+ }
6
+
7
+ #post input, #post #code, #post select {
8
+ display: block;
9
+ margin: 0 0 1em 0;
10
+ width: 100%;
11
+ font-family: 'Rubik', sans-serif;
12
+ }
13
+ #post input:last-child {
14
+ margin: 0;
15
+ }
16
+ #post input[name=title] {
17
+ border: none;
18
+ border-bottom: 1px dotted #ccc;
19
+ font-size: 1.5em;
20
+ }
21
+
22
+ #post #code {
23
+ padding: 0.5em;
24
+ width: calc(100% - 1em);
25
+ margin: 0 0 1em 0;
26
+ resize: none;
27
+ height: calc(100% - 13em);
28
+ font-family: 'FantasqueSansMonoRegular', monospace;
29
+ border: 1px solid #e1e1e1;
30
+ border-radius: 4px;
31
+ }
32
+
33
+ #post select {
34
+ border: 1px solid #e1e1e1;
35
+ border-radius: 4px;
36
+ background: none;
37
+ }
38
+
39
+ #post input[type=submit] {
40
+ background: #fff;
41
+ color: #333;
42
+ border-radius: 4px;
43
+ border: 1px solid #e1e1e1;
44
+ cursor: pointer;
45
+ transition: all .1s ease-in-out;
46
+ }
47
+ #post input[type=submit]:active {
48
+ background: #f3f3f3;
49
+ border: 1px solid #ccc;
50
+ }
51
+ #post input[type=submit]:hover {
52
+ background: #f8f8f8;
53
+ }
@@ -0,0 +1,8 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title FAMalam
5
+ %link{:rel => 'stylesheet', :type => 'text/css', :href => '/styles/master.css'}
6
+ %body
7
+ Create a new program:
8
+ %a{:href => '/program'} New
@@ -0,0 +1,79 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title FAMalam
5
+ %link{:rel => "stylesheet", :type => "text/css", :href => "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css"}
6
+ %link{:rel => "stylesheet", :type => "text/css", :href => "/styles/master.css"}
7
+ %link{:rel => "stylesheet", :type => "text/css", :href => "/styles/submit.css"}
8
+ %link{:rel => "stylesheet", :type => "text/css", :href => "/styles/cpu.css"}
9
+ %link{:rel => "stylesheet", :type => "text/css", :href => "/styles/ram.css"}
10
+ %script{:type=> "text/javascript", :src => "https://code.jquery.com/jquery-3.3.1.min.js"}
11
+ %script{:type=> "text/javascript", :src => "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"}
12
+ %body
13
+ %form{:id => "post", :action => "/program", :method => "POST"}
14
+ %input{:type => "text", :autofocus => "", :autocomplete => "off", :name => "title", :placeholder => "Project Title"}
15
+ %datalist{:id => "tickmarks"}
16
+ %option{:value => "2", :label => "2"}
17
+ %option{:value => "4"}
18
+ %option{:value => "6"}
19
+ %option{:value => "8"}
20
+ %option{:value => "10", :label => "10"}
21
+ %option{:value => "12"}
22
+ %option{:value => "14"}
23
+ %option{:value => "16"}
24
+ %option{:value => "18"}
25
+ %option{:value => "20", :label => "20"}
26
+ %input{:type => "range", :name => "clock",
27
+ :value => "1", :list => "tickmarks",
28
+ :max => "20", :min => "2", :step => "1"}
29
+
30
+
31
+ %textarea{:name => "code", :id => "code",
32
+ :autocomplete => "off",
33
+ :autocorrect => "off",
34
+ :autocapitalize => "off",
35
+ :spellcheck => "false"}
36
+ = preserve do
37
+ :escaped
38
+ STORE 55 : @0
39
+ DATA dyn : 0b01101
40
+ LOAD -0xf : &DAT
41
+ LOAD &DAT : &ACC
42
+
43
+ LOOP:
44
+ ADD 1 : &ACC
45
+ OUT &ACC
46
+ STORE &ACC : dyn
47
+
48
+ MORE &ACC : 29
49
+ | GOTO END
50
+ | GOTO LOOP
51
+
52
+ END: HALT 0
53
+
54
+
55
+
56
+ %select{:id => "alloc"}
57
+ %option{:value => "120", :selected => ""}120B
58
+ %option{:value => "94"}94B
59
+ %option{:value => "64"}64B
60
+ %option{:value => "32"}32B
61
+ %input{:type => "submit", :id => "submit", :value => "Run"}
62
+
63
+ .computer
64
+ .cpu
65
+ %span Control Unit
66
+ .CU
67
+ %span Registers
68
+ .registers
69
+ %span Output
70
+ .output
71
+ %span Input
72
+ .input
73
+ %input{:type => "text",
74
+ :autofocus => "", :autocomplete => "off",
75
+ :name => "input", :placeholder => "Enter value"}
76
+ .ram
77
+ %script{:type=> "text/javascript", :src => "/scripts/graphics.js"}
78
+ %script{:type=> "text/javascript", :src => "/scripts/step.js"}
79
+ %script{:type=> "text/javascript", :src => "/scripts/submitter.js"}
metadata CHANGED
@@ -1,26 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: famalam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Demonstrandum
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-13 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2018-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fam
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: haml
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 5.0.4
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '5.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 5.0.4
53
+ - !ruby/object:Gem::Dependency
54
+ name: sinatra
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 2.0.1
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '2.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.0.1
13
73
  description: FAMalam is a front end web interface for FAM
14
74
  email: knutsen@jetspace.co
15
- executables:
16
- - famalam
75
+ executables: []
17
76
  extensions: []
18
77
  extra_rdoc_files: []
19
78
  files:
20
79
  - LICENSE
21
80
  - README.md
22
- - bin/famalam
23
81
  - lib/famalam.rb
82
+ - lib/famalam/patches.rb
83
+ - public/scripts/graphics.js
84
+ - public/scripts/step.js
85
+ - public/scripts/submitter.js
86
+ - public/styles/cpu.css
87
+ - public/styles/master.css
88
+ - public/styles/ram.css
89
+ - public/styles/submit.css
90
+ - views/index.haml
91
+ - views/program.haml
24
92
  homepage: https://github.com/Demonstrandum/FAM
25
93
  licenses:
26
94
  - GPL-2.0
@@ -1 +0,0 @@
1
- #!/usr/bin/env ruby