現已釋出!閱讀關於 11 月新增功能和修復的內容。

推出 Markdown 語言伺服器

2022 年 8 月 16 日,作者:Matt Bierner,@MattBierner

2016 年我加入 Visual Studio Code 時,Markdown 支援是我負責的第一個功能。哇,真的已經六年了嗎?這是一個完美的結合。我使用 Markdown 的時間夠久了,以至於我經常發現自己充滿希望地在 Twitter、Outlook 以及我的游標所停留的幾乎每一個文字框中輸入反引號和星號。多年來,發展 VS Code 內建的 Markdown 支援,並看到我們的 Markdown 擴充套件如何直接或間接地塑造了 Webview 和筆記本等核心功能,讓我非常有成就感。

這就是為什麼我很高興分享一個我過去半年一直在悄悄推進的專案,一個我認為代表著 VS Code Markdown 工具下一階段的專案:Markdown 語言伺服器。透過這個語言伺服器,我們正在將 VS Code 的大部分內建 Markdown 語言工具——從文件大綱到智慧摺疊再到路徑補全——提供給其他編輯器和工具。我們的目標是利用通常與程式語言相關的智慧功能來推動 Markdown 工具的發展。

Markdown 語言伺服器工作分為兩個新的(且名稱相似!)開源庫

雖然這些庫仍處於早期階段,但它們已經被 VS Code 1.70+ 使用(希望你甚至沒有注意到 :-))。我們甚至從這次轉換中看到了一些好處,例如將 Markdown 工具移到單獨的程序中,這樣它就不會阻塞其他擴充套件。

但在我跑得太遠之前,也許你會想知道:為什麼需要 Markdown 語言伺服器?說實話,我自己也花了這六年的時間才接受這個想法。這同樣記錄了我從將 Markdown 簡單地視為帶有幾個星號、方括號和井號來活躍氣氛的純文字,演變為將其理解為一種標記語言,並且可以受益於我們為 TypeScript 或 Python 等程式語言提供的許多相同工具。

深入瞭解 Markdown 工具

在我發現 VS Code 之前,我主要使用一個簡單的文字編輯器進行編碼。這意味著我必須記住符號名稱,並且每次使用它們時都要輸入一遍。如果我想重新命名一個變數,我會進行文字查詢/替換,並希望我的單元測試能捕獲不可避免的名稱拼寫錯誤或被破壞的情況。這是一種緩慢且不可靠的工作方式,但我很滿足,因為我不知道情況可以變得更好。直到我真正接觸到更智慧的工具之後,才明白我的工作流程有多麼原始。

最近我對 Markdown 有了同樣的領悟。多年來,我一直滿足於使用 VS Code 相對簡單的 Markdown 編輯器。我對語法高亮和內建的 Markdown 預覽感到滿意。文件大綱和可點選的編輯器連結只是額外的獎勵。我已經習慣於手動編寫連結。我已經接受了如果我更改了標題名稱,我需要進行文字搜尋來更新所有指向該標題的連結。而且因為我將 Markdown 視為僅僅是花哨的純文字,所以我甚至無法想象存在更好的方式。

但有一天,在我第一百次輸錯圖片路徑之後,我終於明白了:這不好玩!為什麼我要浪費時間手動輸入和驗證這些連結?這就是工具的用途!我想要的不僅僅是任何工具,我想要的是一個能幫助我將 Markdown 作為文字閱讀和編寫,而不是將 Markdown 原始碼隱藏在某種所見即所得 (WYSIWYG) 式的 UI 魔法之後的工具。這非常符合 VS Code 的精神以及我們對程式語言支援的思考方式。為什麼我們為傳統程式語言提供的許多相同智慧功能不適用於 Markdown 呢?第二天我就開始著手開發連結補全功能。

連結補全是幫助你編寫指向當前檔案內標題或工作區中其他檔案的連結的建議。我甚至添加了對補全指向其他 Markdown 檔案內標題連結的支援。太棒了!這是一個很小的補充,但對我的生產力產生了巨大的影響。很快我就無法想象沒有它我將如何生活。

對 Markdown 補全功能的成功感到興奮不已,我沉醉於想象接下來可以將哪些其他的語言智慧帶給 Markdown。我設想自己自信地按下 F2 鍵來安全地重新命名標題。我白日夢般地想象著紅色的波浪線穿過模糊的文字海洋,幫助識別無效連結。這一切看起來如此顯而易見!為什麼我幾年前沒有想到呢?我開始將 Markdown 理解為結構化文字而不僅僅是純文字,並且更好的 Markdown 工具的可能性似乎無窮無盡。

Markdown 語言功能

我不會用每個新功能背後的故事來讓你感到無聊,也不會深入探討它們是如何實現的血腥細節。簡單地說,我採取了增量方法,這使得在我投入到 VS Code Markdown 支援的有限時間內,所有的努力都成為可能。例如,我沒有直接跳到構建重新命名支援,而是首先實現了查詢所有引用的可靠版本(因為如果你想重新命名一個符號,你首先需要知道所有引用它的地方)。以增量方式工作並將每個功能建立在彼此之上也幫助我在實現新功能時測試舊功能。例如,在連結上實現重新命名幫助我捕獲了大量關於連結檢測的錯誤。(這種方法唯一的缺點是認識到你將你“如此優雅”的塔建立在幾個非常複雜的正則表示式之上)。

當實驗性的無效檔案/圖片連結報告支援在春末推出時,我退後一步審視了我的工作。這套 Markdown 語言功能現在包括:

  • 文件大綱
  • 工作區符號
  • 文件連結
  • 智慧摺疊
  • 智慧選擇
  • 補全
  • 重新命名
  • 查詢所有引用
  • 轉到定義
  • 損壞連結診斷
  • 檔案移動/重新命名時更新連結

我知道這些新工具將使使用 Markdown 更快、更安全。但當我回顧這組程式語言常見功能列表時,一個想法一直在困擾著我。幾個月前我把它當作荒謬的想法而否決了,但現在,當我再次思考它時,我意識到也許終於到了推出 Markdown 語言伺服器的時候了。

你在服務中嗎?

到 2022 年春末,VS Code 的所有 Markdown 工具仍然在常規擴充套件 API 上執行。雖然我想探索將所有這些工具轉移到一個真正的語言伺服器上,但做出改變會產生真正的工程成本。我需要確保這是值得的。

我為此來回糾結了一個多月。儘管現有程式碼狀況良好,但仍存在許多未知因素。如果我做到一半才意識到行不通怎麼辦?我以前甚至從未認真地從事過語言伺服器的工作。

在我爭論這一切時,我讓自己忙於重構 Markdown 擴充套件原始碼,就像它將被移到語言伺服器上一樣。我嘗試隔離對 VS Code 擴充套件 API 的依賴,我將更多邏輯切換為使用服務注入,並確保測試不依賴於檔案系統。這樣即使我從未進行語言伺服器的嘗試,至少我清理了程式碼庫。

一些考慮因素最終說服我,Markdown 語言伺服器是正確的下一步。首先是一個相當平庸的原因:我發現高效地實現 Markdown 檔案連結診斷非常具有挑戰性。在像 vscode-docs 這樣的大型 Markdown 工作區中,我不斷地意外阻塞擴充套件主機幾百毫秒。這不好。另一方面,語言伺服器作為自己的程序執行。不僅如此,語言伺服器現在還有一種新的拉取模型用於診斷,我很興奮嘗試一下。

然後還有更崇高的原因。例如,Markdown 語言伺服器將對其他編輯器和工具有用。這包括 VS Code 團隊釋出的另一個編輯器:Monaco!更不用說像 Markdown CLI 工具這樣的可能性了。如果我沒有時間自己構建這樣的工具,也許其他人可以使用語言伺服器作為起點。我為 VS Code 的 Markdown 工具付出了很多努力,如果所有這些工作也能造福他人,那將是很棒的事情。

透過提供一個新的語言伺服器,我也許可以啟動一項圍繞改進 Markdown 工具的共同努力。VS Code 既是開源軟體的 prolific 生產者也是使用者,我看到了這類專案帶來的明顯好處。一個開源的 Markdown 語言伺服器將幫助其他編輯器,反過來也會邀請貢獻,最終將幫助 VS Code!與其讓每個編輯器/工具重複努力實現自己的 Markdown 支援,不如讓語言伺服器將開發人員聚集在一起,共同完成一個能使每個人受益的更大專案。

所有這些宏偉的思考,如果沒有一個實際構建語言伺服器的計劃,都是無關緊要的。即使經過我所有的重構,將程式碼移到語言伺服器上仍將是一項大量的工作!這看起來令人不知所措,直到我意識到不必一次性完成所有工作。我可以增量地構建伺服器,一次將一個功能從 VS Code Markdown 擴充套件遷移到新的 Markdown 語言伺服器。如果我做得對,我可以簽入每一個小的增量遷移,以便使用者在構建過程中測試新的語言伺服器。理想情況下,當功能從擴充套件遷移到語言伺服器時,使用者永遠不會注意到。

也許這很明顯,但我已經成為這種增量方法進行大型程式碼更改的忠實信徒。沒有十萬行程式碼的 PR 或持續數月(或數年!)的龐大功能分支。相反,對 main 進行一系列小的、安全的更改。如果一切按計劃進行,所有這些工作所達到的提交應該是平淡無奇的。這是我們逐步在整個 VS Code 程式碼庫中使用嚴格空值檢查所採取的方法,這也是我認為我可以快速且儘可能少地折騰將所有 VS Code 的 Markdown 工具轉移到新語言伺服器的方法。

劇透警告:它奏效了!我一次遷移一個語言功能。我邊學邊做,在需要時進行重構。診斷是最後一個遷移的功能,因為我不僅將它們遷移到語言伺服器,還重寫了它們以使用語言伺服器新的拉取診斷模型。整個工作的最後一次提交主要刪除了 Markdown 擴充套件中現在未使用的程式碼。因此,今天,如果你使用的是 VS Code 1.70+,幾乎所有 Markdown 語言功能都使用新的語言伺服器。

共同構建更好的 Markdown 工具

在很多方面,過去六個月裡 VS Code Markdown 工具的進步比我過去六年在這個領域工作中所取得的進步還要多。今天我們正在提供許多新工具,其中一些以前從未用於 Markdown。許多這些功能使最隨意的 Markdown 閱讀者和編寫者受益,而其他功能則只有高階使用者才能體會到。然而,儘管取得了所有這些進展,我知道我們才剛剛開始探索 Markdown 工具的可能性。

真正讓我興奮的是 Markdown 語言伺服器現在不僅僅是一個 VS Code 專案。透過使我們的 Markdown 工具易於使用,我希望我們可以幫助推動每個人的 Markdown 工具向前發展。這些開源專案是邀請大家共同構建 Markdown 工具未來的邀請。如果你有興趣做出貢獻,請檢視這些新專案,看看你可以用它們建立什麼。你可以提交錯誤報告和功能請求,甚至可以提交 PR!有無數我甚至還沒有想到的智慧 Markdown 語言功能。讓我們一起構建它們!

如果你有興趣檢視原始碼或做出貢獻,可以在 GitHub 和 npm 上找到 Markdown 語言服務和伺服器

編碼愉快!

Matt Bierner,@MattBierner

© . This site is unofficial and not affiliated with Microsoft.