Skip to content

Latest commit

 

History

1,466 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Semorphe Logo

Semorphe

同一支程式,三種看法——程式碼、流程圖、積木。改哪一邊都算數,並且即時同步!

TypeScript Blockly MIT License


把真的 C++ 或 Python 貼進去,它變成積木;拖一塊積木,程式碼跟著變; 切到流程圖,它畫的是同一支程式。

🔴 三邊都是入口,不是「一個能改 + 兩個唯讀」

你改程式碼  →  積木與流程當場跟著變
你改積木    →  程式碼與流程當場跟著變
你改流程    →  程式碼與積木當場跟著變

不是按一顆「轉換」按鈕,也不是存檔才更新——打字的當下另外兩邊就在動

馬上試(不用安裝)

打一段 C++ → 程式碼、流程、積木同時長出來 → 三邊各改一次,另外兩邊當場跟著變 → 按執行,底下的主控台印出來

打一段 C++ → 三邊同時長出來 → 在程式碼、在積木、在流程各改一次,另外兩邊當場跟著變 → 按執行,它真的會跑

它跟別的積木工具差在哪

多數積木工具是單向的:積木能變成程式碼,而程式碼變不回積木。 少數做到雙向的(例如 MakeCode),走出它支援的子集就回不去。

Semorphe 想做的是另一件事:

三個畫面都能編輯,而且即時 程式碼、流程圖、積木任何一邊改,另外兩邊當場跟上——不是按一顆「轉換」,也不是存檔才更新
吃的是真的程式碼 貼一段你手邊的 .cpp.py 進去,不是玩具子集
接不住的時候它會說 認不出來的語法不會被丟掉,也不會被猜——它變成一顆灰色積木,原文一字不動地放在裡面

第三點聽起來不像賣點,而它是:它保證這個工具不會安靜地弄壞你的檔案。

貼一段含 goto 的 C++ → 認不出來的那兩行變成灰色積木,原文一字不動地放在裡面 → 在別的地方改一個數字,灰色那兩塊原封不動

認不出來的 goto 變成一顆寫著原文的積木 → 在別的地方改一個數字 → 它一個字都沒動

🔴 積木長在 Arduino IDE 裡面——不是另一個程式

Arduino IDE 2.3.8 裡:左邊是 Arduino 自己的編輯器開著 sketch_sep3a.ino,中間是「Semorphe 積木」分頁,右邊是「Semorphe 流程」分頁,三邊顯示同一支呼吸燈程式;功能表列上有「Semorphe 主控台」「Semorphe 變數」

這是 Arduino IDE 2.3.8 本人。左邊是它自己的編輯器,中間與右邊是 它的編輯器分頁——同一個 .ino 檔,三邊即時同步

Arduino + 積木的工具幾乎都住在 Arduino IDE 外面:

