スタジオCachéの機能を拡張する別の方法

Cachéスタジオは完全なものではなく、特に拡張できないという意見に出会う必要がありました。 ただし、これは完全に真実ではありません。 テンプレートと拡張機能のフルタイムメカニズムがあり 、インタラクティブなアドオンでスタジオを完成させることができます。
この記事では、コードをより効率的に管理するのに役立つ別の拡張方法について説明します。 これは、スタジオ統合クラスとバージョン管理システムを支援します。
バージョン管理クラスで何ができますか? まず、接続、作成、削除、ドキュメントを開くなど、スタジオで発生するいくつかのイベントを追跡し、次に、コンテキストメニューを含むメニューにアイテムを追加する機能。 これらのメニュー項目を使用して、サーバーでコードを実行できるだけでなく、いくつかの簡単なダイアログを作成することもできます。

インデントの削減/増加、コードブロックのコメント化/コメント解除(これらの機能はキーボードショートカットによってCachéの最新バージョンで使用可能)、およびインデントとブラケットを再フォーマットする機能を追加するために、スタジオメニューを展開してみましょう。プログラム。

バージョン管理クラスを作成する

%Studio.Extension.Baseの継承者としてUtil.StudioExtensionクラスを作成し、この拡張機能を使用する領域のサーバー構成に書き込みます。

[システム管理]> [構成]> [詳細設定]-> [バージョン管理システム]

クラスUtil.StudioExtension Extends%Studio.Extension.Base
{
XData メニュー
{
< MenuBase >
< メニュー = "フォーマット" タイプ = "1" >
< MenuItem Name = "PlusTab" />
< MenuItem Name = "MinusTab" />
< MenuItem Separator = "1" />
< MenuItem Name = "ReformatSelection" />
< MenuItem Name = "ReformatDocument" Save = "100" />
< MenuItem Separator = "1" />
< MenuItem Name = "CommentBlock" />
< MenuItem Name = "UnCommentBlock" />
</ メニュー >
</ MenuBase >
}
}
このブロックのMenuBase、Menu、MenuItemタグは、%Studio.Extension.Base、%Studio.Extension.Menu、%Studio.Extension.MenuItemクラスのマッピングであり、属性の意味はドキュメントから理解できます。 この場合、Nameはアイテムの内部名です。Type= 1はメニューがコンテキストに依存することを意味します。Separator= 1はアイテムがセパレータになり、Save = 100になります。メニューアイテムをクリックするとドキュメントが保存されます。

メニュー自体の表示を処理するメソッドを作成します。 読みやすいロシア語の名前をメニュー項目に追加します。必要と思われる場合は、それらを非アクティブにします(Enabled = 0)。 たとえば、何も選択されていない場合、「選択したテキストの再フォーマット」オプションをアクティブにすることは意味がありません。
OnMenuItemメソッド
メソッド OnMenuItem( MenuName As%String InternalName As%String SelectedText As%String ByRef Enabled As%Boolean
ByRef DisplayName As%String As%Status
{
set MenuName = "Format" DisplayName = "Format"
set MenuName = "Format、PlusTab" DisplayName = "-> |インデントを増やす"
set MenuName = "Format、MinusTab" DisplayName = "| <-インデントを減らす"
set MenuName = "Format、ReformatDocument" DisplayName = "ドキュメントの再フォーマット"
set MenuName = "Format、ReformatSelection" DisplayName = "Reformat selection"
set MenuName = "Format、CommentBlock" DisplayName = "Comment block"
set MenuName = "Format、UnCommentBlock" DisplayName = "ブロックのコメント解除"
有効 = 1に 設定
set ext = $ piece InternalName "。" $ length InternalName "。" ))
set :( MenuName = "Format、ReformatDocument" )&&( ext '= "MAC" )&&( ext ' = "CLS" 有効 = 0
set :( MenuName = "Format、ReformatSelection" )&&( SelectedText = "" 有効 = 0
set :( MenuName = "Format、MinusTab" )&&( SelectedText = "" 有効 = 0
set :( MenuName = "Format、UnCommentBlock" )&&( SelectedText = "" 有効 = 0
終了 1
}

再接続すると、新しいコンテキストメニュー項目が表示されますが、それでも何も実行されません。


インデントクラスc

メニュー項目の選択など、さまざまなアクションに応答するUserActionメソッドを作成します。
UserActionメソッド
/ *何かが起こった
タイプ= 0-メニュー項目が押されている、
この場合、InternalNameはメニュー項目の名前ですが、
InternalName-ドキュメントの名前、
SelectedText-選択されたテキスト(選択されている場合)

タイプ= 1-イベントは自動的に作成されましたが、
名前= 0-ユーザーはドキュメントを変更しました
名前= 1-新しいドキュメントを作成して保存しました
名前= 2-ユーザーがドキュメントを削除しました
名前= 3-ユーザーがドキュメントを開いた
名前= 4-ユーザーがドキュメントを閉じた
名前= 5-接続されたユーザー
InternalName-イベントが発生したドキュメントの名前

アクションは、スタジオのアクションを示すために使用されます。
0-何もしない
1-標準ダイアログを表示するyes / no / cancel。 ダイアログのテキストは、Target変数で指定されます。
2-cspページを起動します。 ターゲットはページ名を示します
3-クライアントでEXEファイルを実行します。 ターゲットはファイルパスを示します
4-ターゲット変数に含まれるテキストをドキュメントの現在の位置に挿入します
5-Target変数に含まれるドキュメントを開きます。 ドキュメントのリストはコンマで区切られます。 ドキュメント名に「test.mac:label + 10」が含まれている場合、test.macドキュメントは「label + 10」の位置で開きます。
6-ターゲット変数に含まれるメッセージを含むウィンドウを表示する
7-はい/いいえ/キャンセルオプションを含むダイアログを表示します。 ダイアログのテキストは、Target変数に含まれています。 メッセージテストは、変数Msgで渡されます。
Reload引数がtrueの場合、現在のドキュメントがリロードされます。
* /
メソッド UserAction( Type As%Integer Name As%String InternalName As%String SelectedText As%String
ByRef Action As%String ByRef Target As%String ByRef Msg As%String ByRef Reload As%Boolean As%Status
{
set ext = $ zconvert $ piece InternalName "。" $ length InternalName "。" ))、 "U"
Name = "Format、PlusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます PlusTab SelectedText ext = "CSP"
}
Name = "Format、MinusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます MinusTab SelectedText ext = "CSP"
}
終了 1
}

タブのフォーマットに使用するクラス自体:
Util.FormatTabクラス
///テキスト内のタブを操作するためのクラス
クラスUtil.FormatTab
{
///開始するすべての行の先頭にタブを追加します
///スペースまたはタブを使用します。
///マークされたテキストの場合
ClassMethod PlusTab( text As%String inCsp As%Boolean = 0 As%String
{
set cr = $ char (13,10) ; 改行文字
set tab = $ char (9) ; タブ文字
set stringsIn = $ listfromstring text cr
文字列の 設定 = ""
for i = 1:1: $ listlength stringsIn
{
set line = $ listget stringsIn i
set firstSymbol = $ extract line 、1,1)
if inCsp = 1)||( firstSymbol = "" )||( firstSymbol = tab
{
pos = 1:1: $ length line ; 最初の非空白文字の位置を探す
{
set symbol = $ extract line pos pos
quit :( symbol '= "" )&&( symbol ' = tab
}
set line = $ extract line 、1、 pos -1)_ tab _ $ extract line pos 、*)
}
文字列を 設定し ます = stringsOut _ $ listbuild line
}
quit $ listtostring stringsOut cr
}
///行の先頭のタブを削除します
/// text-処理中のテキスト
/// inCsp-cspページで作業しているというサイン、
///行の先頭にスペースを強制しようとしないで
ClassMethod MinusTab( text As%String inCsp As%Boolean = 0
{
set cr = $ char (13,10) ; 改行文字
set tab = $ char (9) ; タブ文字
tabSize = 4を 設定
set stringsIn = $ listfromstring text cr
文字列の 設定 = ""
for i = 1:1: $ listlength stringsIn
{
set line = $ listget stringsIn i
set firstSymbol = $ extract line 、1,1)
j = 1:1: tabSizeの場合
{
set symbol = $ extract line 、1,1)
if symbol = ""; 最初の4つのスペースを削除します
{
set line = $ extract line 、2、*)
}
elseif symbol = tab ; タブを削除し、ここで終了します
{
set line = $ extract line 、2、*)
やめる
}
その他 ; スペースなし、タブなし、スペースの削除を終了
{
やめる
}
}
; 突然すべてのスペースを削除し、構文の点で行が誤った
; これはcspドキュメントでない場合は間違いなく起こります
if inCsp = 0)&&(( firstSymbol = "" )||( firstSymbol = tab ))&&( $ extract line 、1,1) '= "" )&&( $ extract line 、1,1)' = タブ
{
set line = "" _ line
}
文字列を 設定し ます = stringsOut _ $ listbuild line
}
quit $ listtostring stringsOut cr
}
}

これで、スタジオに再接続する場合(バージョン管理クラスを変更した後は常にこれを行う必要があります)、メニュー項目「インデントを追加」および「インデントを削除」が機能するはずです。

コードのコメント/コメント解除のクラス

Util.StudioExtensionクラスのUserActionメソッドを変更し、新しいアイテムの処理を追加します。
UserActionメソッド
メソッド UserAction( Type As%Integer Name As%String InternalName As%String SelectedText As%String
ByRef Action As%String ByRef Target As%String ByRef Msg As%String ByRef Reload As%Boolean As%Status
{
set ext = $ zconvert $ piece InternalName "。" $ length InternalName "。" ))、 "U"
set docname = $ extract InternalName 、1、*-4)
Name = "Format、PlusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます PlusTab SelectedText ext = "CSP"
}
Name = "Format、MinusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます MinusTab SelectedText ext = "CSP"
}
Name = "Format、CommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )。 AddComment SelectedText
}
Name = "Format、UnCommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )。 RemoveComment SelectedText
}
終了 1
}

Util.FormatCommentクラスを使用して文字列を処理します。
Util.FormatCommentクラス
///コメント/コメント解除コードのクラス
クラスUtil.FormatComment
{
///各行の先頭にコメントを追加します
///スペースまたはタブを使用します。
///マークされたテキストの場合
ClassMethod AddComment( text As%String As%String
{
set cr = $ char (13,10) ; 改行文字
set stringsIn = $ listfromstring text cr
文字列の 設定 = ""
設定 stringCount = $ listlength stringsIn
for i = 1:1: $ listlength stringsIn
{
set line = $ listget stringsIn i
s :( i < stringsCount )||( line '= "" line = "//" _ line ; テキストのブロックをコピーするとき、多くの場合、余分な改行がキャッチされます。
文字列を 設定し ます = stringsOut _ $ listbuild line
}
w !、!、 $ listtostring stringsOut cr
quit $ listtostring stringsOut cr
}
///行の先頭からコメントを削除します
ClassMethod RemoveComment( text As%String
{
set cr = $ char (13,10) ; 改行文字
set tab = $ char (9) ; タブ文字
set stringsIn = $ listfromstring text cr
文字列の 設定 = ""
for i = 1:1: $ listlength stringsIn
{
set line = $ listget stringsIn i
; 先頭のスペースとタブを削除して、この行にコメントがあるかどうかを判断します
set line0 = $ translate line "" _ tab ""
if $ extract line0、1,1 )= ";"
{
set pos = $ find line ";"
set line = $ extract line 、1、 pos -2)_ $ extract line pos 、*)
}
elseif $ extract line0、1,3 )= "///"
{
set pos = $ find line "///"
set line = $ extract line 、1、 pos -4)_ $ extract line pos 、*)
}
elseif $ extract line0、1,2 )= "//"
{
set pos = $ find line "//"
set line = $ extract line 、1、 pos -3)_ $ extract line pos 、*)
}
文字列を 設定し ます = stringsOut _ $ listbuild line
}
quit $ listtostring stringsOut cr
}
///行がコメント化されているかどうかに関する情報を返します。
///単一行のコメントのみを理解する
ClassMethod CheckForComment( text As%String As%ブール
{
set cr = $ char (13,10) ; 改行文字
set tab = $ char (9) ; タブ文字
set stringsIn = $ listfromstring text cr
文字列の 設定 = ""
for i = 1:1: $ listlength stringsIn
{
set line = $ listget stringsIn i
set line = $ translate line "" _ tab ""
return $ e line 、1,2)= "//" 1
return $ e line 、1,1)= ";" 1
}
0を 終了
}
}

テキストの書式設定

クラスを接続してコードを再フォーマットします。 プロジェクトが、同じスタイルに準拠していない別のチームまたはプログラマーによって作成された場合に役立ちます。 タイプコード
for i = TheNum :1: TheNum +2 {
StartTime = 12 * 3600 +(300 * $ R (6))に設定します
StartTime <(3600 * 22) {
set show = ## class Cinema.Show )。 %新規 ()
showを 設定し ます フィルム = TheFilm
showを 設定し ます 劇場 = i
showを 設定し ます StartTime = StartTime
ショーを 行い ます %保存 ()
set StartTime = StartTime +( TheFilm。Length * 60)+ 1200 \ 300 * 300
}
}
に変えることができます
for i = TheNum :1: TheNum +2
{
StartTime = 12 * 3600 +(300 * $ R (6))に設定します
一方、 StartTime <(3600 * 22)
{
set show = ## class Cinema.Show )。 %新規 ()
showを 設定し ます フィルム = TheFilm
showを 設定し ます 劇場 = i
showを 設定し ます StartTime = StartTime
ショーを 行い ます %保存 ()
set StartTime = StartTime +( TheFilm。Length * 60)+ 1200 \ 300 * 300
}
}
好きなように、またはその逆。 「ブラケット上のブラケット」スタイルのクラスはUtil.CodeFormatで、「行末のブラケット」スタイルのクラスはUtil.CodeFormat3です

新しいメニュー項目の処理を追加して、UserActionメソッドを変更します。
UserActionメソッド
メソッド UserAction( Type As%Integer Name As%String InternalName As%String SelectedText As%String ByRef Action As%String
ByRef Target As%String ByRef Msg As%String ByRef Reload As%Boolean As%Status
{
set ext = $ zconvert $ piece InternalName "。" $ length InternalName "。" ))、 "U"
set docname = $ extract InternalName 、1、*-4)
Name = "Format、PlusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます PlusTab SelectedText ext = "CSP"
}
Name = "Format、MinusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます MinusTab SelectedText ext = "CSP"
}
Name = "Format、CommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )を 設定し ます AddComment SelectedText
}
Name = "Format、UnCommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )を 設定し ます RemoveComment SelectedText
}
Name = "Format、ReformatSelection"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.CodeFormat )を 設定し ます FormatString SelectedText
}
Name = "Format、ReformatDocument"の場合
{
アクション = 0を 設定
do ext = "MAC" ##クラス Util.CodeFormat )。 FormatMAC docname
do ext = "CLS" ##クラス Util.CodeFormat )。 FormatClass docname
}
終了 1
}

「括弧より括弧」スタイルのクラスハンドラコード
クラスUtil.CodeFormat
///コードフォーマッタクラス
クラスUtil.CodeFormat Extends%RegisteredObject
{
///入力バッファのグローバル名
プロパティ Buffer1 As%String ;

///グローバル出力バッファの名前
プロパティ Buffer2 As%String ;

///入力バッファの現在の行
プロパティ CurrentLine1 As%Numeric [ InitialExpression = 1 ];

///出力バッファの現在の行
プロパティ CurrentLine2 As%Numeric [ InitialExpression = 1 ];

///入力バッファ行の現在位置
プロパティ CurrentPos1 As%Numeric [ InitialExpression = 1 ];

///中括弧のレベル
プロパティ LevelFigureBrace As%Integer [ InitialExpression = 0 ];

///括弧レベル
プロパティ LevelRoundBrace As%Integer [ InitialExpression = 0 ];

///行にコードはありますか? <br>
///組み合わせ:
/// LineHasCode = 0 && SkipSpace = 1->行の先頭、ラベルまたはコードが必要
/// LineHasCode = 0 && SkipSpace = 0->そのようなことはないはず
/// LineHasCode = 1 && SkipSpace = 0->すでにコードがあり、そのまますべてを書く
/// LineHasCode = 1 && SkipSpace = 1->すでにコードはありますが、たとえば{
プロパティ LineHasCode As%Boolean ;

///スペースをスキップ
プロパティ SkipSpace As%Boolean [ InitialExpression = 1 ];

///改行をスキップ
/// 1-1つスキップ
/// -1-翻訳はスキップされたばかりなので、タグなどに注意する必要があります
プロパティ SkipCR As%Boolean [ InitialExpression = 0 ];

///インデントが必要です(コードが表示されるとき)
プロパティ NeedIndent As%Boolean ;

/// 1行のコメントで?
プロパティ InSingleLineComment As%Boolean [ InitialExpression = 0 ];

///複数行のコメントで?
プロパティ InMultiLineComment As%Boolean [ InitialExpression = 0 ];

///改行を処理する
メソッド ProcessCR( text As%String
{
if .. SkipCR = 1
{
設定 .. SkipCR = -1
終了 1
}
do :.. NeedIndent .. 書き込み (.. MakeIndent ())
セット .. LineHasCode = 0
セット .. SkipSpace = 1
設定 .. NeedIndent = 0
設定 .. InSingleLineComment = 0
do .. WriteCR ()
終了 1
}
///空白を処理する
メソッド ProcessSpace( text As%String
{
quit :( .. InMultiLineComment ).. ProcessCommonCode テキスト
; 改行は抑制されました。通常の文字は空白です。
set :.. SkipCR = -1 .. SkipCR = 0、.. NeedIndent = 0、.. SkipSpace = 1
do : '.. SkipSpace .. Write text
set : '.. LineHasCode .. NeedIndent = 1
終了 1
}
///プロセス中括弧
メソッド ProcessFigureBraceOpen( text As%String
{
quit :( .. LevelRoundBrace ).. ProcessCommonCode テキスト
quit :( .. InMultiLineComment ).. ProcessCommonCode テキスト
quit :( .. InSingleLineComment ).. ProcessCommonCode テキスト
do :.. LineHasCode .. WriteCR ()
do .. Write (.. MakeIndent ()_ text
do .. WriteCR ()

set .. LevelFigureBrace = .. LevelFigureBrace +1
set .. LineHasCode = 0、.. SkipSpace = 1、.. NeedIndent = 1、.. SkipCR = 1
終了 1
}
///閉じ括弧を処理します
メソッド ProcessFigureBraceClose( text As%String
{
quit :( .. LevelRoundBrace ).. ProcessCommonCode テキスト
quit :( .. InMultiLineComment ).. ProcessCommonCode テキスト
quit :( .. InSingleLineComment ).. ProcessCommonCode テキスト
quit :( .. LevelFigureBrace = 0).. ProcessCommonCode テキスト
do :.. LineHasCode .. WriteCR ()
set .. LevelFigureBrace = .. LevelFigureBrace -1
do .. Write (.. MakeIndent ()_ text
do .. WriteCR ()
set .. SkipCR = 1、.. NeedIndent = 1、.. SkipSpace = 1、.. LineHasCode = 0
終了 1
}
///プロセス開始括弧
メソッド ProcessRoundBraceOpen( text As%String
{
セット :( .. InMultiLineComment = 0)&&(.. InSingleLineComment = 0).. LevelRoundBrace = .. LevelRoundBrace +1
do .. 書き込み テキスト
終了 1
}
///プロセスの閉じ括弧
メソッド ProcessRoundBraceClose( text As%String
{
set :( .. InMultiLineComment = 0)&&(.. InSingleLineComment = 0)&&(.. LevelRoundBrace > 0).. LevelRoundBrace = .. LevelRoundBrace -1
do .. 書き込み テキスト
終了 1
}
///複数行コメントを開くプロセス
メソッド ProcessMultilineCommentOpen( text As%String
{
セット .. InMultiLineComment = 1
do .. ProcessCommonCode テキスト
終了 1
}
///複数行コメントを閉じるプロセス
メソッド ProcessMultilineCommentClose( text As%String
{
セット .. InMultiLineComment = 0
do .. ProcessCommonCode テキスト
終了 1
}
///単一行コメント
メソッド ProcessOnelineCommentOpen( text As%String
{
do .. ProcessCommonCode テキスト
セット .. InSingleLineComment = 1
終了 1
}
///機能なしでコードを処理します
メソッド ProcessCommonCode( text As%String
{
//行を翻訳し、新しい行ですぐにテキスト-これは表示されるラベルです。
//翻訳が抑制されていたにもかかわらず、文字列をすべて同じように翻訳する必要があります
if .. SkipCR = -1
{
do .. WriteCR ()
設定 .. NeedIndent = 0
}
設定 .. SkipCR = 0
セット :.. NeedIndent text = .. MakeIndent ()_ text
do .. 書き込み テキスト
設定 .. SkipSpace = 0
セット .. LineHasCode = 1
設定 .. NeedIndent = 0
終了 1
}
///ポピープログラムを再フォーマットする
/// d ##クラス(Util.CodeFormat).FormatMAC( "Untitled1")
ClassMethod FormatMAC( name As%String As%整数
{
quit name = ""
quit : ' $ data (^ rMAC( name ))
set parser = .. %New ()
パーサーを 設定し ます。 Buffer1 = "^ || buffer1"
パーサーを 設定し ます。 Buffer2 = "^ || buffer2"
@ パーサーを 殺し ます。 Buffer1
@ パーサーを 殺し ます。 Buffer2
設定 キー = 0、 = 0
for //プログラムグローバルからバッファデータに書き込む
{
set key = $ order (^ rMAC( name 、0、 key )) quit :+ key = 0
@ パーサーを 設定し ます。 Buffer1 @( $ increment line ))= ^ rMAC( name 、0、 key
}
中括弧 = parserを 設定し ます FormatBuffer ()
書き なさい!、 名前 「:」 中括弧
キーを 設定する = 0
のために ; 古いプログラム行を削除する
{
set key = $ order (^ rMAC( name 、0、 key )) quit :+ key = 0
kill ^ rMAC( name 、0、 key
}
merge ^ rMAC( 名前 、0)= @ パーサー Buffer2
set ^ rMAC( name 、0,0)= $ order (@ parser。Buffer2 @( "" )、-1)
セット ^ rMAC( name 、0)= $ horolog
}
///すべてのクラスメソッドをフォーマット<br>
/// d ##クラス(Util.CodeFormat).FormatClass( "Import.NIAdvs")
ClassMethod FormatClass( クラス As%String
{
set メソッド = ""
のために
{
set method = $ order (^ oddDEF( class "m" method )) quit method = ""
do .. FormatMethod クラス メソッド
}
}
///クラスメソッドをフォーマットします。 あまり美しく書かれていない-グローバルとオブジェクトの混合<br>
/// d ##クラス(Util.CodeFormat).FormatMethod( "Import.NIAdvs"、 "%OnValidateObject5")
ClassMethod FormatMethod( クラス As%String メソッド As%String
{
set mdef = ## class %Dictionary.MethodDefinition )。 %OpenId クラス _ "||" _ メソッド
終了 mdef = ""
set gl1 = "^ oddDEF(" "" _ class _ "" "、" "m" "、" "" _ method _ "" "、30)"; メソッドコードはここに保存されます
set parser = .. %New ()
パーサーを 設定し ます。 Buffer1 = "^ || buffer1"
パーサーを 設定し ます。 Buffer2 = "^ || buffer2"
@ パーサーを 殺し ます。 Buffer1
@ パーサーを 殺し ます。 Buffer2

キーを 設定する = 0
for //メソッドglobalからバッファデータに書き込みます
{
set key = $ order (@ gl1 @( key )) quit :+ key = 0
@ パーサーを 設定し ます。 Buffer1 @( キー )= @ gl1 @( キー
}
中括弧 = parserを 設定し ます FormatBuffer ()
!、 クラス 「。」と 書く メソッド 「:」 中括弧

mdefを実行し ます。 実装 クリア ()
キーを 設定する = 0
のために
{
set key = $ order (@ parser。Buffer2 @( key )) quit :+ key = 0
mdefを実行し ます。 実装 WriteLine (@ parser。Buffer2 @( key ))
}
mdefを実行し ます。 %保存 ()
}
///文字列をフォーマットし、次にそれを返します
/// w ##クラス(Util.CodeFormat).FormatString( "if x = 1 {s x = 1}")
ClassMethod FormatString( str As%String As%String
{

set parser = .. %New ()
パーサーを 設定し ます。 Buffer1 = "^ || buffer1"
パーサーを 設定し ます。 Buffer2 = "^ || buffer2"
@ パーサーを 殺し ます。 Buffer1
@ パーサーを 殺し ます。 Buffer2

set rowend = $ char (13,10)
set rows = $ listfromstring str rowend
キーを 設定する = 0
for i = 1:1: $ listlength rows //メソッドglobalからバッファにデータを書き込みます
{
@ パーサーを 設定し ます。 Buffer1 @( i )= $ listget rows i
}
パーサーを行い ます。 FormatBuffer ()

設定 str = ""
キーを 設定 = ""
のために
{
set key = $ order (@ parser。Buffer2 @( key )) quit key = ""
set str = str _ $ listbuild (@ parser。Buffer2 @( key ))
}
set $ listget rows $ listlength rows ))= "" str = str _ $ listbuild ""
$ listtostring str rowend )を 終了し ます
}
///入力バッファからテキストを読み取る<br>
///テキストとそのタイプのリストを返します<br>
///テキストタイプ<br>
/// p-空白<br>
/// s-文字列<br>
/// e-行末<br>
/// E-一般的なテキストの終わり<br>
/// {-{<br>
///}-} <br>
///(-(<br>
///)-)<br>
///; -単一行コメントの開始<br>
/// / *-複数行コメントの開始<br>
/// * /-複数行コメントの終わり
メソッド ReadTerm() As%リスト
{
set $ data (@ .. Buffer1 @(.. CurrentLine1 ))= 0 .. CurrentLine1 = .. CurrentLine1 +1、.. CurrentPos1 = 1
quit $ data (@ .. Buffer1 @(.. CurrentLine1 ))= 0 $ listbuild "" "E"
set str = @ .. Buffer1 @(.. CurrentLine1
set char1 = $ extract str 、.. CurrentPos1 、.. CurrentPos1
set char2 = $ extract str 、.. CurrentPos1 +1、.. CurrentPos1 +1)
set char1 = "" .. CurrentLine1 = .. CurrentLine1 +1、.. CurrentPos1 = 1
quit char1 = "" $ listbuild "" "e"
set .. CurrentPos1 = .. CurrentPos1 +1
quit char1 = "" $ listbuild char1 "p"
quit char1 = $ char (9) $ listbuild char1 "p"
quit char1 = "{" $ listbuild char1 "{"
quit char1 = "}" $ listbuild char1 "}"
quit char1 = "(" $ listbuild char1 "("
quit char1 = ")" $ listbuild char1 ")"
quit char1 = ";" $ listbuild char1 ";"
if char1 = "/" )&&( char2 = "/" set .. CurrentPos1 = .. CurrentPos1 +1 quit $ listbuild char1 _ char2 ";"
if char1 = "/" )&&( char2 = "*" set .. CurrentPos1 = .. CurrentPos1 +1 quit $ listbuild char1 _ char2 "/ *"
if char1 = "*" )&&( char2 = "/" set .. CurrentPos1 = .. CurrentPos1 +1 quit $ listbuild char1 _ char2 "* /"
if char1 = "" ""
{
set pos2 = $ find str "" "" 、.. CurrentPos1
set text = $ extract str 、.. CurrentPos1 -1、 pos2 -1)
セット .. CurrentPos1 = pos2
$ listbuild text "s" )を終了します
}
$ listbuild char1 "s" )を終了します
}
///同じReadTermですが、引数の処理方法と受信方法が異なります
メソッド ReadTerm1( ByRef type As%String As%String
{
設定 res = .. ReadTerm ()
セット タイプ = $ listget res 、2)
$ listget res 、1)を終了します
}
///テキストを出力バッファーに出力します
メソッドの 書き込み( text As%String = ""
{
set @ .. Buffer2 @(.. CurrentLine2 )= $ get (@ .. Buffer2 @(.. CurrentLine2 ))_ text
}
///出力バッファ内の行を変換します
メソッド WriteCR()
{
set .. CurrentLine2 = .. CurrentLine2 +1
}
///テキスト文字列をインデントします
メソッド MakeIndent() As%String
{
インデントを 設定 = $ char (9)
for i = 1:1:.. LevelFigureBrace set indent = indent _ $ char (9)
for i = 1:1:.. LevelRoundBrace set indent = indent _ ""
インデントを 終了
}
///内部「バッファ」内のテキストをフォーマットする
メソッド FormatBuffer()
{
設定 レベル = 0
のために
{
set text = .. ReadTerm1 。type quit type = "E"
do type = "e" .. ProcessCR テキスト
do type = "p" .. ProcessSpace text
do type = ";" .. ProcessOnelineCommentOpen テキスト
do type = "/ *" .. ProcessMultilineCommentOpen text
do type = "* /" .. ProcessMultilineCommentClose text
do type = "(" .. ProcessRoundBraceOpen text
do type = ")" .. ProcessRoundBraceClose text
do type = "{" .. ProcessFigureBraceOpen text
do type = "}" .. ProcessFigureBraceClose text
do type = "s" .. ProcessCommonCode text
set :.. LevelFigureBrace > level level = .. LevelFigureBrace
}
終了 レベル
}
}

「行末の括弧」スタイルのクラスハンドラクラス。 このスタイルが望ましい場合は、UserActionメソッドからのUtilCodeFormatクラスの呼び出しをUtilCodeFormat3に置き換える必要があります。
Util.CodeFormat3クラス
クラスUtil.CodeFormat3はUtil.CodeFormatを拡張します
{
///最後の改行をロールバックします
メソッド ReturnCR()
{
set .. CurrentLine2 = .. CurrentLine2 -1
}
///最後のスペースをロールバックする
メソッド ReturnSpace()
{
set str = @ .. Buffer2 @(.. CurrentLine2
len = $ length str )に 設定し ます
のために
{
set lastchar = $ extract str len len
quit :( lastchar '= "" )&&( lastchar ' = $ char (9))
set str = $ extract str 、1、 len -1)
len = len -1に 設定
set @ .. Buffer2 @(.. CurrentLine2 )= str
}
}
///プロセス中括弧
メソッド ProcessFigureBraceOpen( text As%String
{
quit :( .. LevelRoundBrace ).. ProcessCommonCode テキスト
quit :( .. InMultiLineComment ).. ProcessCommonCode テキスト
quit :( .. InSingleLineComment ).. ProcessCommonCode テキスト
do : '.. LineHasCode .. ReturnCR ()
do .. ReturnSpace ()
do .. 書き込み ""
do .. 書き込み テキスト
set .. LevelFigureBrace = .. LevelFigureBrace +1

do .. WriteCR ()
set .. LineHasCode = 0、.. SkipSpace = 1、.. NeedIndent = 1、.. SkipCR = 1
終了 1
}
}

クラス拡張StudioCaché全体:
Util.StudioExtensionクラス
クラスUtil.StudioExtension Extends%Studio.Extension.Base
{
XData メニュー
{
< MenuBase >
< メニュー = "フォーマット" タイプ = "1" >
< MenuItem Name = "PlusTab" />
< MenuItem Name = "MinusTab" />
< MenuItem Separator = "1" />
< MenuItem Name = "ReformatSelection" />
< MenuItem Name = "ReformatDocument" Save = "100" />
< MenuItem Separator = "1" />
< MenuItem Name = "CommentBlock" />
< MenuItem Name = "UnCommentBlock" />
</ メニュー >
</ MenuBase >
}
メソッド OnMenuItem( MenuName As%String InternalName As%String SelectedText As%String
ByRef Enabled As%Boolean ByRef DisplayName As%String As%Status
{
set MenuName = "Format" DisplayName = "Format"
set MenuName = "Format、PlusTab" DisplayName = "-> |インデントを増やす"
set MenuName = "Format、MinusTab" DisplayName = "| <-インデントを減らす"
set MenuName = "Format、ReformatDocument" DisplayName = "ドキュメントの再フォーマット"
set MenuName = "Format、ReformatSelection" DisplayName = "Reformat selection"
set MenuName = "Format、CommentBlock" DisplayName = "Comment block"
set MenuName = "Format、UnCommentBlock" DisplayName = "ブロックのコメント解除"
有効 = 1に 設定
set ext = $ piece InternalName "。" $ length InternalName "。" ))
set :( MenuName = "Format、ReformatDocument" )&&( ext '= "MAC" )&&( ext ' = "CLS" 有効 = 0
set :( MenuName = "Format、ReformatSelection" )&&( SelectedText = "" 有効 = 0
set :( MenuName = "Format、MinusTab" )&&( SelectedText = "" 有効 = 0
set :( MenuName = "Format、UnCommentBlock" )&&( ##クラス Util.FormatComment 。CheckForComment SelectedText )= 0) 有効 = 0
終了 1
}
/ *何かが起こった
タイプ= 0-メニュー項目が押されている、
この場合、InternalNameはメニュー項目の名前ですが、
InternalName-ドキュメントの名前、
SelectedText-選択されたテキスト(選択されている場合)
タイプ= 1-イベントは自動的に作成されましたが、
名前= 0-ユーザーはドキュメントを変更しました
名前= 1-新しいドキュメントを作成して保存しました
名前= 2-ユーザーがドキュメントを削除しました
名前= 3-ユーザーがドキュメントを開いた
名前= 4-ユーザーがドキュメントを閉じた
名前= 5-ユーザー接続
InternalName-イベントが発生したドキュメントの名前
アクションは、スタジオのアクションを示すために使用されます。
0-何もしない
1-標準ダイアログを表示するyes / no / cancel。 ダイアログのテキストは、Target変数で指定されます。
2-cspページを起動します。 ターゲットはページ名を示します
3-クライアントでEXEファイルを実行します。 ターゲットはファイルパスを示します
4-ターゲット変数に含まれるテキストをドキュメントの現在の位置に挿入します
5-Target変数に含まれるドキュメントを開きます。 ドキュメントのリストはコンマで区切られます。 ドキュメント名に「test.mac:label + 10」が含まれている場合、test.macドキュメントは「label + 10」の位置で開きます。
6-ターゲット変数に含まれるメッセージを含むウィンドウを表示する
7-はい/いいえ/キャンセルオプションを含むダイアログを表示します。 ダイアログのテキストは、Target変数に含まれています。 メッセージテストは、変数Msgで渡されます。
Reload引数がtrueの場合、現在のドキュメントがリロードされます。
* /
メソッド UserAction( Type As%Integer Name As%String InternalName As%String SelectedText As%String
ByRef Action As%String ByRef Target As%String ByRef Msg As%String ByRef Reload As%Boolean As%Status
{
set ext = $ zconvert $ piece InternalName "。" $ length InternalName "。" ))、 "U"
set docname = $ extract InternalName 、1、*-4)
Name = "Format、PlusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます PlusTab SelectedText ext = "CSP"
}
Name = "Format、MinusTab"の場合
{
アクション = 4を 設定し ます。 テキスト挿入
ターゲット = ##クラス Util.FormatTab )を 設定し ます MinusTab SelectedText ext = "CSP"
}
Name = "Format、CommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )を 設定し ます AddComment SelectedText
}
Name = "Format、UnCommentBlock"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.FormatComment )を 設定し ます RemoveComment SelectedText
}
Name = "Format、ReformatSelection"の場合
{
アクション = 4を 設定
ターゲット = ##クラス Util.CodeFormat )を 設定し ます FormatString SelectedText
}
Name = "Format、ReformatDocument"の場合
{
アクション = 0を 設定
do ext = "MAC" ##クラス Util.CodeFormat )。 FormatMAC docname
do ext = "CLS" ##クラス Util.CodeFormat )。 FormatClass docname
}
終了 1
}
}

できた!

Source: https://habr.com/ru/post/J202608/


All Articles