Attila Kovacs 629 Posted November 29, 2019 (edited) Yesterday I had the feeling I'm missing this feature from the IDE, today I can't remember why, maybe I'll recall it later 🙂     And my rough implementation of the feature:  Comments, patches, etc. are welcome. ( f.e. I'm completely ignoring the top and the bottom of the file, and other line endings as 0D 0A, also not sure about utf-8 in the code) Blocks are moving on the basis of the starting and ending line. This is intended.  procedure TKeyboardBinding.BindKeyboard(const BindingServices: IOTAKeyBindingServices); begin BindingServices.AddKeyBinding([ShortCut(VK_UP, [ssAlt])], MoveLineOrBlockUp, nil); BindingServices.AddKeyBinding([ShortCut(VK_DOWN, [ssAlt])], MoveLineOrBlockDown, nil); end; procedure TKeyboardBinding.MoveLineOrBlock(ADirection: Integer; const Context: IOTAKeyContext; var BindingResult: TKeyBindingResult); var EditPosition: IOTAEditPosition; EditBlock: IOTAEditBlock; CurrentRow: Integer; CurrentRowEnd: Integer; BlockSize: Integer; IsAutoIndent: Boolean; CodeLine: string; sr, er: Integer; begin EditPosition := Context.EditBuffer.EditPosition; EditBlock := Context.EditBuffer.EditBlock; // Store original cursor row CurrentRow := EditPosition.Row; // Length of the selected block (0 means no block) BlockSize := EditBlock.Size; // Store AutoIndent property IsAutoIndent := Context.EditBuffer.BufferOptions.AutoIndent; // Turn off AutoIndent, if necessary if IsAutoIndent then Context.EditBuffer.BufferOptions.AutoIndent := False; if (EditPosition.Row = 1) and (ADirection = -1) then Exit; if (BlockSize = 0) then begin // Only a single line to move EditPosition.Save; if ADirection = 1 then EditPosition.Move(EditPosition.Row + ADirection, EditPosition.Column); // Move to end of current line EditPosition.MoveEOL; // Get the column position CurrentRowEnd := EditPosition.Column; // Move to beginning of current line EditPosition.MoveBOL; // Get the text of the current line, less the EOL marker CodeLine := EditPosition.Read(CurrentRowEnd + 1); if Ord(CodeLine[Length(CodeLine)]) <> $0A then Exit; EditPosition.Move(EditPosition.Row - 1, EditPosition.Column); // Move to end of current line EditPosition.MoveEOL; // Get the column position CurrentRowEnd := EditPosition.Column; // Move to beginning of current line EditPosition.MoveBOL; // Get the text of the current line, less the EOL marker CodeLine := CodeLine + EditPosition.Read(CurrentRowEnd + 1); if Ord(CodeLine[Length(CodeLine)]) <> $0A then Exit; EditPosition.Delete(Length(CodeLine) - 2); EditPosition.InsertText(CodeLine); // Move cursor to original position EditPosition.Restore; EditPosition.Restore; EditPosition.Move(EditPosition.Row + ADirection, EditPosition.Column); BindingResult := krHandled; end else begin // More than one line selected. Get block text sr := EditBlock.StartingRow; er := EditBlock.EndingRow; if (EditBlock.StartingColumn <> 1) or (EditBlock.EndingColumn <> 1) then begin EditPosition.Move(sr, 1); EditBlock.BeginBlock; EditPosition.Move(er + 1, 1); EditBlock.EndBlock; sr := EditBlock.StartingRow; er := EditBlock.EndingRow; end; CodeLine := EditBlock.Text; EditBlock.Delete; EditPosition.Move(EditPosition.Row + ADirection, 1); // Insert block text EditPosition.InsertText(CodeLine); EditPosition.Move(sr + ADirection, 1); EditBlock.BeginBlock; EditPosition.Move(er + ADirection, 1); EditBlock.EndBlock; BindingResult := krHandled; end; // Restore AutoIndent, if necessary if IsAutoIndent then Context.EditBuffer.BufferOptions.AutoIndent := True; BindingResult := krHandled; end; procedure TKeyboardBinding.MoveLineOrBlockDown(const Context: IOTAKeyContext; KeyCode: TShortCut; var BindingResult: TKeyBindingResult); begin MoveLineOrBlock(1, Context, BindingResult); end; procedure TKeyboardBinding.MoveLineOrBlockUp(const Context: IOTAKeyContext; KeyCode: TShortCut; var BindingResult: TKeyBindingResult); begin MoveLineOrBlock(-1, Context, BindingResult); end;  Edited November 29, 2019 by Attila Kovacs Share this post Link to post
Uwe Raabe 2057 Posted November 29, 2019 MMX Code Explorer offers that with Shift-Alt-Up/Down (if no other key binding catches it first). 1 Share this post Link to post
Attila Kovacs 629 Posted November 29, 2019 Uwe, why am I not surprised? <o> 🙂 I should try MMX some day. Share this post Link to post
FreeDelphiPascal 19 Posted June 6 DDevExt also has this capability https://github.com/ahausladen/DDevExtensions Share this post Link to post