形狀 例子
另一個網站 Tinkercad Circuits · Wokwi · Ardublockly
另一個桌面程式 mBlock · S4A(Scratch for Arduino)
IDE 的工具外掛 ArduBlock(Arduino IDE 1.x,而它開的仍是一個獨立視窗

共同點是同一件事:積木不在你正在用的那個編輯器裡。於是流程長這樣—— 在那邊拼 → 匯出 .ino → 切回 Arduino IDE → 燒錄。而那個「→」每一個都要錢:

兩個程式、兩份檔案     改了哪一邊要自己記,而記錯了沒有人會說
燒錄要換視窗           學生的注意力每次都要搬一次家
函式庫/開發板/序列埠  Arduino IDE 裡有的,外面那個要自己再做一份(而且永遠落後)
教的環境 ≠ 用的環境     學生「畢業」的那天要重學一次工具

Semorphe 是 Arduino IDE 的延伸模組,所以上面那四行都不存在:

同一個程式 裝上去就好,不用開第二個視窗、不用註冊帳號
同一個檔 那是 IDE 開著的 sketch_sep3a.ino——不是匯出的一份拷貝
IDE 的原生分頁 積木與流程是編輯器分頁(拖到哪一欄都行),主控台與變數在 panel 那一排,與序列埠監控並排
三邊都能改 改積木 → .ino 當場變;改 .ino → 積木與流程當場變
編譯與燒錄照舊 左上角那兩顆 ✓ → 還是 Arduino 自己的——我們沒有接管它,也不想:函式庫、開發板管理員、序列埠都留在原地
同一份延伸模組 VSCode 與 Arduino IDE 共用(Arduino IDE 2.x 是 Theia,吃 VSCode 的延伸模組)

⚠️ 而它不是「把我們的畫面塞進去」:狀態列上那個 同步中(vscode-code-view) 是真的——文字那一側的真相是 IDE 的文件, 我們只送範圍編輯回去,所以你的檔案不會被我們整份覆蓋(見〈IDE 延伸模組〉)。

我們沒有找到第二個「積木活在官方 IDE 裡、對使用者自己的檔、而且雙向」的工具。 如果你知道有,請開一個 issue 告訴我們——那會是一個很有用的比較。

📱 手機、平板也能用——沒有電腦的地方一樣學得了程式

同一個網址(https://semorphe.com/)在手機上是專為觸控排的版面,不是把桌機 畫面縮小:

四個分頁 程式碼 · 流程 · 積木 · 主控台——一次專心一件事
拇指按得到 選單從下面升起來(頂端置中的清單,單手拿著手機按不到)
不用安裝、不用帳號 開瀏覽器就是全部。⚠️ 而它離線也能跑——第一次載完之後不再向外要任何東西
真的能執行 程式在你的裝置上跑,不是送到某個伺服器

🔴 這件事對誰重要:一間沒有電腦教室的學校、一個只有家長手機的孩子、 一節在走廊上的補課。程式教育的門檻常常不是能力,是那台機器。

而它不是「手機版的閹割功能表」:三邊同步、執行、課程、鷹架, 在手機上是同一套東西——因為它們本來就是同一份程式碼。

還有這些

  • 由淺入深 — 66 堂課、6 條軌道(C++ 入門/進階、C 銜接、Python 入門/銜接、Arduino 專題)。 工具箱只給這一堂該有的積木
  • 骨架看得到、拆不壞#includeint main() 這些「不是你寫的」那幾行, 可以藏起來、可以淡淡地顯示(看得到而拖不動)、也可以整個交給學生
  • 多種程式碼風格 — APCS(cout/cin)、競賽(printf/scanf)、Google、Python 一鍵切換
  • 硬體 — 8 塊板子(Uno/Nano/ESP32 家族/D1 mini…), 每塊板子有自己的腳位、常數與函式庫標頭
  • 離線可用 — 跑起來之後不會向外要任何東西(有一條測試守著)
  • IDE 延伸模組 — VSCode 與 Arduino IDE 共用同一份

課程:讀一段,然後直接動手

66 堂課的課文是靜態頁——純 HTML、不載編輯器、打開就在那裡 (semorphe.com/lessons/)。每一頁底下有一顆「在編輯器打開這一課」, 而編輯器裡的章節選單有一顆「📖 看這一課的課文」——兩邊互相指得回去。

課程索引 → 一條軌道的課表 → 一堂課的課文(上一課/下一課)→ 在編輯器打開這一課 → 工具箱只剩這一課要的、鷹架是淡的 → 照課文打一段,積木長出來

課文 → 「在編輯器打開這一課」 → 工具箱只剩這一課要的、鷹架是淡的 → 照著打,積木長出來

課文 每一課一頁,/lessons/<軌道>/<課>/——有上一課/下一課,不跨軌道
一堂課會做什麼 釘住目標(語言/板子)、收窄工具箱到這一課的元件、決定鷹架露多少
一條連結就夠 ?lesson=<軌道>/<課> — 老師貼出去,學生點開就是那一課的環境

那 66 堂課的課文早就寫好了(13 萬字),而在 2026-09-03 之前 產品裡沒有任何讀者——唯二讀它的是兩支測試,而它們讀完就丟。

畫面怎麼排

三個投影各佔一欄,而哪一格顯示哪一層由你決定

三張版面 專注(一次一個)/對照(程式碼 + 積木)/三欄
每一格自己選 每一格的頭上有一顆下拉「這一格顯示」——選到別處的就對調
主控台在底下 它不是投影,是執行的輸出——所以它是編輯區底下一條獨立、全寬、關得掉的底條(主控台/變數兩頁)

關掉主控台 → 按執行,它自己帶著輸出回來 → 用「這一格顯示」把兩格對調 → 切成對照,收成兩欄

關掉主控台 → 按執行,它自己回來 → 用「這一格顯示」把兩格對調 → 切「對照」收成兩欄

主控台關得掉,而它一定回得來:版面選單叫得回來,而程式一有輸出它自己就回來。

⚠️ 而 IDE 裡這幾件事由 IDE 自己排(分頁、分欄都是宿主的東西), 所以那裡的「版面」是一句請求,不是我們自己畫的格子——見下面〈IDE 延伸模組〉。

⚠️ 現在做不到什麼

寫在這裡,因為你遲早會撞到:

  • 語言只有 C++(含 C 方言)與 Python。加一個語言是一整刀,不是設定
  • 認不出來的語法會降級成灰色積木。它跑得動、來回轉換不會壞,但它在積木上就是一塊灰的
  • Arduino IDE 沒有自動更新——它把擴充市集對使用者關掉了,只能手動放 .vsix (步驟見安裝⚠️ 更新時有一個少了會安靜失敗的步驟)
  • 流程圖是新的(2026-08),它的編輯能力還在長
  • Arduino IDE 排不出等寬的三欄——它沒有那顆指令(查證過),要手動拖分隔線

安裝

不想裝的話,網頁版就是完整的同一套東西—— 以下只在你想「在自己的編輯器裡用」時才需要。

VSCode

方法一:市集(會自動更新)

擴充商店搜 Semorphe,或直接開 市集頁面

方法二:.vsix

Releases 下載 semorphe-vscode-<版本>.vsix,然後任選一種:

code --install-extension semorphe-vscode-0.16.0.vsix

或在 VSCode 裡:命令面板(Cmd/Ctrl + Shift + P)→ Extensions: Install from VSIX… → 選那個檔。

⚠️ 這樣裝的不會自動更新,新版要再做一次。

Arduino IDE

🔴 Arduino IDE 沒有安裝擴充的介面——它是 Theia 做的,而它把擴充市集 對使用者關掉了。所以只能把檔案放進去:

  1. Releases 下載 semorphe-vscode-<版本>.vsix

  2. 完全關掉 Arduino IDE

  3. 把檔案放進這個資料夾(不存在就自己建):

    macOS / Linux ~/.arduinoIDE/plugins/
    Windows %USERPROFILE%\.arduinoIDE\plugins\
  4. 重開 Arduino IDE——它會自己解壓——命令面板 → Semorphe: 開啟積木面板

更新:一樣的四步,而第 3 步先把舊的 semorphe-vscode-*.vsix 刪掉。 檔名帶版本是有意的:Theia 的解壓快取以名字為鍵,版本進到名字裡, 新舊就不會混。

🪦 這不是官方支援的安裝方式,Arduino IDE 換一版就可能失效。 如果哪天它不動了,網頁版是同一套東西。

裝好之後,怎麼把它叫出來

兩個宿主一模一樣(Arduino IDE 是 Theia,吃同一份擴充),只有介面位置略有不同。

① 開一個檔

.ino · .cpp · .c · .h · .py——新檔案也行,把語言選成 C++ 或 Python 就會出現。

② 叫出積木或流程

怎麼叫 做什麼
編輯器右上角的 <Σ> 圖示 開積木——⚠️ 只在上面那幾種檔案上出現
命令面板(Cmd/Ctrl+Shift+P)→ Semorphe: 開啟積木面板 同上
命令面板 → Semorphe: 開啟流程面板 開流程圖

它們是編輯器分頁——拖到右邊、拖到下面、拖到另一個視窗都可以, 就跟你平常拖任何一個分頁一樣。

③ 主控台與變數

它們在 panel 那一排(與終端機/問題/輸出並排),叫做 Semorphe 主控台Semorphe 變數

VSCode 檢視 → 開啟檢視… → 搜 Semorphe;或命令面板 → Semorphe: 主控台
Arduino IDE 它們直接在最上面那條功能表列

⚠️ 主控台關得掉,而它一定回得來:版面選單叫得回來,而程式一有輸出它自己就回來。

④ 其餘的控制項

在哪 有什麼
狀態列(右下) 目標(語言/板子)· 課程 · 章節 · 鷹架 · 風格 · 積木外觀 · 介面語言 · 版面
標題列(分頁右上) ▷ 執行 · ↩ 還原 · ↪ 重做
每一格的右上 「這一格顯示哪一層」——選到別處的就對調

🔴 版面(專注/對照/三欄)是一句請求:分頁與分欄是 IDE 自己的東西, 我們只能請它把某一格放到第幾欄——所以三個宿主的版面清單逐字相同。

出事的時候

命令面板 → Semorphe: 顯示同步診斷——它會印出寫入歷程、鏡像對帳、宿主能力。 回報問題時把那一段貼上來,比任何描述都有用。

從原始碼跑起來(開發者)

npm install
npm run dev          # 開發伺服器
npm test             # 單元/整合測試
npm run test:e2e     # Playwright
npm run build        # tsc + vite build
npm run build:vscode # 打包 IDE 延伸模組
npm run install:ide  # 裝進本機的 VSCode / Arduino IDE

架構

src/
├── core/         # 語義樹本身、兩個方向的轉換引擎、各語言登記自己資料的地方
├── components/   # 一顆「程式概念」一個資料夾(if、迴圈、印出來…)
├── languages/    # 每個語言一包:解析器、課程、目標板子、程式碼風格、工具箱分類
├── interpreter/  # 語義樹直譯器
├── ui/           # 三個面板(積木 / 流程圖 / 程式碼)與它們之間的同步
└── vscode/       # IDE 延伸模組(VSCode + Arduino IDE 共用)

為什麼三邊不會各說各話

程式碼 ──讀進來──→ 語義樹 ──寫回去──→ 程式碼
                     │
                     ├──→ 積木
                     └──→ 流程圖

中間那棵樹是唯一的真相。 三個畫面都從它算出來,也都改得動它, 而沒有任何一條捷徑——不會有「積木直接翻成程式碼」這種路。

那正是多數同類工具會漂掉的地方:兩邊各自維護一份翻譯, 改了一邊而另一邊沒跟上,久了就對不起來。

專案裡把那三個畫面叫做投影——一個投影是從真相算出來的, 所以它可以少(積木上看不到 #include),但不會多出真相裡沒有的東西

兩句標語:「唯一真實,各式投影。」 教育情境的那句是「解構語法之散,重塑形態之模」。

一顆「元件」是什麼

一個程式概念(ifwhile、印出來、變數指派…)= 一個資料夾。 專案裡叫它膠囊,因為它把那個概念的每一面都裝在同一處:

src/components/python/loop_while/          ← Python 的 while 迴圈
  component.json        它叫什麼、有哪些欄位、可以接哪些子積木
  lift-pattern.json     怎麼從【程式碼】認出它
  generate.ts           怎麼把它寫回【程式碼】
  forms/blocks.json     它畫成【積木】長什麼樣(同一份也用來從積木讀回資料)
  execute.ts            執行它會發生什麼事
  labels/zh-TW.json     積木上的中文字(另有 en.json)
  spec.test.ts          它自己的測試

那五件事(認出來 · 寫回去 · 畫出來 · 讀回來 · 執行)就是一顆元件的全部—— 少任何一件都要在 component.json寫明為什麼沒有, 好讓「刻意不做」與「忘了做」分得出來。

🟢 加一顆元件=新增一個資料夾。 系統自己會掃到它, 不需要去別的檔案登記——所以加東西不會弄壞既有的東西。

AI 輔助的開發管線

Semorphe 把重複的開發流程寫成 skill——給 AI 助理看的操作手冊 (原始檔在 knowledge/skills/,用符號連結出現在 .claude/skills/)。

它們不是模板,是這個專案的記憶:裡面幾乎每一條規矩後面都有一次具體的翻車, 而那次翻車就寫在旁邊。

加一顆元件

/component-pipeline {lang} {target}

它串起六個階段:

階段 Skill 做什麼
1 component-discover 查這個函式庫/語法有哪些概念,該怎麼命名、放在第幾關
2 component-generate 產出上面那個資料夾裡的每一個檔
3 component-roundtrip 程式碼 → 積木 → 再變回程式碼,跑起來比對輸出
4 component-fuzz 出題的 AI 看不到實作,只有這樣它才會問你不會問自己的問題
5 component-integrate 最終關卡:型別檢查、全套測試、來回轉換全部通過才算數
6 verify-in-browser 🔴 打開瀏覽器【用眼睛看】——前五關全綠而使用者一看就發現的缺陷

加一個語言

/add-language

⚠️ 與上面那條是不同的路——上面那條假設語言已經在了

從零加一個語言要處理的是另一批東西:接上解析器、 讓系統知道每條辨識規則是寫給哪個語法的(少了這一步, 新語言的 if 會被當成舊語言的 if,而且不會有任何錯誤訊息)、 以及四件「這個語言怎麼寫註解」「認不出來時用哪顆灰色積木」之類的登記。

其他

Skill 用途
component-refactor 檢查與修復既有的元件(它讀的是自動檢查產生的報表,不是自己重掃)
component-rename 大規模改名(上千處引用)——一定要附使用者舊存檔的轉換
build-guardrail 把一條「應該要這樣」的規矩,變成一支做錯就會變紅的測試
manual-acceptance 有些規矩測不起來(「按下去看到什麼」)——寫成一張人按得完的清單
diagnose-in-browser 已經知道有問題時,在瀏覽器裡查出是哪一段
ship-extension 把一次改動交到兩個 IDE 手上(這條流程跑了九次才被固定下來)

完整清單與各自的緣起見 knowledge/skills/README.md

IDE 延伸模組

已出貨,VSCode 與 Arduino IDE(Theia 1.57)共用同一份 .vsix。 (畫面見上面〈積木長在 Arduino IDE 裡面〉。)

面板【就是】網頁版的 App,只是程式碼那一格換成宿主的編輯器

而 2026-09 之後它長成宿主原生的形狀:

這一層 住在哪
程式碼 IDE 自己的編輯器
積木 · 流程 各自一個編輯器分頁semorphe.openBlocks / openFlow
主控台 · 變數 panel 區的兩個原生分頁,與終端機/問題並排
控制項 狀態列(目標、課程、風格、版面…)+ 標題列(▷ 執行、↩↪)

三個宿主(網頁、VSCode、Arduino IDE)的版面清單逐字相同,因為三張版面 全是純欄——排它只需要「把這一格放到第幾欄」,而那是每個宿主都做得到的 最小動作。

🔴 上一版有一張「十字」(四格,主控台佔一格),而它是唯一需要編輯區有 第二列的版面——Theia 沒有 setEditorLayout,那一格排不出來。 拿掉它之後,三個宿主第一次是同一個形狀。 見 history/202

⚠️ 兩個宿主真的不一樣的地方

都是量出來的(bundle 裡查證 + 實測),而不是猜的:

VSCode Arduino IDE
三欄等寬 ✅ 自動 ❌ 它沒有「平均欄寬」那顆指令——要手動拖
「這一格改顯示程式碼」 ❌ 不列入選單(它關不掉多開的那個檔案分頁)
面板現在開著沒有 ✅ 答得出 ❌ 答不出 → 選單改用中性的名字(不假裝知道)

名單住在 src/vscode/host-quirks.ts每一筆都附病歷,而且都有「實測會降級」 的第二層——⚠️ 其餘每一個檔都不准問「你是誰」(第六十三條護欄擋著)。

npm run build:vscode   # 產出 .vsix
npm run install:ide    # 裝進本機兩個 IDE

⚠️ 開發時不要自己複製 .vsix——install:ide 會處理兩邊的快取失效 (Theia 以資料夾名字為鍵、VSCode 以 (id, version) 為鍵,兩個都是 「換了而不重載,且不報錯」)。使用者的手動步驟見安裝

🪦 2026-03 的那個原型已於 2026-08-16 退休(教訓見 knowledge/history/069), 現在這一份是 2026-08 重做的。

給 AI agent 與貢獻者

這個 repo 把「為什麼」寫下來了,而且它是權威的,不是裝飾。動手之前依序讀:

  1. CLAUDE.md — 什麼時候跑什麼測試(⚠️ 那張表有一列是紅字的,別跳過)
  2. knowledge/principles.md — 不可協商的那幾條
  3. knowledge/vision.md — 下一步在哪
  4. knowledge/experience.md — 前人踩過的坑(找與你這一刀相關的)

三件會讓一次改動被擋下來的事:

  • 改了規範而沒有機械化的檢查 — 見 knowledge/skills/build-guardrail。 這個專案有 113 條護欄(數字由 tests/integration/audit-guardrail-count.test.ts 算出來,而它會擋住這一行變成過期的數字),而它們的存在理由是同一句: 一條規範沒有機械化的檢查,它本身就是殼——而殼看起來像完成。
  • 改了使用者按得到的東西而沒跑 npm run test:e2e — 全套單元測試綠擋不住
  • 把同一個決定實作第二次 — 這裡發生過六次,見 history/188

⚠️knowledge/skills/ 裡有 19 支學過的流程(加語言、生課程、退場一顆積木…)。 你要做的事如果在裡面,照著走,不要重想——每一條規矩後面都有一次具體的翻車。

專案知識庫

這個專案的 why 記在 knowledge/,而不是散在 commit 訊息裡:

principles.md 根公理與衍生原則——不可協商的那些
vision.md 定位與還活著的路線圖(完成的收斂成一行 + 指標)
experience.md 從翻車裡蒸餾出來的教訓
concepts/ 反覆出現的概念,各自一篇
history/ 「為什麼變成現在這樣」的因果紀錄——每次改變都留一筆
episodes/ 值得重看的完整除錯現場
draft/ 還沒定案的想法(沒有被用到就會自然淡掉)

⚠️ 接手任何工作之前先讀那三個檔——這個專案的多數規矩都有一次具體的災難在後面, 而那個災難不在程式碼裡

授權

MIT

About

同一支程式,三種看法——程式碼、流程圖、積木。改哪一邊都算數,並且即時同步!

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages