ruby_uml_class 0.1.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.
data/lib/js/main.js ADDED
@@ -0,0 +1,463 @@
1
+ // main.js
2
+
3
+ var $ws = null;
4
+ var $auto_scroll = true;
5
+ var dialog = null;
6
+ var dialog_timeout = null;
7
+
8
+ function open_dialog(msg, timeout = 0) {
9
+ console.log("msg=" + msg);
10
+ $("#msg_text").html(msg);
11
+ d = $("#msg_dialog").dialog({
12
+ modal: true
13
+ , show: "slide" //表示時のアニメーション
14
+ , hide: "slide" //閉じた時のアニメーション
15
+ , title: "Message" //ダイアログのタイトル
16
+ , width: 500 //ダイアログの横幅
17
+ , height: 300 //ダイアログの高さ
18
+ , resizable: true //リサイズ可
19
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
20
+ , draggable: true //ダイアログの移動を可に
21
+ , buttons: {
22
+ "OK": function () { //Cancelボタン
23
+ if (dialog_timeout != null) {
24
+ clearTimeout(dialog_timeout);
25
+ }
26
+ $(this).dialog("close");
27
+ }
28
+ }
29
+ });
30
+ if (timeout != 0) {
31
+ dialog_timeout = setTimeout(function () {
32
+ d.dialog("close");
33
+ }, timeout);
34
+ }
35
+ }
36
+
37
+ function open_dialog_org(msg) {
38
+ var top = window.screenTop + 10;
39
+ var left = window.screenLeft + 10;
40
+ if (dialog != null) {
41
+ dialog.close();
42
+ }
43
+ var dialog = window.open(
44
+ "/open_dialog?msg=" + msg,
45
+ "pop",
46
+ "width=300, height=100, left=" + left + ", top=" + top
47
+ );
48
+ console.log("open dialog dialog=" + dialog);
49
+ if (dialog == null) {
50
+ console.log("open dialog retry");
51
+ setTimeout(function () {
52
+ open_dialog(msg);
53
+ }, 1000);
54
+ } else {
55
+ dialog.focus();
56
+ }
57
+ }
58
+
59
+ function server_connect(url) {
60
+ var ws = new WebSocket(url);
61
+ ws.onopen = function () {
62
+ // Web Socket is connected. You can send data by send() method.
63
+ ws.send("message to send");
64
+ };
65
+ ws.onmessage = function (evt) {
66
+ //alert(evt.data);
67
+
68
+ if (evt.data.match(/^startup:/)) {
69
+ file_name = evt.data.replace(/^startup:/, "");
70
+ }
71
+ else if (evt.data.match(/^app_end:normal/)) {
72
+ open_dialog("終了しました");
73
+ }
74
+ else if (evt.data.match(/^app_end:stop/)) {
75
+ open_dialog("中止しました");
76
+ }
77
+ else if (evt.data.match(/^app_end:error/)) {
78
+ open_dialog("<font color='red'>エラーが発生しました</font>");
79
+ }
80
+ else if (evt.data.match(/^popup:/)) {
81
+ open_dialog(evt.data.replace(/^popup:/, ""), 3000);
82
+ } else {
83
+ var log = "<li>" + evt.data + "</li>";
84
+ $('#log').append(log);
85
+ if ($auto_scroll) {
86
+ $('.outarea').scrollTop($('.outarea').get(0).scrollHeight);
87
+ }
88
+ }
89
+ };
90
+ ws.onclose = function () {
91
+ alert("アプリケーションが終了しました!!");
92
+ $(window).unbind("beforeunload");
93
+ //window.open('about:blank','_self').close();
94
+ window.close();
95
+ };
96
+ $ws = ws;
97
+ }
98
+
99
+ function send_message(msg) {
100
+ if ($ws != null) {
101
+ $ws.send(msg);
102
+ }
103
+ }
104
+
105
+ function autocomp(id, file_kind) {
106
+ $("#" + id).autocomplete({
107
+ autoFocus: true,
108
+ minLength: 0,
109
+ delay: 0,
110
+ select: function (event, ui) {
111
+ //console.log(ui.item.value);
112
+ jQuery("#" + id).val(ui.item.value);
113
+ //jQuery(this).autocomplete("search", "");
114
+ $(this).keydown();
115
+ },
116
+ source: function (req, resp) {
117
+ $.ajax({
118
+ url: "search?path=" + $("#" + id).val() + "&kind=" + file_kind,
119
+ type: "GET",
120
+ cache: false,
121
+ dataType: "json",
122
+ data: {
123
+ param1: req.term
124
+ },
125
+ success: function (o) {
126
+ resp(o);
127
+ },
128
+ error: function (xhr, ts, err) {
129
+ resp(['']);
130
+ }
131
+ });
132
+
133
+ }
134
+ }).focus(function () {
135
+ //jQuery(this).autocomplete("search", "");
136
+ $(this).keydown();
137
+ });
138
+ }
139
+
140
+ function autocomp_history(id, file_name) {
141
+ $("#" + id).autocomplete({
142
+ autoFocus: true,
143
+ minLength: 0,
144
+ delay: 0,
145
+ select: function (event, ui) {
146
+ jQuery("#" + id).val(ui.item.value);
147
+ $(this).keydown();
148
+ },
149
+ source: function (req, resp) {
150
+ $.ajax({
151
+ url: "history/" + file_name,
152
+ type: "POST",
153
+ cache: false,
154
+ dataType: "json",
155
+ data: {
156
+ param1: req.term
157
+ },
158
+ success: function (o) {
159
+ resp(o);
160
+ },
161
+ error: function (xhr, ts, err) {
162
+ resp(['']);
163
+ }
164
+ });
165
+
166
+ }
167
+ }).focus(function () {
168
+ $(this).keydown();
169
+ });
170
+ }
171
+
172
+ function select_file_dialog(search_id, file_kind, dialog_id, select_file, file_name) {
173
+ $("#" + select_file).click(function () {
174
+ autocomp(search_id, file_kind);
175
+ $(".ui-autocomplete").css("z-index", 1000);
176
+ console.log("name=" + $("#" + file_name).val());
177
+ $("#" + search_id).val($("#" + file_name).val());
178
+ $("#" + dialog_id).dialog({
179
+ modal: true
180
+ , show: "slide" //表示時のアニメーション
181
+ , hide: "explode" //閉じた時のアニメーション
182
+ , title: "Select File" //ダイアログのタイトル
183
+ , width: 580 //ダイアログの横幅
184
+ , height: 400 //ダイアログの高さ
185
+ , resizable: true //リサイズ可
186
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
187
+ , draggable: true //ダイアログの移動を可に
188
+ , buttons: {
189
+ "OK": function () { //OKボタン
190
+ $("#" + file_name).val($("#" + search_id).val());
191
+ $(this).dialog("close");
192
+ $("#" + search_id).autocomplete("destroy");
193
+ },
194
+ "Cancel": function () { //Cancelボタン
195
+ $(this).dialog("close");
196
+ $("#" + search_id).autocomplete("destroy");
197
+ }
198
+ }
199
+ });
200
+ });
201
+ }
202
+
203
+ function setting_dialog(open_id, dialog_id, json_file) {
204
+ var version;
205
+ $("#" + open_id).click(function () {
206
+ $("#" + dialog_id).val = $(function () {
207
+ $("dl#wrap").empty();
208
+ $.getJSON(json_file, function (s) {
209
+ version = s["version"];
210
+ for (var i in s["setting_list"]) {
211
+ if (s["setting_list"][i].type == "input") {
212
+ var h = "<table><tr>"
213
+ + "<td class='setting_name'>" + s["setting_list"][i].description + "</td>"
214
+ + "<td><input class='setting_value' type='text' " + "id=" + s["setting_list"][i].name + "_value " + "value=" + "'" + s["setting_list"][i].value + "'" + ">"
215
+ + "</td></tr></table>"
216
+ $("dl#wrap").append(h);
217
+ } else if (s["setting_list"][i].type == "checkbox") {
218
+ var h = "<table><tr>";
219
+ h += "<td class='setting_name'>" + s["setting_list"][i].description + "</td>";
220
+ if (s["setting_list"][i].value == true) {
221
+ h += "<td><input class='setting_checkbox' type='checkbox' " + "id=" + s["setting_list"][i].name + "_value checked ></td>";
222
+ } else {
223
+ h += "<td><input class='setting_checkbox' type='checkbox' " + "id=" + s["setting_list"][i].name + "_value ></td>";
224
+ }
225
+ h += "</tr></table>";
226
+ $("dl#wrap").append(h);
227
+ } else if (s["setting_list"][i].type == "select") {
228
+ var h = "<table><tr>";
229
+ h += "<td class='setting_name'>" + s["setting_list"][i].description + "</td>";
230
+ h += "<td> <select class='setting_value' id=" + s["setting_list"][i].name + "_value " + ">";
231
+ s["setting_list"][i].select.forEach(e => {
232
+ if (e == s["setting_list"][i].value) {
233
+ h += "<option value=" + e + " selected >" + e + "</option>";
234
+ } else {
235
+ h += "<option value=" + e + ">" + e + "</option>";
236
+ }
237
+ });
238
+ h += "</select></td>";
239
+ h += "</tr></table>";
240
+ $("dl#wrap").append(h);
241
+ } else {
242
+ //console.log("type=" + s["setting_list"][i].type);
243
+ }
244
+ }
245
+ });
246
+ });
247
+ $("#" + dialog_id).dialog({
248
+ modal: true
249
+ , show: "slide" //表示時のアニメーション
250
+ , hide: "explode" //閉じた時のアニメーション
251
+ , title: "Setting" //ダイアログのタイトル
252
+ , width: 580 //ダイアログの横幅
253
+ , height: 400 //ダイアログの高さ
254
+ , resizable: true //リサイズ可
255
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
256
+ , draggable: true //ダイアログの移動を可に
257
+ , buttons: {
258
+ "OK": function () { //OKボタン
259
+ var json_obj = {};
260
+ var json_data = [];
261
+ $.getJSON(json_file, function (s) {
262
+ json_obj["version"] = s["version"];
263
+ for (var i in s["setting_list"]) {
264
+ //console.log(s["setting_list"][i].name);
265
+ if (s["setting_list"][i].type == "input") {
266
+ var data = {};
267
+ data["name"] = s["setting_list"][i].name;
268
+ data["value"] = $("#" + s["setting_list"][i].name + "_value").val();
269
+ data["type"] = s["setting_list"][i].type;
270
+ data["select"] = s["setting_list"][i].select;
271
+ data["description"] = s["setting_list"][i].description;
272
+ json_data.push(data);
273
+ }
274
+ else if (s["setting_list"][i].type == "checkbox") {
275
+ var data = {};
276
+ data["name"] = s["setting_list"][i].name;
277
+ if ($("#" + s["setting_list"][i].name + "_value:checked").val() == "on") {
278
+ data["value"] = true;
279
+ } else {
280
+ data["value"] = false;
281
+ }
282
+ data["type"] = s["setting_list"][i].type;
283
+ data["select"] = s["setting_list"][i].select;
284
+ data["description"] = s["setting_list"][i].description;
285
+ json_data.push(data);
286
+ } else if (s["setting_list"][i].type == "select") {
287
+ var data = {};
288
+ data["name"] = s["setting_list"][i].name;
289
+ data["value"] = $("#" + s["setting_list"][i].name + "_value" + " option:selected").val();
290
+ data["type"] = s["setting_list"][i].type;
291
+ data["select"] = s["setting_list"][i].select;
292
+ data["description"] = s["setting_list"][i].description;
293
+ json_data.push(data);
294
+ } else {
295
+ //console.log("type=" + s["setting_list"][i].type);
296
+ }
297
+ }
298
+ // Jsonデータをサーバに送信
299
+ json_obj["setting_list"] = json_data;
300
+ $ws.send("setting:" + JSON.stringify(json_obj));
301
+ });
302
+ $(this).dialog("close");
303
+ },
304
+ "Cancel": function () { //Cancelボタン
305
+ $(this).dialog("close");
306
+ }
307
+ }
308
+ });
309
+ });
310
+ }
311
+
312
+ // 設定読み込み
313
+ function load_setting(open_id) {
314
+ document.getElementById(open_id).onclick = async () => {
315
+ [fileHandle] = await window.showOpenFilePicker();
316
+ const file = await fileHandle.getFile();
317
+ const json_data = await file.text();
318
+ console.log(json_data);
319
+ // Jsonデータをサーバに送信
320
+ $ws.send("setting:" + json_data);
321
+ };
322
+ }
323
+
324
+ // 設定保存
325
+ function save_setting(open_id, json_file) {
326
+ document.getElementById(open_id).onclick = async () => {
327
+ var json_data = ""
328
+ $.ajax({
329
+ // jsonの読み込み
330
+ type: "GET",
331
+ url: json_file, // ファイルパス(相対パス)
332
+ dataType: "json", // ファイル形式
333
+ async: false // 非同期通信フラグ
334
+ }).then(
335
+ function (json) {
336
+ // 読み込み成功時の処理
337
+ json_data = JSON.stringify(json, null, 2);
338
+ console.log("json=" + json_data);
339
+ },
340
+ function () {
341
+ // 読み込み失敗時の処理
342
+ console.log("読み込みに失敗しました");
343
+ }
344
+ );
345
+ // Jsonを保存
346
+ const opts = {
347
+ suggestedName: 'setting.json',
348
+ types: [{
349
+ description: 'Text file',
350
+ accept: { 'text/plain': ['.json'] },
351
+ }],
352
+ };
353
+ // ファイルをどこにどんな名前で保存するか訊くダイアログを表示
354
+ const saveHandle = await window.showSaveFilePicker(opts)
355
+ // 保存先ファイルに書き込み準備
356
+ const writable = await saveHandle.createWritable();
357
+ // 先程同様に書き込んで終了
358
+ await writable.write(json_data);
359
+ await writable.close();
360
+ };
361
+ }
362
+
363
+ function get_dirname(path) {
364
+ var result = path.replace(/\\/g, '/').replace(/\/[^\/]*$/, '');
365
+ if (result.match(/^[^\/]*\.[^\/\.]*$/)) {
366
+ result = '';
367
+ }
368
+ return result.replace(/\//g, "\\");
369
+ }
370
+
371
+ function dispFile() {
372
+ var fName = $("#inDir").val();
373
+ alert('選択したファイルの値は' + fName + 'です');
374
+ }
375
+
376
+ function openFile(file) {
377
+ $ws.send("openfile:" + file);
378
+ }
379
+
380
+ // 起動時の処理
381
+ $(document).ready(function () {
382
+
383
+ // サーバに接続
384
+ server_connect("ws://localhost:40159/wsserver")
385
+ window.onload = function (e) {
386
+ // サーバに接続
387
+ //server_connect("ws://localhost:40159/wsserver")
388
+ }
389
+
390
+ // menu
391
+ $(function () {
392
+ $(".menu li").hover(
393
+ function () {
394
+ //クラス名「open」を付与する
395
+ $(this).children(".menuSub").addClass("open");
396
+ //hoverが外れた場合
397
+ }, function () {
398
+ //クラス名「open」を取り除く
399
+ $(this).children(".menuSub").removeClass("open");
400
+ }
401
+ );
402
+ });
403
+
404
+ // ウインドウサイズ
405
+ var width = 800;
406
+ var height = 600;
407
+ $(window).resize(function () {
408
+ $(".outarea").height($(window).height() - 180);
409
+ });
410
+ // ウインドウの位置
411
+ $(function () {
412
+ //window.resizeTo(width, height);
413
+ //window.moveTo((window.screen.width / 2) - (width / 2), (screen.height / 2) - (height / 2));
414
+ //window.moveTo(0,0);
415
+ $(".outarea").height($(window).height() - 180);
416
+ });
417
+
418
+ $('.outarea').scroll(function () {
419
+ var h = $('.outarea').get(0).scrollHeight - $('.outarea').innerHeight();
420
+ //console.log("scrollEnd=" + Math.abs($('.outarea').scrollTop() - h));
421
+ if (Math.abs($('.outarea').scrollTop() - h) < 30) {
422
+ // 最後までスクロールしている
423
+ // 自動スクロールON
424
+ $auto_scroll = true;
425
+ } else {
426
+ // 自動スクロールOFF
427
+ $auto_scroll = false;
428
+ }
429
+ //console.log("auto_scroll=" + $auto_scroll);
430
+ });
431
+
432
+ // 設定ダイアログ
433
+ setting_dialog("setting", "setting_dialog", "config/setting.json");
434
+
435
+ // 設定保存
436
+ save_setting("save_setting", "config/setting.json");
437
+
438
+ // 設定読み込み
439
+ load_setting("load_setting");
440
+
441
+ // ハンドラ登録
442
+ $("#stop").click(function () {
443
+ send_message("stop");
444
+ });
445
+
446
+ $("#exec").click(function () {
447
+ $('#log').empty();
448
+ send_message("exec:" + $("#inDir").val() + "," + $("#outFile").val());
449
+ });
450
+
451
+ $("#open_file").click(function () {
452
+ openFile($("#outFile").val());
453
+ });
454
+
455
+ select_file_dialog("search_str", "dir", "dialog1", "select_dir", "inDir");
456
+
457
+ select_file_dialog("search_str2", "file", "dialog2", "select_file", "outFile");
458
+
459
+ autocomp_history("inDir", "history.json")
460
+ autocomp_history("outFile", "out_history.json")
461
+
462
+ });
463
+
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUmlClassVer
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,55 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "server_app_base.rb"
3
+ require "kconv"
4
+ #require "create_uml_class.rb"
5
+
6
+ class RubyUmlClass < AppMainBase
7
+ def start(argv)
8
+ super
9
+ begin
10
+ @abort = false
11
+ puts argv
12
+ in_dir = argv[0]
13
+ out_file = argv[1]
14
+
15
+ # 履歴の保存
16
+ add_history("history.json", in_dir)
17
+ add_history("out_history.json", out_file)
18
+
19
+ # Browserにメッセージ送信
20
+ #app_send("popup:start app #{argv[0]}")
21
+
22
+ out_svg = out_file.gsub(File.extname(out_file), "") + ".svg"
23
+
24
+ # uml作成
25
+ load "create_uml_class.rb"
26
+
27
+ uml = create_uml_class(in_dir, out_file)
28
+
29
+ File.open(out_file, "w") do |f|
30
+ f.puts uml
31
+ end
32
+
33
+ # PlantUMLの実行
34
+ FileUtils.rm_f out_svg
35
+ cmd = "#{@config["plantuml"]} #{out_file}"
36
+ puts cmd
37
+ system cmd
38
+ if File.exist? out_svg
39
+ yield File.read out_svg
40
+ else
41
+ yield "exec error"
42
+ yield cmd
43
+ end
44
+ rescue
45
+ puts $!
46
+ puts $@
47
+ yield $!.to_s.toutf8
48
+ yield $@.to_s.toutf8
49
+ end
50
+ end
51
+
52
+ def stop()
53
+ super
54
+ end
55
+ end
data/lib/server.rb ADDED
@@ -0,0 +1,58 @@
1
+ require "json"
2
+ require "kconv"
3
+
4
+ class Search < Sinatra::Base
5
+ helpers Sinatra::Streaming
6
+ get "" do
7
+ q_hash = {}
8
+ puts request.query_string
9
+ request.query_string.split("&").each do |q|
10
+ work = q.split("=")
11
+ if work[1] != nil
12
+ q_hash[work[0]] = CGI.unescape work[1].toutf8
13
+ else
14
+ q_hash[work[0]] = ""
15
+ end
16
+ end
17
+ str = q_hash["path"].gsub(/\\/, "/")
18
+ puts "str=#{str}"
19
+ kind = q_hash["kind"].gsub(/\\/, "/")
20
+ puts "kind=#{kind}"
21
+ res = []
22
+ str = str.gsub(/\\/, "/")
23
+ dir = File.dirname(str)
24
+ file = File.basename(str)
25
+ puts "dir=#{dir}"
26
+ puts "file=#{file}"
27
+
28
+ kernel = Facter.value(:kernel)
29
+ if kernel == "windows"
30
+ dir = "c:/" if dir == nil
31
+ dir = "c:/" if dir == "/"
32
+ elsif kernel == "Linux"
33
+ dir = "/" if dir == nil
34
+ else
35
+ dir = "c:/" if dir == nil
36
+ dir = "c:/" if dir == "/"
37
+ end
38
+
39
+ path = "#{dir}/#{file}"
40
+ if File.directory?(path)
41
+ path = path + "/*"
42
+ else
43
+ path = path + "*"
44
+ end
45
+ path.gsub!(/[\/]+/, "/")
46
+ puts path
47
+ Dir.glob(path, File::FNM_DOTMATCH).each do |file|
48
+ data = {}
49
+ next if File.basename(file) == "."
50
+ next if kind == "dir" and !File.directory?(file)
51
+ data["label"] = File.basename(file)
52
+ data["label"] += "/" if (File.directory?(file))
53
+ data["value"] = File.expand_path(file)
54
+ res.push data
55
+ end
56
+ JSON.generate res.sort { |a, b| a["value"] <=> b["value"] }
57
+ end
58
+ end
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+ class AppMainBase
3
+ def initialize
4
+ @config = nil
5
+ @aboet = false
6
+ @exec = false
7
+ @suspend = false
8
+ @ws = nil
9
+ end
10
+
11
+ def app_send(str)
12
+ if @ws != nil
13
+ @ws.send(str)
14
+ end
15
+ end
16
+
17
+ def set_ws(ws)
18
+ @ws = ws
19
+ end
20
+
21
+ def set_config(config)
22
+ @config = config
23
+ end
24
+
25
+ def start(argv)
26
+ @exec = true
27
+ end
28
+
29
+ def stop()
30
+ @abort = true
31
+ @exec = false
32
+ end
33
+
34
+ def suspend()
35
+ @suspend = true
36
+ end
37
+
38
+ def resume()
39
+ @suspend = false
40
+ end
41
+
42
+ # 履歴の保存
43
+ def add_history(file, history_data, max = 10)
44
+ begin
45
+ buf = File.read "#{$home_dir}history/#{file}"
46
+ rescue
47
+ buf = ""
48
+ end
49
+ data = eval(buf)
50
+ if data == nil
51
+ data = []
52
+ end
53
+ if history_data.to_s != ""
54
+ data.prepend history_data
55
+ end
56
+ data = data.uniq[0..max - 1]
57
+ File.open("#{$home_dir}history/#{file}", "w") do |f|
58
+ f.write JSON.pretty_generate data
59
+ end
60
+ end
61
+ end
62
+
63
+ require "app_load.rb"