自動配對括號與引號
輸入 (、'、[、" 時補上另一半,游標留在中間:
SELECT * FROM dbo.Loan WHERE LoanId IN |
↓ 打 (
SELECT * FROM dbo.Loan WHERE LoanId IN (|)一組配對有四個方向,四個都要成立才是一個功能而不是一個干擾:
| 這一次按鍵 | 行為 |
|---|---|
| 打開頭字元 | 補上結尾字元,游標留在中間 |
| 打結尾字元,而它就在游標右邊 | 跳過它,不再插一個 |
| Backspace,而游標夾在空的配對中間 | 兩個一起刪 |
| 先選一段文字再打開頭字元 | 把選取的那一段包起來,並保持選取 |
只有第一與第三個方向會出現在其他編輯器的設定名稱裡,但少了第二個方向, 使用者打完 (1, 2 順手打 ) 就得到 (1, 2));少了第四個方向, 選著一段文字打 ' 會直接把它換成一個單引號。這四個是同一件事, 因此只有一個開關:設定 → 一般 → 自動補上成對的括號與引號。
BEGIN…END 不在這裡。那是程式碼片段的守備範圍——它有縮排、 有內容、有游標停留位置,而且不是「每一次按鍵都要判斷」的東西。
哪些字元會配對
(/)、'/'、[/]、"/",就這四組。
< 與 > 刻意不算:它們在 T-SQL 裡絕大多數時候是比較運算子,a < b 每打一次 就補一個右角括號是純粹的干擾。方括號則相反——它是識別字的跳脫寫法。 建議清單在方括號裡照樣開,提交時連補上的 ] 一起換掉,見 插入文字。
什麼時候不補
補一個多餘的字元,使用者當場就得回頭刪掉——那是打字節奏被打斷的唯一原因, 所以「不補」的條件比「補」重要:
| 情形 | 為什麼 |
|---|---|
游標右邊還有字(WHERE |CopyNo = 1) | 補上的那一半會夾在中間,接著打的每一個字都在配對外面 |
| 游標在字串、註解或方括號識別字裡 | 那裡的括號與引號是內容而不是語法,補上等於竄改字面值 |
| 建議清單開著,而這個字元是提交鍵 | 吞掉它就提交不了 |
| 程式碼片段的欄位 session 開著 | 從外部改緩衝區會打斷欄位標記與同名欄位同步 |
| 游標在虛擬空白裡(行尾之後) | 寫進去的字元會出現在看得到的位置之前 |
| 方塊選取或多重選取 | 「包夾」在多段選取上沒有明確語意 |
「右邊還有字」的例外是邊界字元:空白、換行、)、]、,、;。 VALUES (1, |, 3) 這種補完中間一格、以及 fn(|) 裡再包一層都要成立。
清單開著本身不是理由:分隔字元都不是提交鍵(提交字元只有 SqlAsyncCompletionCommitManager.CommitsOn 一份),那一次按鍵本來就結束正在打的詞元。 一律讓開的症狀是 RESULT SETS 開著清單時打 ( 不補、再打一個才補成 ((),以及 (|) 開著清單時按 Backspace 留下 )。四個方向動緩衝區前都先收掉清單——否則補上的 字元落進 session 的適用範圍——新位置的清單由重開清單接手。
建議清單提交進來的左括號
內建函式與帶參數的型別,插入文字自己就帶著左括號(GETDATE(、varchar(), 平台只會照著寫進去。少了這一條,提交完留在編輯器裡的是 SELECT GETDATE( ——一句跑不掉的語法錯誤,而使用者每選一次函式就得手動補一個右括號:
SELECT GET|
↓ 從清單提交 GETDATE
SELECT GETDATE(|)補不補問的是同一份規則(右邊要是邊界、不能在字串或註解裡),所以 SELECT |CopyNo 那種右邊還有字的位置照樣不補。使用者自訂函式不走這裡: 它的括號是整對補上的,不受這一頁的開關與條件影響; 程式碼片段的括號寫在樣板裡,也不缺這一個。
右括號併進提交的那一次編輯,因此這裡的 Ctrl+Z 一次就連它一起收掉——與打字時 要按兩次不同,那一次有平台的另一半要等,這一次沒有。補上的字元同樣記進追蹤清單, 接著打 ) 是跳過去而不是插出 GETDATE())。
跳過的必須是自己補的那一個
文字上分不出「這個 ) 是我補的」還是「使用者自己打的」,而兩者要的行為相反: 游標停在一個既有的 ) 前面打右括號,要的是插進去,不是跳過去。 'abc|' 想補一個跳脫用的單引號更是如此。
所以每補一個結尾字元就記一個 ITrackingPoint,只有記錄裡的那一個才跳得過、 才會被 Backspace 一起帶走。記錄跟著文字移動,使用者在配對中間繼續打字也跟得住; 每次使用前先清掉已經對不上的(被刪掉、被別的編輯換掉),所以「跳過」與 「整對刪掉」永遠只作用在真的還在那裡的字元上。
判斷與記錄刻意分開:什麼時候該配對只看文字,全部在 Core/Pairing/SqlAutoPairAnalyzer,測得到;哪一個是我補的是編輯器的狀態, 留在 Ssms22/Editor/SqlAutoPairing。
復原要按兩次
補結尾字元時只插入結尾字元、把游標留在它前面,開頭字元仍然由編輯器自己插入。 這樣選取取代、覆寫模式與虛擬空白都還是平台的行為,不必在按鍵路徑上重寫一份。
代價是那是兩次編輯,Ctrl+Z 要按兩次才連補上的字元一起收掉。自己插入兩個字元 可以合成一次復原,但要接管的東西比省下的那一次多得多。Backspace 刪整對沒有 這個問題——那一次沒有平台的另一半要等,所以合成一次編輯。