diff --git a/package.json b/package.json index 51d7eed97df..5af61de770f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smalruby3-gui", - "version": "2.0.0", + "version": "2.0.1", "description": "GraphicaL User Interface for creating and running Smalruby 3.0 projects", "author": "Ruby Programming Shounendan", "license": "BSD-3-Clause", diff --git a/src/containers/ruby-tab.jsx b/src/containers/ruby-tab.jsx index 70fee0938db..06d21eaf4e9 100644 --- a/src/containers/ruby-tab.jsx +++ b/src/containers/ruby-tab.jsx @@ -19,6 +19,8 @@ import 'ace-builds/src-noconflict/theme-clouds'; import 'ace-builds/src-noconflict/ext-searchbox'; import 'ace-builds/src-noconflict/ext-language_tools'; +import SnippetsCompleter from './ruby-tab/snippets-completer'; + class RubyTab extends React.Component { constructor (props) { super(props); @@ -87,6 +89,9 @@ class RubyTab extends React.Component { errors, markers } = rubyCode; + + const completers = [new SnippetsCompleter()]; + return ( ', this.#escapeHTML(description), '', '
', + '', this.#escapeHTML(code), '' + ].join(''); + } + } + + #escapeHTML = function (str) { + return (`${str}`).replace(/&/g, '&').replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/ なら" + }, + "if-else": { + "snippet": "if ${1:false}\n${2}\nelse\n${3}\nend\n", + "description": "もし < > なら、でなければ" + }, + "wait-until": { + "snippet": "wait until ${1:false}", + "description": "< > まで待つ" + }, + "until": { + "snippet": "until ${1:false}\n${2}\nend\n", + "description": "< > まで繰り返す" + }, + "stop-all": { + "snippet": "stop(\"${1:all}\")", + "description": "[すべてを止める▼]" + }, + "stop-this": { + "snippet": "stop(\"${1:this script}\")", + "description": "[このスクリプトを止める▼]" + }, + "stop-other": { + "snippet": "stop(\"${1:other scripts in sprite}\")", + "description": "[スプライトの他のスクリプトを止める▼]" + }, + "when_start_as_a_clone": { + "snippet": "when_start_as_a_clone do\n${1}\nend\n", + "description": "クローンされたとき" + }, + "create_clone": { + "snippet": "create_clone(\"${1:_myself_}\")", + "description": "(自分自身▼) のクローンを作る" + }, + "delete_this_clone": { + "snippet": "delete_this_clone", + "description": "このクローンを削除する" + } +} diff --git a/src/containers/ruby-tab/events-snippets.json b/src/containers/ruby-tab/events-snippets.json new file mode 100644 index 00000000000..76100877a82 --- /dev/null +++ b/src/containers/ruby-tab/events-snippets.json @@ -0,0 +1,34 @@ +{ + "when_flag_clicked": { + "snippet": "when_flag_clicked do\n${1}\nend\n", + "description": "旗が押されたとき" + }, + "when_key_pressed": { + "snippet": "when_key_pressed(\"${1:space}\") do\n${2}\nend\n", + "description": "[スペース▼] キーが押されたとき" + }, + "when_clicked": { + "snippet": "when_clicked do\n${1}\nend\n", + "description": "このスプライトが押されたとき" + }, + "when_backdrop_switches": { + "snippet": "when_backdrop_switches(\"${1:背景1}\") do\n${2}\nend\n", + "description": "背景が [背景1▼] になったとき" + }, + "when_greater_than": { + "snippet": "when_greater_than(\"${1:loudness}\", ${2:10}) do\n${3}\nend\n", + "description": "[音量▼] > (10) のとき" + }, + "when_receive": { + "snippet": "when_receive(\"${1:メッセージ1}\") do\n${2}\nend\n", + "description": "[メッセージ1▼] を受け取ったとき" + }, + "broadcast": { + "snippet": "broadcast(\"${1:メッセージ1}\")", + "description": "(メッセージ1) を送る" + }, + "broadcast_and_wait": { + "snippet": "broadcast_and_wait(\"${1:メッセージ1}\")", + "description": "(メッセージ1) を送って待つ" + } +} diff --git a/src/containers/ruby-tab/looks-snippets.json b/src/containers/ruby-tab/looks-snippets.json new file mode 100644 index 00000000000..a1db636dcec --- /dev/null +++ b/src/containers/ruby-tab/looks-snippets.json @@ -0,0 +1,86 @@ +{ + "say-for": { + "snippet": "say(\"${1:こんにちは!}\", ${2:2})", + "description": "(こんにちは!) と (2) 秒言う" + }, + "say": { + "snippet": "say(\"${1:こんにちは!}\")", + "description": "(こんにちは!) と言う" + }, + "think-for": { + "snippet": "think(\"${1:うーん...}\", ${2:2})", + "description": "(うーん...) と (2) 秒考える" + }, + "think": { + "snippet": "think(\"${1:うーん...}\")", + "description": "(うーん...) と考える" + }, + "switch_costume": { + "snippet": "switch_costume(\"${1:コスチューム1}\")", + "description": "コスチュームを (コスチューム1▼) にする" + }, + "next_costume": { + "snippet": "next_costume", + "description": "次のコスチュームにする" + }, + "switch_backdrop": { + "snippet": "switch_backdrop(\"${1:背景1}\")", + "description": "背景を (背景1▼) にする" + }, + "next_backdrop": { + "snippet": "next_backdrop", + "description": "次の背景にする" + }, + "size+=": { + "snippet": "self.size += ${1:10}", + "description": "大きさを (10) ずつ変える" + }, + "size=": { + "snippet": "self.size = ${1:100}", + "description": "大きさを (100) %にする" + }, + "change_effect_by": { + "snippet": "change_effect_by(\"${1:color}\", ${2:25})", + "description": "[色▼] の効果を (25) ずつかえる" + }, + "set_effect": { + "snippet": "set_effect(\"${1:color}\", ${2:0})", + "description": "[色▼] の効果を (0) にする" + }, + "clear_graphic_effects": { + "snippet": "clear_graphic_effects", + "description": "画像効果をなくす" + }, + "show": { + "snippet": "show", + "description": "表示する" + }, + "hide": { + "snippet": "hide", + "description": "隠す" + }, + "go_layers": { + "snippet": "go_layers(${1:1}, \"${2:forward}\")", + "description": "(1) 層 [手前に出す▼]" + }, + "costume_number": { + "snippet": "costume_number", + "description": "コスチュームの [番号▼]" + }, + "costume_name": { + "snippet": "costume_name", + "description": "コスチュームの [名前▼]" + }, + "backdrop_number": { + "snippet": "backdrop_number", + "description": "背景の [番号▼]" + }, + "backdrop_name": { + "snippet": "backdrop_name", + "description": "背景の [名前▼]" + }, + "size": { + "snippet": "size", + "description": "大きさ" + } +} diff --git a/src/containers/ruby-tab/mesh-snippets.json b/src/containers/ruby-tab/mesh-snippets.json new file mode 100644 index 00000000000..ba8d9f8525c --- /dev/null +++ b/src/containers/ruby-tab/mesh-snippets.json @@ -0,0 +1,6 @@ +{ + "mesh.sensor_value": { + "snippet": "mesh.sensor_value(\"${1: }\")", + "description": "( ▼) センサーの値" + } +} diff --git a/src/containers/ruby-tab/microbit-more-snippets.json b/src/containers/ruby-tab/microbit-more-snippets.json new file mode 100644 index 00000000000..d44bca483f7 --- /dev/null +++ b/src/containers/ruby-tab/microbit-more-snippets.json @@ -0,0 +1,6 @@ +{ + "microbit_more.when_button_is": { + "snippet": "microbit_more.when_button_is(\"${1:A}\", \"${2:down}\") do\n${3}\nend\n", + "description": "ボタン [A▼] が [押された▼] とき" + } +} diff --git a/src/containers/ruby-tab/microbit-snippets.json b/src/containers/ruby-tab/microbit-snippets.json new file mode 100644 index 00000000000..1654c8d80b5 --- /dev/null +++ b/src/containers/ruby-tab/microbit-snippets.json @@ -0,0 +1,38 @@ +{ + "microbit.when_button_pressed": { + "snippet": "microbit.when_button_pressed(\"${1:A}\") do\n${2}\nend\n", + "description": "ボタン (A▼) が押されたとき" + }, + "microbit.button_pressed?": { + "snippet": "microbit.button_pressed?(\"${1:A}\")", + "description": "ボタン (A▼) が押された" + }, + "microbit.when": { + "snippet": "microbit.when(\"${1:moved}\") do\n${2}\nend\n", + "description": "(動いた▼) とき" + }, + "microbit.display_text": { + "snippet": "microbit.display_text(\"${1:こんにちは!}\")", + "description": "(こんにちは!) を表示する" + }, + "microbit.display": { + "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", + "description": "(♡▼) を表示する" + }, + "microbit.when_tilted": { + "snippet": "microbit.when_tilted(\"${1:any}\") do\n${2}\nend\n", + "description": "(どれかの向き▼) に傾いたとき" + }, + "microbit.tilted?": { + "snippet": "microbit.tilted?(\"${1:any}\")", + "description": "(どれかの向き▼) に傾いた" + }, + "microbit.tilt_angle": { + "snippet": "microbit.tilt_angle(\"${1:front}\")", + "description": "(前▼) 方向の傾き" + }, + "microbit.when_pin_connected": { + "snippet": "microbit.when_pin_connected(${1:0}) do\n${2}\nend\n", + "description": "ピン (0▼) がつながったとき" + } +} diff --git a/src/containers/ruby-tab/motion-snippets.json b/src/containers/ruby-tab/motion-snippets.json new file mode 100644 index 00000000000..26458007142 --- /dev/null +++ b/src/containers/ruby-tab/motion-snippets.json @@ -0,0 +1,94 @@ +{ + "move": { + "snippet": "move(${1:10})", + "description": "(10) 歩動かす" + }, + "turn_right": { + "snippet": "turn_right(${1:15})", + "description": "時計回りに (15) 度回す" + }, + "turn_left": { + "snippet": "turn_left(${1:15})", + "description": "反時計回りに (15) 度回す" + }, + "go_to": { + "snippet": "go_to(\"${1:_random_}\")", + "description": "(どこかの場所▼) へ行く" + }, + "_random_": { + "snippet": "_random_", + "description": "どこかの場所" + }, + "_mouse_": { + "snippet": "_mouse_", + "description": "マウスのポインター" + }, + "go_to-xy": { + "snippet": "go_to([${1:0}, ${2:0}])", + "description": "x座標を (0) 、y座標を (0) にする" + }, + "glide": { + "snippet": "glide(\"${1:_random_}\", secs: ${2:1})", + "description": "(1) 秒で (どこかの場所▼) へ行く" + }, + "glide-xy": { + "snippet": "glide([${1:0}, ${2:0}], secs: ${3:1})", + "description": "(1) 秒でx座標を (0) に、y座標を (0) にする" + }, + "direction=": { + "snippet": "self.direction = ${1:90}", + "description": "(90) 度に向ける" + }, + "point_towards": { + "snippet": "point_towards(\"${1:_mouse_}\")", + "description": "(マウスのポインター▼) へ向ける" + }, + "x+=": { + "snippet": "self.x += ${1:10}", + "description": "x座標を (10) ずつ変える" + }, + "x=": { + "snippet": "self.x = ${1:0}", + "description": "x座標を (0) にする" + }, + "y+=": { + "snippet": "self.y += ${1:10}", + "description": "y座標を (10) ずつ変える" + }, + "y=": { + "snippet": "self.y = ${1:0}", + "description": "y座標を (0) にする" + }, + "bounce_if_on_edge": { + "snippet": "bounce_if_on_edge", + "description": "もし端についたら、跳ね返る" + }, + "rotation_style=": { + "snippet": "self.rotation_style = \"${1:left-right}\"", + "description": "回転方法を [左右のみ▼] にする" + }, + "left-right": { + "snippet": "left-right", + "description": "左右のみ" + }, + "don't_rotate": { + "snippet": "don't rotate", + "description": "回転しない" + }, + "all_around": { + "snippet": "all around", + "description": "自由に回転" + }, + "x": { + "snippet": "x", + "description": "x座標" + }, + "y": { + "snippet": "y", + "description": "y座標" + }, + "direction": { + "snippet": "direction", + "description": "向き" + } +} diff --git a/src/containers/ruby-tab/music-snippets.json b/src/containers/ruby-tab/music-snippets.json new file mode 100644 index 00000000000..7873796d0f2 --- /dev/null +++ b/src/containers/ruby-tab/music-snippets.json @@ -0,0 +1,186 @@ +{ + "music.play_drum": { + "snippet": "play_drum(drum: ${1:1}, beats: ${2:0.25})", + "description": "((1)スネアドラム▼) のドラムを (0.25) 拍鳴らす" + }, + "music.d-snare": { + "snippet": "1", + "description": "(1) スネアドラム" + }, + "music.d-bass": { + "snippet": "2", + "description": "(2) バスドラム" + }, + "music.d-side-stick": { + "snippet": "3", + "description": "(3) サイドスティック" + }, + "music.d-crash-cymbal": { + "snippet": "4", + "description": "(4) クラッシュシンバル" + }, + "music.d-open-hihat": { + "snippet": "5", + "description": "(5) オープンハイハット" + }, + "music.d-closed-hihat": { + "snippet": "6", + "description": "(6) クローズハイハット" + }, + "music.d-tambourine": { + "snippet": "7", + "description": "(7) タンバリン" + }, + "music.d-hand-clap": { + "snippet": "8", + "description": "(8) 手拍子" + }, + "music.d-claves": { + "snippet": "9", + "description": "(9) クラーベ" + }, + "music.d-wood-block": { + "snippet": "10", + "description": "(10) ウッドブロック" + }, + "music.d-cowbell": { + "snippet": "11", + "description": "(11) カウベル" + }, + "music.d-triangle": { + "snippet": "12", + "description": "(12) トライアングル" + }, + "music.d-bongo": { + "snippet": "13", + "description": "(13) ボンゴ" + }, + "music.d-conga": { + "snippet": "14", + "description": "(14) コンガ" + }, + "music.d-cabasa": { + "snippet": "15", + "description": "(15) カバサ" + }, + "music.d-guiro": { + "snippet": "16", + "description": "(16) ギロ" + }, + "music.d-vibraslap": { + "snippet": "17", + "description": "(17) ビブラスラップ" + }, + "music.d-cuica": { + "snippet": "18", + "description": "(18) クイーカ" + }, + "music.rest": { + "snippet": "rest(${1:0.25})", + "description": "(0.25) 拍休む" + }, + "music.play_note": { + "snippet": "play_note(note: ${1:60}, beats: ${2:0.25})", + "description": "(60) の音符を (0.25) 拍鳴らす" + }, + "music.instrument=": { + "snippet": "self.instrument = ${1:1}", + "description": "楽器を ((1)ピアノ▼) にする" + }, + "music.i-piano": { + "snippet": "1", + "description": "(1) ピアノ" + }, + "music.i-electric-piano": { + "snippet": "2", + "description": "(2) 電子ピアノ" + }, + "music.i-organ": { + "snippet": "3", + "description": "(3) オルガン" + }, + "music.i-guitar": { + "snippet": "4", + "description": "(4) ギター" + }, + "music.i-electric-guitar": { + "snippet": "5", + "description": "(5) エレキギター" + }, + "music.i-bass": { + "snippet": "6", + "description": "(6) ベース" + }, + "music.i-pizzicato": { + "snippet": "7", + "description": "(7) ピチカート" + }, + "music.i-cello": { + "snippet": "8", + "description": "(8) チェロ" + }, + "music.i-trombone": { + "snippet": "9", + "description": "(9) トロンボーン" + }, + "music.i-clarinet": { + "snippet": "10", + "description": "(10) クラリネット" + }, + "music.i-saxophone": { + "snippet": "11", + "description": "(11) サクソフォン" + }, + "music.i-flute": { + "snippet": "12", + "description": "(12) フルート" + }, + "music.i-wooden-flute": { + "snippet": "13", + "description": "(13) 木管フルート" + }, + "music.i-bassoon": { + "snippet": "14", + "description": "(14) バスーン" + }, + "music.i-choir": { + "snippet": "15", + "description": "(15) 合唱団" + }, + "music.i-vibraphone": { + "snippet": "16", + "description": "(16) ビブラフォン" + }, + "music.i-music-box": { + "snippet": "17", + "description": "(17) ミュージックボックス" + }, + "music.i-steel-drum": { + "snippet": "18", + "description": "(18) スチールドラム" + }, + "music.i-marimba": { + "snippet": "19", + "description": "(19) マリンバ" + }, + "music.i-synth-lead": { + "snippet": "20", + "description": "(20) シンセリード" + }, + "music.i-synth-pad": { + "snippet": "21", + "description": "(21) シンセパッド" + }, + "music.tempo=": { + "snippet": "self.tempo = ${1:60}", + "description": "テンポを (60) にする" + }, + "music.tempo+=": { + "snippet": "self.tempo += ${1:20}", + "description": "テンポを (20) ずつ変える" + }, + "music.tempo": { + "snippet": "tempo", + "description": "テンポ" + } +} diff --git a/src/containers/ruby-tab/operators-snippets.json b/src/containers/ruby-tab/operators-snippets.json new file mode 100644 index 00000000000..705d771f37d --- /dev/null +++ b/src/containers/ruby-tab/operators-snippets.json @@ -0,0 +1,86 @@ +{ + "rand": { + "snippet": "rand(${1:1}..${2:10})", + "description": "(1) から (10) までの乱数" + }, + "and": { + "snippet": "${1:false} && ${2:false}", + "description": "< > かつ < >" + }, + "or": { + "snippet": "${1:false} || ${2:false}", + "description": "< > または < >" + }, + "not": { + "snippet": "!${1:false}", + "description": "< > ではない" + }, + "string+": { + "snippet": "\"${1:りんご}\" + \"${2:バナナ}\"", + "description": "(りんご) と (バナナ)" + }, + "string[]": { + "snippet": "\"${1:りんご}\"[${2:1}]", + "description": "(りんご) の (1) 番目の文字" + }, + "string.length": { + "snippet": "\"${1:りんご}\".length", + "description": "(りんご) の長さ" + }, + "string.include?": { + "snippet": "\"${1:りんご}\".include?(\"${2:り}\")", + "description": "(りんご) に (り) が含まれる" + }, + "round": { + "snippet": "${1:0}.round", + "description": "(0) を四捨五入" + }, + "abs": { + "snippet": "${1:0}.abs", + "description": "(0) の [絶対値▼]" + }, + "floor": { + "snippet": "${1:0}.floor", + "description": "(0) の [切り下げ▼]" + }, + "ceil": { + "snippet": "${1:0}.ceil", + "description": "(0) の [切り上げ▼]" + }, + "sqrt": { + "snippet": "Math.sqrt(${1:0})", + "description": "(0) の [平方根▼]" + }, + "sin": { + "snippet": "Math.sin(${1:0})", + "description": "(0) の [sin▼]" + }, + "cos": { + "snippet": "Math.cos(${1:0})", + "description": "(0) の [cons▼]" + }, + "tan": { + "snippet": "Math.tan(${1:0})", + "description": "(0) の [tan▼]" + }, + "asin": { + "snippet": "Math.asin(${1:0})", + "description": "(0) の [asin▼]" + }, + "acos": { + "snippet": "Math.acos(${1:0})", + "description": "(0) の [acos▼]" + }, + "atan": { + "snippet": "Math.atan(${1:0})", + "description": "(0) の [atan▼]" + }, + "log": { + "snippet": "Math.log(${1:0})", + "description": "(0) の [In▼]" + }, + "log10": { + "snippet": "Math.log10(${1:0})", + "description": "(0) の [log▼]" + } +} diff --git a/src/containers/ruby-tab/pen-snippets.json b/src/containers/ruby-tab/pen-snippets.json new file mode 100644 index 00000000000..d3acd1413ba --- /dev/null +++ b/src/containers/ruby-tab/pen-snippets.json @@ -0,0 +1,62 @@ +{ + "pen.clear": { + "snippet": "pen_clear", + "description": "全部消す" + }, + "pen.stamp": { + "snippet": "pen_stamp", + "description": "スタンプ" + }, + "pen.down": { + "snippet": "pen_down", + "description": "ペンを下ろす" + }, + "pen.up": { + "snippet": "pen_up", + "description": "ペンを上げる" + }, + "pen.color=#": { + "snippet": "self.pen_color = \"#${1:7a2d74}\"", + "description": "ペンの色を (#7a2d74) にする" + }, + "pen.color+=": { + "snippet": "self.pen_color += ${1:10}", + "description": "ペンの [色▼] を (10) ずつ変える" + }, + "pen.saturation+=": { + "snippet": "self.pen_saturation += ${1:10}", + "description": "ペンの [鮮やかさ▼] を (10) ずつ変える" + }, + "pen.brightness+=": { + "snippet": "self.pen_brightness += ${1:10}", + "description": "ペンの [明るさ▼] を (10) ずつ変える" + }, + "pen.transparency+=": { + "snippet": "self.pen_transparency += ${1:10}", + "description": "ペンの [透明度▼] を (10) ずつ変える" + }, + "pen.color=": { + "snippet": "self.pen_color = ${1:50}", + "description": "ペンの [色▼] を (50) にする" + }, + "pen.saturation=": { + "snippet": "self.pen_saturation = ${1:50}", + "description": "ペンの [鮮やかさ▼] を (50) にする" + }, + "pen.brightness=": { + "snippet": "self.pen_brightness = ${1:50}", + "description": "ペンの [明るさ▼] を (50) にする" + }, + "pen.transparency=": { + "snippet": "self.pen_transparency = ${1:50}", + "description": "ペンの [透明度▼] を (50) にする" + }, + "pen.size+=": { + "snippet": "self.pen_size += ${1:1}", + "description": "ペンの太さを (1) ずつ変える" + }, + "pen.size=": { + "snippet": "self.pen_size = ${1:1}", + "description": "ペンの太さを (1) にする" + } +} diff --git a/src/containers/ruby-tab/procedure-snippets.json b/src/containers/ruby-tab/procedure-snippets.json new file mode 100644 index 00000000000..edcff57685d --- /dev/null +++ b/src/containers/ruby-tab/procedure-snippets.json @@ -0,0 +1,6 @@ +{ + "def": { + "snippet": "def self.${1:ブロック名}(${2:number_or_text})\n${3}\nend\n", + "description": "定義 ブロック名 (number_or_text)" + } +} diff --git a/src/containers/ruby-tab/sensing-snippets.json b/src/containers/ruby-tab/sensing-snippets.json new file mode 100644 index 00000000000..6eb3fa0a6d1 --- /dev/null +++ b/src/containers/ruby-tab/sensing-snippets.json @@ -0,0 +1,138 @@ +{ + "touching?": { + "snippet": "touching?(\"${1:_mouse_}\")", + "description": "(マウスのポインター▼) に触れた" + }, + "touching_color?": { + "snippet": "touching_color?(\"${1:#571332}\")", + "description": "(#571332▼) 色に触れた" + }, + "color_is_touching_color?": { + "snippet": "color_is_touching_color?(\"#${1:ce2ef7}\", \"#${2:6a7a0e}\")", + "description": "(#ce2ef7▼) 色が (#6a7a0e▼) 色に触れた" + }, + "distance": { + "snippet": "distance(\"${1:_mouse_}\")", + "description": "(マウスのポインター▼) までの距離" + }, + "ask": { + "snippet": "ask(\"${1:あなたの名前は何ですか?}\")", + "description": "(あなたの名前は何ですか?) と聞いて待つ" + }, + "answer": { + "snippet": "answer", + "description": "答え" + }, + "Keyboard.pressed?": { + "snippet": "Keyboard.pressed?(\"${1:space}\")", + "description": "[スペースキー▼] が押された" + }, + "Mouse.down?": { + "snippet": "Mouse.down?", + "description": "マウスが押された" + }, + "Mouse.x": { + "snippet": "Mouse.x", + "description": "マウスのx座標" + }, + "Mouse.y": { + "snippet": "Mouse.y", + "description": "マウスのy座標" + }, + "drag_mode=": { + "snippet": "self.drag_mode = \"${1:draggable}\"", + "description": "ドラッグ [できる▼] ようにする" + }, + "loudness": { + "snippet": "loudness", + "description": "音量" + }, + "Timer.value": { + "snippet": "Timer.value", + "description": "タイマー" + }, + "Timer.reset": { + "snippet": "Timer.reset", + "description": "タイマーをリセット" + }, + "stage.backdrop_number": { + "snippet": "stage.backdrop_number", + "description": "(ステージ▼) の [背景#▼]" + }, + "stage.backdrop_name": { + "snippet": "stage.backdrop_name", + "description": "(ステージ▼) の [背景の名前▼]" + }, + "stage.volume": { + "snippet": "stage.volume", + "description": "(ステージ▼) の [音量▼]" + }, + "stage.variable": { + "snippet": "stage.variable(\"${1:変数}\")", + "description": "(ステージ▼) の [変数▼]" + }, + "sprite.x": { + "snippet": "sprite(\"${1:スプライト1}\").x", + "description": "(スプライト1▼) の [x座標▼]" + }, + "sprite.y": { + "snippet": "sprite(\"${1:スプライト1}\").y", + "description": "(スプライト1▼) の [y座標▼]" + }, + "sprite.direction": { + "snippet": "sprite(\"${1:スプライト1}\").direction", + "description": "(スプライト1▼) の [向き▼]" + }, + "sprite.costume_number": { + "snippet": "sprite(\"${1:スプライト1}\").costume_number", + "description": "(スプライト1▼) の [コスチューム#▼]" + }, + "sprite.costume_name": { + "snippet": "sprite(\"${1:スプライト1}\").costume_name", + "description": "(スプライト1▼) の [コスチューム名▼]" + }, + "sprite.size": { + "snippet": "sprite(\"${1:スプライト1}\").size", + "description": "(スプライト1▼) の [大きさ▼]" + }, + "sprite.volume": { + "snippet": "sprite(\"${1:スプライト1}\").volume", + "description": "(スプライト1▼) の [音量▼]" + }, + "current_year": { + "snippet": "Time.now.year", + "description": "現在の [年▼]" + }, + "current_month": { + "snippet": "Time.now.month", + "description": "現在の [月▼]" + }, + "current_day": { + "snippet": "Time.now.day", + "description": "現在の [日▼]" + }, + "current_day_of_week": { + "snippet": "Time.now.date", + "description": "現在の [曜日▼]" + }, + "current_hour": { + "snippet": "Time.now.hour", + "description": "現在の [時▼]" + }, + "current_minute": { + "snippet": "Time.now.min", + "description": "現在の [分▼]" + }, + "current_second": { + "snippet": "Time.now.sec", + "description": "現在の [秒▼]" + }, + "days_since_2000": { + "snippet": "days_since_2000", + "description": "2000年からの日数" + }, + "user_name": { + "snippet": "user_name", + "description": "ユーザー名" + } +} diff --git a/src/containers/ruby-tab/smalrubot-s1-snippets.json b/src/containers/ruby-tab/smalrubot-s1-snippets.json new file mode 100644 index 00000000000..d25ef9774d6 --- /dev/null +++ b/src/containers/ruby-tab/smalrubot-s1-snippets.json @@ -0,0 +1,66 @@ +{ + "smalrubot_s1.action": { + "snippet": "smalrubot_s1.action(\"${1:forward}\")", + "description": "[進める▼]" + }, + "smalrubot_s1.a-forward": { + "snippet": "forward", + "description": "進める" + }, + "smalrubot_s1.a-backward": { + "snippet": "backward", + "description": "バックさせる" + }, + "smalrubot_s1.a-turn-left": { + "snippet": "left", + "description": "左に曲げる" + }, + "smalrubot_s1.a-turn-right": { + "snippet": "right", + "description": "右に曲げる" + }, + "smalrubot_s1.a-stop": { + "snippet": "stop", + "description": "止める" + }, + "smalrubot_s1.action-in": { + "snippet": "smalrubot_s1.action(\"${1:forward}\", ${2:0.5})", + "description": "(0.5) 秒 [進める▼]" + }, + "smalrubot_s1.bend_arm": { + "snippet": "smalrubot_s1.bend_arm(${1:90}, ${2:1})", + "description": "(1) 秒でアームを (90) 度に曲げる" + }, + "smalrubot_s1.sensor_value": { + "snippet": "smalrubot_s1.sensor_value(\"${1:left}\")", + "description": "[左▼] のセンサー" + }, + "smalrubot_s1.d-left": { + "snippet": "left", + "description": "左" + }, + "smalrubot_s1.d-right": { + "snippet": "right", + "description": "右" + }, + "smalrubot_s1.led_on": { + "snippet": "smalrubot_s1.led(\"${1:left}\", true)", + "description": "[左▼] のLEDをオンにする" + }, + "smalrubot_s1.led_off": { + "snippet": "smalrubot_s1.led(\"${1:left}\", false)", + "description": "[左▼] のLEDをオフにする" + }, + "smalrubot_s1.get_motor_speed": { + "snippet": "smalrubot_s1.get_motor_speed(\"${1:left}\")", + "description": "[左▼] DCモーターの速度 (%)" + }, + "smalrubot_s1.set_motor_speed": { + "snippet": "smalrubot_s1.set_motor_speed(\"${1:left}\", ${1:50})", + "description": "[左▼] DCモーターの速度を (50) (%) にする" + }, + "smalrubot_s1.arm_calibration=": { + "snippet": "smalrubot_s1.arm_calibration = ${1:0}", + "description": "アームを (0) 度調整する" + } +} diff --git a/src/containers/ruby-tab/snippets-completer.js b/src/containers/ruby-tab/snippets-completer.js new file mode 100644 index 00000000000..4df893ea11e --- /dev/null +++ b/src/containers/ruby-tab/snippets-completer.js @@ -0,0 +1,64 @@ +import BaseCompleter from './base-completer'; + +import MotionSnippets from './motion-snippets.json'; +import LooksSnippets from './looks-snippets.json'; +import SoundSnippets from './sound-snippets.json'; +import EventsSnippets from './events-snippets.json'; +import ControlSnippets from './control-snippets.json'; +import SensingSnippets from './sensing-snippets.json'; +import OperatorsSnippets from './operators-snippets.json'; +import VariablesSnippets from './variables-snippets.json'; +import ProcedureSnippets from './procedure-snippets.json'; + +import MusicSnippets from './music-snippets.json'; +import PenSnippets from './pen-snippets.json'; +import VideoSensingSnippets from './video-sensing-snippets.json'; +import TextToSpeechSnippets from './text-to-speech-snippets.json'; +import TranslateSnippets from './translate-snippets.json'; +import MicrobitSnippets from './microbit-snippets.json'; +import MeshSnippets from './mesh-snippets.json'; +import SmalrubotS1Snippets from './smalrubot-s1-snippets.json'; +import MicrobitMoreSnippets from './microbit-more-snippets.json'; + +class SnippetsCompleter extends BaseCompleter { + #completions = []; + + constructor () { + super(); + + const snippetsList = [ + MotionSnippets, + LooksSnippets, + SoundSnippets, + EventsSnippets, + ControlSnippets, + SensingSnippets, + OperatorsSnippets, + VariablesSnippets, + ProcedureSnippets, + + MusicSnippets, + PenSnippets, + VideoSensingSnippets, + TextToSpeechSnippets, + TranslateSnippets, + MicrobitSnippets, + MeshSnippets, + SmalrubotS1Snippets, + MicrobitMoreSnippets + ]; + snippetsList.forEach(snippets => { + for (const [caption, item] of Object.entries(snippets)) { + item.caption = caption; + item.type = 'snippet'; + this.#completions.push(item); + } + }); + } + + getCompletions (editor, session, pos, prefix, callback) { + callback(null, this.#completions); + } +} + +export default SnippetsCompleter; diff --git a/src/containers/ruby-tab/sound-snippets.json b/src/containers/ruby-tab/sound-snippets.json new file mode 100644 index 00000000000..46167a727fa --- /dev/null +++ b/src/containers/ruby-tab/sound-snippets.json @@ -0,0 +1,38 @@ +{ + "play_until_done": { + "snippet": "play_until_done(\"${1:ニャー}\")", + "description": "終わるまで (ニャー▼) の音を鳴らす" + }, + "play": { + "snippet":"play(\"${1:ニャー}\")", + "description": "(ニャー▼) の音を鳴らす" + }, + "stop_all_sounds": { + "snippet": "stop_all_sounds", + "description": "すべての音を止める" + }, + "change_sound_effect_by": { + "snippet": "change_sound_effect_by(\"${1:pitch}\", ${2:10})", + "description": "[ピッチ▼] の効果を (10) ずつ変える" + }, + "set_sound_effect": { + "snippet": "set_sound_effect(\"${1:pitch}\", ${2:100})", + "description": "[ピッチ▼] の効果を (100) にする" + }, + "clear_sound_effects": { + "snippet": "clear_sound_effects", + "description": "音の効果をなくす" + }, + "volume+=": { + "snippet": "self.volume += ${1:-10}", + "description": "音量を (-10) ずつ変える" + }, + "volume=": { + "snippet": "self.volume = ${1:100}", + "description": "音量を (100) %にする" + }, + "volume": { + "snippet": "volume", + "description": "音量" + } +} diff --git a/src/containers/ruby-tab/text-to-speech-snippets.json b/src/containers/ruby-tab/text-to-speech-snippets.json new file mode 100644 index 00000000000..bd541bade55 --- /dev/null +++ b/src/containers/ruby-tab/text-to-speech-snippets.json @@ -0,0 +1,14 @@ +{ + "text2speech.speak": { + "snippet": "text2speech.speak(\"${1:こんにちは}\")", + "description": "(こんにちは) としゃべる" + }, + "text2speech.voice=": { + "snippet": "text2speech.voice = \"${1:alto}\"", + "description": "声を (アルト▼) にする" + }, + "text2speech.language=": { + "snippet": "text2speech.language = \"${1:ja}\"", + "description": "言語を (日本語▼) にする" + } +} diff --git a/src/containers/ruby-tab/translate-snippets.json b/src/containers/ruby-tab/translate-snippets.json new file mode 100644 index 00000000000..ce682fd0647 --- /dev/null +++ b/src/containers/ruby-tab/translate-snippets.json @@ -0,0 +1,10 @@ +{ + "translate.translate": { + "snippet": "translate(\"${1:こんにちは}\", \"${2:en}\")", + "description": "(こんにちは) を (英語▼) に翻訳する" + }, + "translate.language": { + "snippet": "language", + "description": "言語" + } +} diff --git a/src/containers/ruby-tab/variables-snippets.json b/src/containers/ruby-tab/variables-snippets.json new file mode 100644 index 00000000000..a3564a5790d --- /dev/null +++ b/src/containers/ruby-tab/variables-snippets.json @@ -0,0 +1,70 @@ +{ + "$": { + "snippet": "$${1:変数}", + "description": "変数" + }, + "$=": { + "snippet": "$${1:変数} = ${2:0}", + "description": "[変数▼] を (0) にする" + }, + "$+=": { + "snippet": "$${1:変数} += ${2:1}", + "description": "[変数▼] を (1) ずつ変える" + }, + "show_variable": { + "snippet": "show_variable(\"$${1:変数}\")", + "description": "変数 [変数▼] を表示する" + }, + "hide_variable": { + "snippet": "hide_variable(\"$${1:変数}\")", + "description": "変数 [変数▼] を隠す" + }, + "list.push": { + "snippet": "list(\"$${1:リスト}\").push(\"${2:なにか}\")", + "description": "(なにか) を [リスト▼] に追加する" + }, + "list.delete_at": { + "snippet": "list(\"$${1:リスト}\").delete_at(${2:1})", + "description": "[リスト▼] の (1) 番目を削除する" + }, + "list.clear": { + "snippet": "list(\"$${1:リスト}\").clear", + "description": "[リスト▼] のすべてを削除する" + }, + "list.insert": { + "snippet": "list(\"$${1:リスト}\").insert(${2:1}, \"${3:なにか}\")", + "description": "[リスト▼] の (1) 番目に (なにか) を挿入する" + }, + "list[]=": { + "snippet": "list(\"$${1:リスト}\")[${2:1}] = \"${3:なにか}\"", + "description": "[リスト▼] の (1) 番目を (なにか) で置き換える" + }, + "list": { + "snippet": "list(\"$${1:リスト}\")", + "description": "リスト" + }, + "list[]": { + "snippet": "list(\"$${1:リスト}\")[${2:1}]", + "description": "[リスト▼] の (1) 番目" + }, + "list.index": { + "snippet": "list(\"$${1:リスト}\").index(\"${2:なにか}\")", + "description": "[リスト▼] 中の (なにか) の場所" + }, + "list.length": { + "snippet": "list(\"$${1:リスト}\").length", + "description": "[リスト▼] の長さ" + }, + "list.include?": { + "snippet": "list(\"$${1:リスト}\").include?(\"${2:なにか}\")", + "description": "[リスト▼] に (なにか) が含まれる" + }, + "show_list": { + "snippet": "show_list(\"$${1:リスト}\")", + "description": "リスト [リスト▼] を表示する" + }, + "hide_list": { + "snippet": "hide_list(\"$${1:リスト}\")", + "description": "リスト [リスト▼] を隠す" + } +} diff --git a/src/containers/ruby-tab/video-sensing-snippets.json b/src/containers/ruby-tab/video-sensing-snippets.json new file mode 100644 index 00000000000..5784388e480 --- /dev/null +++ b/src/containers/ruby-tab/video-sensing-snippets.json @@ -0,0 +1,18 @@ +{ + "video_sensing.when_video_motion>": { + "snippet": "video_sensing.when_video_motion_greater_than(${1:10}) do\n${2}\nend\n", + "description": "ビデオモーション > (10) のとき" + }, + "video_sensing.video": { + "snippet": "video_sensing.video_on(\"${1:motion}\", \"${2:this sprite}\")", + "description": "(スプライト▼) のビデオの (モーション▼)" + }, + "video_sensing.turn_video": { + "snippet": "video_sensing.video_turn(\"${1:on}\")", + "description": "ビデオを (入▼) にする" + }, + "video_sensing.video_transparency=": { + "snippet": "video_sensing.video_transparency = ${1:50}", + "description": "ビデオの透明度を (50) にする" + } +} diff --git a/src/lib/ruby-generator/mesh.js b/src/lib/ruby-generator/mesh.js index fa2fc071836..243c1def96a 100644 --- a/src/lib/ruby-generator/mesh.js +++ b/src/lib/ruby-generator/mesh.js @@ -11,7 +11,7 @@ export default function (Generator) { Generator.mesh_getSensorValue = function (block) { const name = Generator.valueToCode(block, 'NAME', Generator.ORDER_NONE) || '" "'; - return [`mesh_sensor_value(${name})`, Generator.ORDER_ATOMIC]; + return [`mesh.sensor_value(${name})`, Generator.ORDER_ATOMIC]; }; return Generator; diff --git a/src/lib/ruby-to-blocks-converter/index.js b/src/lib/ruby-to-blocks-converter/index.js index 6a647860747..6062f138e41 100644 --- a/src/lib/ruby-to-blocks-converter/index.js +++ b/src/lib/ruby-to-blocks-converter/index.js @@ -87,7 +87,6 @@ class RubyToBlocksConverter { PenConverter, EV3Converter, GdxForConverter, - MeshConverter, SmalrubotS1Converter, BoostConverter, TranslateConverter, @@ -112,7 +111,8 @@ class RubyToBlocksConverter { VideoConverter, Text2SpeechConverter, Wedo2Converter, - MicrobitMoreConverter + MicrobitMoreConverter, + MeshConverter ].forEach(x => x.register(this)); } diff --git a/src/lib/ruby-to-blocks-converter/mesh.js b/src/lib/ruby-to-blocks-converter/mesh.js index 106e79725a7..91aad6f6864 100644 --- a/src/lib/ruby-to-blocks-converter/mesh.js +++ b/src/lib/ruby-to-blocks-converter/mesh.js @@ -1,27 +1,25 @@ -/* global Opal */ -import _ from 'lodash'; +const Mesh = 'mesh'; /** * Mesh extension converter */ const MeshConverter = { - // eslint-disable-next-line no-unused-vars - onSend: function (receiver, name, args, rubyBlockArgs, rubyBlock) { - let block; - if ((this._isSelf(receiver) || receiver === Opal.nil) && !rubyBlock) { - switch (name) { - case 'mesh_sensor_value': - if (args.length === 1 && this._isStringOrBlock(args[0])) { - block = this._createBlock('mesh_getSensorValue', 'statement'); - this._addFieldInput( - block, 'NAME', 'mesh_menu_variableNames', 'variableNames', - args[0], ' ' - ); - } - break; - } - } - return block; + register: function (converter) { + converter.registerCallMethod('self', Mesh, 0, params => { + const {node} = params; + + return converter.createRubyExpressionBlock(Mesh, node); + }); + + converter.registerCallMethod(Mesh, 'sensor_value', 1, params => { + const {receiver, args} = params; + + if (!converter.isStringOrBlock(args[0])) return null; + + const block = converter.changeRubyExpressionBlock(receiver, 'mesh_getSensorValue', 'value'); + converter.addFieldInput(block, 'NAME', 'mesh_menu_variableNames', 'variableNames', args[0], ' '); + return block; + }); } }; diff --git a/test/integration/ruby-tab/extension_mesh.test.js b/test/integration/ruby-tab/extension_mesh.test.js index 53553e684b5..ca0a0975787 100644 --- a/test/integration/ruby-tab/extension_mesh.test.js +++ b/test/integration/ruby-tab/extension_mesh.test.js @@ -29,7 +29,7 @@ describe('Ruby Tab: Mesh extension blocks', () => { await loadUri(urlFor('/')); const code = dedent` - mesh_sensor_value("mesh variable") + mesh.sensor_value("mesh variable") `; await expectInterconvertBetweenCodeAndRuby(code); }); diff --git a/test/unit/lib/ruby-to-blocks-converter/mesh.test.js b/test/unit/lib/ruby-to-blocks-converter/mesh.test.js index 1503266c2cd..09241082dd9 100644 --- a/test/unit/lib/ruby-to-blocks-converter/mesh.test.js +++ b/test/unit/lib/ruby-to-blocks-converter/mesh.test.js @@ -18,7 +18,7 @@ describe('RubyToBlocksConverter/Mesh', () => { }); test('mesh_getSensorValue', () => { - code = 'mesh_sensor_value(" ")'; + code = 'mesh.sensor_value(" ")'; expected = [ { opcode: 'mesh_getSensorValue', @@ -42,9 +42,9 @@ describe('RubyToBlocksConverter/Mesh', () => { convertAndExpectToEqualBlocks(converter, target, code, expected); [ - 'mesh_sensor_value()', - 'mesh_sensor_value(1)', - 'mesh_sensor_value("arg1", "arg2")' + 'mesh.sensor_value()', + 'mesh.sensor_value(1)', + 'mesh.sensor_value("arg1", "arg2")' ].forEach(s => { convertAndExpectRubyBlockError(converter, target, s); });