Skip to content

Commit 4ac52eb

Browse files
authored
Merge pull request #266 from smalruby/gh-265-auto-completion
feat: support auto completion in ruby tab
2 parents 8920ebe + 183a6f6 commit 4ac52eb

27 files changed

+1147
-29
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "smalruby3-gui",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "GraphicaL User Interface for creating and running Smalruby 3.0 projects",
55
"author": "Ruby Programming Shounendan",
66
"license": "BSD-3-Clause",

src/containers/ruby-tab.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import 'ace-builds/src-noconflict/theme-clouds';
1919
import 'ace-builds/src-noconflict/ext-searchbox';
2020
import 'ace-builds/src-noconflict/ext-language_tools';
2121

22+
import SnippetsCompleter from './ruby-tab/snippets-completer';
23+
2224
class RubyTab extends React.Component {
2325
constructor (props) {
2426
super(props);
@@ -87,6 +89,9 @@ class RubyTab extends React.Component {
8789
errors,
8890
markers
8991
} = rubyCode;
92+
93+
const completers = [new SnippetsCompleter()];
94+
9095
return (
9196
<AceEditor
9297
annotations={errors}
@@ -100,7 +105,10 @@ class RubyTab extends React.Component {
100105
setOptions={{
101106
tabSize: 2,
102107
useSoftTabs: true,
103-
showInvisibles: true
108+
showInvisibles: true,
109+
enableAutoIndent: true,
110+
enableBasicAutocompletion: completers,
111+
enableLiveAutocompletion: true
104112
}}
105113
style={{
106114
border: '1px solid hsla(0, 0%, 0%, 0.15)',
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class BaseCompleter {
2+
getCompletions () {
3+
throw new Error('Not implemented');
4+
}
5+
6+
getDocTooltip (item) {
7+
if (!item.docHTML) {
8+
let description = item.description;
9+
let code;
10+
if (item.type === 'snippet') {
11+
const snippet = this.#removeSnippetVarAroundCode(item.snippet);
12+
description = description || snippet;
13+
code = snippet;
14+
} else {
15+
description = description || item.value;
16+
code = item.value;
17+
}
18+
item.docHTML = [
19+
'<b>', this.#escapeHTML(description), '</b>', '<hr></hr>',
20+
'<code>', this.#escapeHTML(code), '</code>'
21+
].join('');
22+
}
23+
}
24+
25+
#escapeHTML = function (str) {
26+
return (`${str}`).replace(/&/g, '&#38;').replace(/"/g, '&#34;')
27+
.replace(/'/g, '&#39;')
28+
.replace(/</g, '&#60;');
29+
};
30+
31+
#removeSnippetVarAroundCode = function (snippet) {
32+
return snippet.replace(/\$\{[0-9]+:?([^}]*?)\}/g, '$1');
33+
};
34+
}
35+
36+
export default BaseCompleter;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"sleep": {
3+
"snippet": "sleep(${1:1})",
4+
"description": "(1) 秒待つ"
5+
},
6+
"times": {
7+
"snippet": "${1:10}.times do\n${2}\nend\n",
8+
"description": "(10) 回繰り返す"
9+
},
10+
"loop": {
11+
"snippet": "loop do\n${1}\nend\n",
12+
"description": "ずっと"
13+
},
14+
"if": {
15+
"snippet": "if ${1:false}\n${2}\nend\n",
16+
"description": "もし < > なら"
17+
},
18+
"if-else": {
19+
"snippet": "if ${1:false}\n${2}\nelse\n${3}\nend\n",
20+
"description": "もし < > なら、でなければ"
21+
},
22+
"wait-until": {
23+
"snippet": "wait until ${1:false}",
24+
"description": "< > まで待つ"
25+
},
26+
"until": {
27+
"snippet": "until ${1:false}\n${2}\nend\n",
28+
"description": "< > まで繰り返す"
29+
},
30+
"stop-all": {
31+
"snippet": "stop(\"${1:all}\")",
32+
"description": "[すべてを止める▼]"
33+
},
34+
"stop-this": {
35+
"snippet": "stop(\"${1:this script}\")",
36+
"description": "[このスクリプトを止める▼]"
37+
},
38+
"stop-other": {
39+
"snippet": "stop(\"${1:other scripts in sprite}\")",
40+
"description": "[スプライトの他のスクリプトを止める▼]"
41+
},
42+
"when_start_as_a_clone": {
43+
"snippet": "when_start_as_a_clone do\n${1}\nend\n",
44+
"description": "クローンされたとき"
45+
},
46+
"create_clone": {
47+
"snippet": "create_clone(\"${1:_myself_}\")",
48+
"description": "(自分自身▼) のクローンを作る"
49+
},
50+
"delete_this_clone": {
51+
"snippet": "delete_this_clone",
52+
"description": "このクローンを削除する"
53+
}
54+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"when_flag_clicked": {
3+
"snippet": "when_flag_clicked do\n${1}\nend\n",
4+
"description": "旗が押されたとき"
5+
},
6+
"when_key_pressed": {
7+
"snippet": "when_key_pressed(\"${1:space}\") do\n${2}\nend\n",
8+
"description": "[スペース▼] キーが押されたとき"
9+
},
10+
"when_clicked": {
11+
"snippet": "when_clicked do\n${1}\nend\n",
12+
"description": "このスプライトが押されたとき"
13+
},
14+
"when_backdrop_switches": {
15+
"snippet": "when_backdrop_switches(\"${1:背景1}\") do\n${2}\nend\n",
16+
"description": "背景が [背景1▼] になったとき"
17+
},
18+
"when_greater_than": {
19+
"snippet": "when_greater_than(\"${1:loudness}\", ${2:10}) do\n${3}\nend\n",
20+
"description": "[音量▼] > (10) のとき"
21+
},
22+
"when_receive": {
23+
"snippet": "when_receive(\"${1:メッセージ1}\") do\n${2}\nend\n",
24+
"description": "[メッセージ1▼] を受け取ったとき"
25+
},
26+
"broadcast": {
27+
"snippet": "broadcast(\"${1:メッセージ1}\")",
28+
"description": "(メッセージ1) を送る"
29+
},
30+
"broadcast_and_wait": {
31+
"snippet": "broadcast_and_wait(\"${1:メッセージ1}\")",
32+
"description": "(メッセージ1) を送って待つ"
33+
}
34+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{
2+
"say-for": {
3+
"snippet": "say(\"${1:こんにちは!}\", ${2:2})",
4+
"description": "(こんにちは!) と (2) 秒言う"
5+
},
6+
"say": {
7+
"snippet": "say(\"${1:こんにちは!}\")",
8+
"description": "(こんにちは!) と言う"
9+
},
10+
"think-for": {
11+
"snippet": "think(\"${1:うーん...}\", ${2:2})",
12+
"description": "(うーん...) と (2) 秒考える"
13+
},
14+
"think": {
15+
"snippet": "think(\"${1:うーん...}\")",
16+
"description": "(うーん...) と考える"
17+
},
18+
"switch_costume": {
19+
"snippet": "switch_costume(\"${1:コスチューム1}\")",
20+
"description": "コスチュームを (コスチューム1▼) にする"
21+
},
22+
"next_costume": {
23+
"snippet": "next_costume",
24+
"description": "次のコスチュームにする"
25+
},
26+
"switch_backdrop": {
27+
"snippet": "switch_backdrop(\"${1:背景1}\")",
28+
"description": "背景を (背景1▼) にする"
29+
},
30+
"next_backdrop": {
31+
"snippet": "next_backdrop",
32+
"description": "次の背景にする"
33+
},
34+
"size+=": {
35+
"snippet": "self.size += ${1:10}",
36+
"description": "大きさを (10) ずつ変える"
37+
},
38+
"size=": {
39+
"snippet": "self.size = ${1:100}",
40+
"description": "大きさを (100) %にする"
41+
},
42+
"change_effect_by": {
43+
"snippet": "change_effect_by(\"${1:color}\", ${2:25})",
44+
"description": "[色▼] の効果を (25) ずつかえる"
45+
},
46+
"set_effect": {
47+
"snippet": "set_effect(\"${1:color}\", ${2:0})",
48+
"description": "[色▼] の効果を (0) にする"
49+
},
50+
"clear_graphic_effects": {
51+
"snippet": "clear_graphic_effects",
52+
"description": "画像効果をなくす"
53+
},
54+
"show": {
55+
"snippet": "show",
56+
"description": "表示する"
57+
},
58+
"hide": {
59+
"snippet": "hide",
60+
"description": "隠す"
61+
},
62+
"go_layers": {
63+
"snippet": "go_layers(${1:1}, \"${2:forward}\")",
64+
"description": "(1) 層 [手前に出す▼]"
65+
},
66+
"costume_number": {
67+
"snippet": "costume_number",
68+
"description": "コスチュームの [番号▼]"
69+
},
70+
"costume_name": {
71+
"snippet": "costume_name",
72+
"description": "コスチュームの [名前▼]"
73+
},
74+
"backdrop_number": {
75+
"snippet": "backdrop_number",
76+
"description": "背景の [番号▼]"
77+
},
78+
"backdrop_name": {
79+
"snippet": "backdrop_name",
80+
"description": "背景の [名前▼]"
81+
},
82+
"size": {
83+
"snippet": "size",
84+
"description": "大きさ"
85+
}
86+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"mesh.sensor_value": {
3+
"snippet": "mesh.sensor_value(\"${1: }\")",
4+
"description": "( ▼) センサーの値"
5+
}
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"microbit_more.when_button_is": {
3+
"snippet": "microbit_more.when_button_is(\"${1:A}\", \"${2:down}\") do\n${3}\nend\n",
4+
"description": "ボタン [A▼] が [押された▼] とき"
5+
}
6+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"microbit.when_button_pressed": {
3+
"snippet": "microbit.when_button_pressed(\"${1:A}\") do\n${2}\nend\n",
4+
"description": "ボタン (A▼) が押されたとき"
5+
},
6+
"microbit.button_pressed?": {
7+
"snippet": "microbit.button_pressed?(\"${1:A}\")",
8+
"description": "ボタン (A▼) が押された"
9+
},
10+
"microbit.when": {
11+
"snippet": "microbit.when(\"${1:moved}\") do\n${2}\nend\n",
12+
"description": "(動いた▼) とき"
13+
},
14+
"microbit.display_text": {
15+
"snippet": "microbit.display_text(\"${1:こんにちは!}\")",
16+
"description": "(こんにちは!) を表示する"
17+
},
18+
"microbit.display": {
19+
"snippet": "microbit.display(\n \"${1:.1.1.}\",\n \"${2:1.1.1}\",\n \"${3:1...1}\",\n \"${4:.1.1.}\",\n \"${5:..1..}\"\n)\n",
20+
"description": "(♡▼) を表示する"
21+
},
22+
"microbit.when_tilted": {
23+
"snippet": "microbit.when_tilted(\"${1:any}\") do\n${2}\nend\n",
24+
"description": "(どれかの向き▼) に傾いたとき"
25+
},
26+
"microbit.tilted?": {
27+
"snippet": "microbit.tilted?(\"${1:any}\")",
28+
"description": "(どれかの向き▼) に傾いた"
29+
},
30+
"microbit.tilt_angle": {
31+
"snippet": "microbit.tilt_angle(\"${1:front}\")",
32+
"description": "(前▼) 方向の傾き"
33+
},
34+
"microbit.when_pin_connected": {
35+
"snippet": "microbit.when_pin_connected(${1:0}) do\n${2}\nend\n",
36+
"description": "ピン (0▼) がつながったとき"
37+
}
38+
}

0 commit comments

Comments
 (0)