..
配合使 \ 用,使其中的 code 在 source 中仍可用 indent 保持美觀,但是執行前用 \ unindent 命令把前導的 white spaces 都過濾掉以配合 區段的原意。 \ 本來以為很簡單,沒想到搞成一整個檔案! hcchen 2015/11/30 \ ---------- Tab to spaces for .. ------------------------------- s" " value tab-spaces // ( -- value ) Tab spaces setting for .. tag. : (^tab>spaces) ( "string" -- "cooked" ) \ Replace ^\t* with spaces tab-spaces swap ( tab-spaces "input" ) \ 先把 "^\t*\S.*"+'x' 切開成 "^\t*", "\S.*x". \ Where the dummy leading \t and tailing x guarantees the pattern js> '\t' swap + char x + :> match(/(^\t*)(.*)/) ( tab-spaces [0:all][1:\t*][2:.*x] ) \ 把 [1] 全部 \t 換成 space tos()[1].replace(/\t/g,pop(1)) ( [0:all][1:\t*][2:\S.*x] "1:spaces" ) \ 把後半部接回去並去掉 dummy x js> pop(1)[2] + :> slice(4,-1) ; /// Value tab-spaces specifies how many spaces to replace a TAB. /// Works on a single line only. /// 只針對行首的連續 \t 轉換。 : ^tab>spaces ( "text" -- "cooked" ) \ Replace all ^\t* with spaces :> split(/\r?\n\r?/) >r ( R: string-array ) r@ :> length dup for ( total | string-array countDown ) dup r@ - ( total i ) js> rtos(1)[tos()] ( total i line[i] ) \ 拿出一行 (^tab>spaces) ( total i cooked ) \ 轉換 ^\t* js: rtos(1)[pop(1)]=pop() ( total ) \ 放回去 next drop r> :> join('\n') ; /// 把整個 text string 每一行的領頭 \t 都換成 tab-spaces \ ---------- ... -------------------------------------------------- code all-blank? ( string-array -- T/f ) \ Are string-array lines all white spaces? push(pop().join("").search(/\S/)==-1) end-code code spaces dup :> split(/\r?\n\r?/) >r ( string | string-array ) r@ all-blank? if r> drop exit then drop \ leave the string, do nothing \ ---- 整段往左移 ---------------- begin ( R: string-array ) \ one loop shift left one char r@ hit-left-end? if r> :> join('\n') exit then \ 出口 r@ ..< /unindent> bar" sections :> split(/(|<\/un\indent>)/) >r \ \i == i 避免本身被掃到 \ split 的結果:[之前][][中間][][重複]... "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) \ 之前 r@ :> shift() dup undefined = if drop r> drop exit then drop ( cooked ) \ r@ :> shift() dup undefined = if drop r> drop exit then shift() dup undefined = if drop r> drop exit then drop ( cooked ) \ again ; /// 尚未寫出 break 為了有用到 exit 只好把 (unindent) 分離出來 /// 否則這個 block 之後的部分執行不到。 : unindent ( "input" -- "cooked" ) \ Shift left all .. sections s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (unindent) :> slice(1,-1) \ remove dummy 'x' ; include unindent.f \ 實驗範例 Command 'unindent' 處理 multiple lines string 把其中用 .. 標示的部分做 unindent 處理。 方法就是把標示的部分整個左移到不能再移為止。且 TAG 本身 的頭尾最後都會消失,好像不存在一樣。 I should be indented x y I should not be indented xy I should be indented z I should not be indented I should be indented I should not be indented I should be indented unindent . cr \ ----------- escape ----------------- \ ... 裡面的 < > 不希望被 HTML 認到, 以下寫出 escape 命令 \ 來避免之。方法是預先把 ... 當中的 <> 改成 <> : (escape) ( "raw" -- "cooked" ) \ foo '<' '>' to "<" ">" bar \ 規定 ... 不能 nested, 而且要成對依序出現。 \ foo bar 都存在時,經此 split() 之後一定是 foo,,<>,,bar 的形式。 :> split(/(|<\/code>)/) >r \ 也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
區段的原意。 \ 本來以為很簡單,沒想到搞成一整個檔案! hcchen 2015/11/30 \ ---------- Tab to spaces for .. ------------------------------- s" " value tab-spaces // ( -- value ) Tab spaces setting for .. tag. : (^tab>spaces) ( "string" -- "cooked" ) \ Replace ^\t* with spaces tab-spaces swap ( tab-spaces "input" ) \ 先把 "^\t*\S.*"+'x' 切開成 "^\t*", "\S.*x". \ Where the dummy leading \t and tailing x guarantees the pattern js> '\t' swap + char x + :> match(/(^\t*)(.*)/) ( tab-spaces [0:all][1:\t*][2:.*x] ) \ 把 [1] 全部 \t 換成 space tos()[1].replace(/\t/g,pop(1)) ( [0:all][1:\t*][2:\S.*x] "1:spaces" ) \ 把後半部接回去並去掉 dummy x js> pop(1)[2] + :> slice(4,-1) ; /// Value tab-spaces specifies how many spaces to replace a TAB. /// Works on a single line only. /// 只針對行首的連續 \t 轉換。 : ^tab>spaces ( "text" -- "cooked" ) \ Replace all ^\t* with spaces :> split(/\r?\n\r?/) >r ( R: string-array ) r@ :> length dup for ( total | string-array countDown ) dup r@ - ( total i ) js> rtos(1)[tos()] ( total i line[i] ) \ 拿出一行 (^tab>spaces) ( total i cooked ) \ 轉換 ^\t* js: rtos(1)[pop(1)]=pop() ( total ) \ 放回去 next drop r> :> join('\n') ; /// 把整個 text string 每一行的領頭 \t 都換成 tab-spaces \ ---------- ... -------------------------------------------------- code all-blank? ( string-array -- T/f ) \ Are string-array lines all white spaces? push(pop().join("").search(/\S/)==-1) end-code code spaces dup :> split(/\r?\n\r?/) >r ( string | string-array ) r@ all-blank? if r> drop exit then drop \ leave the string, do nothing \ ---- 整段往左移 ---------------- begin ( R: string-array ) \ one loop shift left one char r@ hit-left-end? if r> :> join('\n') exit then \ 出口 r@ ..< /unindent> bar" sections :> split(/(|<\/un\indent>)/) >r \ \i == i 避免本身被掃到 \ split 的結果:[之前][][中間][][重複]... "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) \ 之前 r@ :> shift() dup undefined = if drop r> drop exit then drop ( cooked ) \ r@ :> shift() dup undefined = if drop r> drop exit then shift() dup undefined = if drop r> drop exit then drop ( cooked ) \ again ; /// 尚未寫出 break 為了有用到 exit 只好把 (unindent) 分離出來 /// 否則這個 block 之後的部分執行不到。 : unindent ( "input" -- "cooked" ) \ Shift left all .. sections s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (unindent) :> slice(1,-1) \ remove dummy 'x' ; include unindent.f \ 實驗範例 Command 'unindent' 處理 multiple lines string 把其中用 .. 標示的部分做 unindent 處理。 方法就是把標示的部分整個左移到不能再移為止。且 TAG 本身 的頭尾最後都會消失,好像不存在一樣。 I should be indented x y I should not be indented xy I should be indented z I should not be indented I should be indented I should not be indented I should be indented unindent . cr \ ----------- escape ----------------- \ ... 裡面的 < > 不希望被 HTML 認到, 以下寫出 escape 命令 \ 來避免之。方法是預先把 ... 當中的 <> 改成 <> : (escape) ( "raw" -- "cooked" ) \ foo '<' '>' to "<" ">" bar \ 規定 ... 不能 nested, 而且要成對依序出現。 \ foo bar 都存在時,經此 split() 之後一定是 foo,,<>,,bar 的形式。 :> split(/(|<\/code>)/) >r \ 也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
escape ----------------- \ ... 裡面的 < > 不希望被 HTML 認到, 以下寫出 escape 命令 \ 來避免之。方法是預先把 ... 當中的 <> 改成 <> : (escape) ( "raw" -- "cooked" ) \ foo '<' '>' to "<" ">" bar \ 規定 ... 不能 nested, 而且要成對依序出現。 \ foo bar 都存在時,經此 split() 之後一定是 foo,,<>,,bar 的形式。 :> split(/(|<\/code>)/) >r \ 也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
...
escape 命令 \ 來避免之。方法是預先把 ... 當中的 <> 改成 <> : (escape) ( "raw" -- "cooked" ) \ foo '<' '>' to "<" ">" bar \ 規定 ... 不能 nested, 而且要成對依序出現。 \ foo bar 都存在時,經此 split() 之後一定是 foo,,<>,,bar 的形式。 :> split(/(|<\/code>)/) >r \ 也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
escape) ( "raw" -- "cooked" ) \ foo '<' '>' to "<" ">" bar \ 規定 ... 不能 nested, 而且要成對依序出現。 \ foo bar 都存在時,經此 split() 之後一定是 foo,,<>,,bar 的形式。 :> split(/(|<\/code>)/) >r \ 也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
'<' '>' to "<" ">"
,<>,
也要考慮 "" ( cooked ) begin r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then <>escape + ( cooked ) r@ :> shift() dup undefined = if drop r> drop exit then + ( cooked ) again ; /// foo bar must be both existing /// Support multiple lines : escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
escape ( "raw" -- "cooked" ) \ '<' '>' to "<" ">" s" x" swap + s" x" + \ add dummy 'x' guarantee the pattern (escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
escape) :> slice(1,-1) \ remove dummy 'x' ; /// Support multiple lines /// 只針對 ... 裡面。 \ --- End ---
Editor Guide: _edit_comment_
' swap + char
_ss_