お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"エディタで代入の反転処理"




Delphi のエディタでクリップボードを使用して代入の反転を行います。
  Abc.Value := Efg;  --->  Efg := Abc.Value;
上記のように左辺と右辺の入れ換えをします。
複数行の処理も一度に出来ます。代入以外のコードはそのままです。


Delphi5 での動作確認しか行っていませんので、以前のバージョンで試す場合
は Delphi が暴走する可能性を覚悟してやってください^^;
といっても、クリップボードを使用しているだけなんで動作すると思います。
なお、Delphi へのショートカット登録は nifty:FDELPHI/MES/08/10902
「Satobe さん」のご発言をそのまま利用させていただきましたm(__)m

ゴリゴリとコーディングしてしまったのであんまり奇麗じゃないですけど、似
たような機能のものが見当たらないのでアップしました。
気づいたことがありましたらレス頂ければと思います。

使用方法

以下のユニットを設計時パッケージのコンポーネントとして追加します。

Ctrl+C で元のソースをクリップボードにコピーして、Ctrl+D でクリップボー
ド内の代入を反転、貼り付けたい場所に移動して Ctrl+V すれば反転したソー
スがペーストされます。

Ctrl+D のショートカットを変更したい場合は、*1 を変更してください。

------------------------------------------ 以下 ソース
unit SbstTurn;

interface

procedure Register;

implementation

uses Windows, Classes, SysUtils, ToolsAPI, Menus, Clipbrd;

type
  TSbstTurnModule = class(TNotifierObject, IUnknown, IOTANotifier,
    IOTAKeyboardBinding)
    procedure SbstTurn(const Context: IOTAKeyContext;
              KeyCode: TShortCut; var BindingResult: TKeyBindingResult);
    function GetBindingType: TBindingType;
    function GetDisplayName: string;
    function GetName: string;
    procedure BindKeyboard(const BindingServices: IOTAKeyBindingServices);
  end;

procedure Register;
begin
  (BorlandIDEServices as IOTAKeyBoardServices).
    AddKeyboardBinding(TSbstTurnModule.Create);
end;

{ TSbstTurnModule }

procedure TSbstTurnModule.BindKeyboard(
  const BindingServices: IOTAKeyBindingServices);
begin
  BindingServices.AddKeyBinding([ShortCut(Ord('D'), [ssCtrl])],  // *1
    SbstTurn, nil);              // ↑ショートカットの変更はここを修正
end;

function TSbstTurnModule.GetBindingType: TBindingType;
begin
  Result := btPartial;
end;

function TSbstTurnModule.GetDisplayName: string;
begin
  Result := 'Ctrl+''D''で代入式を反転';
end;

function TSbstTurnModule.GetName: string;
begin
  Result := 'QZF12401.SbstTurnModule';
end;

procedure TSbstTurnModule.SbstTurn(const Context: IOTAKeyContext;
  KeyCode: TShortCut; var BindingResult: TKeyBindingResult);
var
  BaseText, TurnText, LeftText, RightText: string;
  i, j, LeftPos, LeftLen, RightPos, RightLen: Integer;
  Eot, Notsp, QuoteFnd: Boolean;

  function LeftWordFound(WordPos: Integer ; WordText: string): Boolean;
  var
    WordLen: Integer;
  begin
    WordLen := Length(WordText);
    if  (WordPos > WordLen - 1)
    and (Copy(BaseText, WordPos - WordLen + 1, WordLen) = WordText)  then
      if  (BaseText[WordPos + 1] in  [#10, #13, ' '])
      and ((WordPos = WordLen)
      or  (BaseText[WordPos - WordLen] in  [#10, #13, ' ']))  then
        Result := True
      else
        Result := False
    else
      Result := False;
  end;

  function RightWordFound(WordPos: Integer ; WordText: string): Boolean;
  var
    WordLen: Integer;
  begin
    WordLen := Length(WordText);
    if  (WordPos < Length(BaseText) - WordLen + 2)
    and (Copy(BaseText, WordPos, WordLen) = WordText)  then
      if  ((WordPos + WordLen > Length(BaseText))
      or  (BaseText[WordPos + WordLen] in  [#10, #13, ' ', ';', '.']))
      and (BaseText[WordPos - 1] in  [#10, #13, ' '])  then
        Result := True
      else
        Result := False
    else
      Result := False;
  end;

begin
  TurnText := Clipboard.AsText;
  BaseText := UpperCase(TurnText);
  //  代入文の反転処理(Pascal)
  i := 2;
  while  i < Length(BaseText) - 1  do
  begin
    if  (BaseText[i] = ':') and (BaseText[i + 1] = '=')  then
      begin
  //  左側の文字列を検出
        j := i - 1;
        Eot := False;
        Notsp := False;
        QuoteFnd := False;
        LeftLen := 0;
        while  (j > 0) and (not Eot)  do
        begin
          if  BaseText[j] = ''''  then  QuoteFnd := not QuoteFnd;
          if  (not Notsp) and not (BaseText[j] in [#10, #13, ' '])  then
            Notsp := True;
          if  Notsp  then
            begin
              if  not QuoteFnd  then
                case  BaseText[j]  of
                  ':', ';' :  Eot := True;
                  'O' :
                    if  LeftWordFound(j, 'DO')  then  Eot := True;
                  'N' :
                    if  LeftWordFound(j, 'THEN')
                    or  LeftWordFound(j, 'BEGIN')  then  Eot := True;
                  'Y' :
                    if  LeftWordFound(j, 'TRY')
                    or  LeftWordFound(j, 'FINALLY')  then  Eot := True;
                  'T' :
                    if  LeftWordFound(j, 'REPEAT')
                    or  LeftWordFound(j, 'EXCEPT')  then  Eot := True;
                end;
              Inc(LeftLen);
            end;
          Inc(j, -1);
        end;
        if  j = 0  then  j := 1
        else
          begin
            Inc(j, 2);
            Inc(LeftLen, -1);
          end;
        Notsp := False;
        while  (j < i) and (not Notsp)  do
        begin
          if  not (BaseText[j] in [#10, #13, ' '])  then  Notsp := True
          else
            begin
              Inc(LeftLen, -1);
              Inc(j);
            end;
        end;
        LeftPos := j;
  //  右側の文字列を検出
        j := i + 2;
        Eot := False;
        Notsp := False;
        QuoteFnd := False;
        RightPos := j;
        RightLen := 0;
        while  (j < Length(BaseText)) and (not Eot)  do
        begin
          if  BaseText[j] = ''''  then  QuoteFnd := not QuoteFnd;
          if  (not Notsp) and not (BaseText[j] in [#10, #13, ' '])  then
            begin
              RightPos := j;
              Notsp := True;
            end;
          if  Notsp  then
            begin
              if  not QuoteFnd  then
                case  BaseText[j]  of
                  ';' :  Eot := True;
                  'E' :
                    if  RightWordFound(j, 'END')
                    or  RightWordFound(j, 'EXCEPT')  then
                      Eot := True;
                  'U' :
                    if  RightWordFound(j, 'UNTIL')  then
                      Eot := True;
                  'F' :
                    if  RightWordFound(j, 'FINALLY')  then
                      Eot := True;
                end;
              Inc(RightLen);
            end;
          Inc(j);
        end;
        Inc(j, -2);
        Inc(RightLen, -1);
        Notsp := False;
        while  (j > i + 2) and (not Notsp)  do
        begin
          if  not (BaseText[j] in [#10, #13, ' '])  then  Notsp := True
          else
            begin
              Inc(RightLen, -1);
              Inc(j, -1);
            end;
        end;
  //  左右文字列の入れ換え
        if  (LeftLen < 1) or (RightLen < 1)  then  Exit;
        RightText := Copy(TurnText, RightPos, RightLen);
        LeftText := Copy(TurnText, LeftPos, LeftLen);
        Delete(TurnText, RightPos, RightLen);
        Insert(LeftText, TurnText, RightPos);
        Delete(TurnText, LeftPos, LeftLen);
        Insert(RightText, TurnText, LeftPos);
        i := RightPos + RightLen + 1;
     end
    else
      Inc(i);
  end;
  //  加工後の string をクリップボードに書き込む
  Clipboard.AsText := TurnText;
end;

end.
------------------------------------------------ ここまで

                             2000/01/07(金) 10:42am  Ohtaka(QZF12401)

Original document by Ohtaka          氏 ID:(QZF12401)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum