// Duplicate Line Key Binding
// Copyright (c) 2001-2010 Cary Jensen, Jensen Data Systems, Inc.
unit Dupline;
// Duplicate Line Key Binding
// Copyright (c) 2001-2010 Cary Jensen, Jensen Data Systems, Inc.
//
// You may freely distribute this unit, so long as this comment
// section is retained, and no fee is charged for it.
//
// This key binding is provided as a demonstration of key bindings.
//
// To use this key binding, install it into a design-time package.
//
// Once installed, this key binding adds a Ctrl-Shift-D (duplicate line) function to the code editor.
//
// No warranty is intended or implied concerning the
// appropriateness of this code example for any other use. If you use
// this examples, or any part of it, you assume all responsibility
// for ensuring that it works as intended.
//
// For information concerning Delphi training, visit www.jensendatasystems.com.
interface
uses
SysUtils, Classes, Dialogs, Controls, Windows, Menus, ToolsAPI;
procedure register;
implementation
type
TDupLineBinding =
class(TNotifierObject, IOTAKeyboardBinding)
private
public
procedure Dupline(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
procedure AppendComment(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
procedure CommentToggle(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
procedure CommentToggle1(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
{ IOTAKeyboardBinding }
function GetBindingType: TBindingType;
function GetDisplayName:
string;
function GetName:
string;
procedure BindKeyboard(
const BindingServices: IOTAKeyBindingServices);
end;
procedure register;
begin
(BorlandIDEServices
as IOTAKeyboardServices).AddKeyboardBinding(TDupLineBinding.Create);
end;
{ TKeyBindingImpl }
function TDupLineBinding.GetBindingType: TBindingType;
begin
Result := btPartial;
end;
function TDupLineBinding.GetDisplayName:
string;
begin
Result := '
Duplicate Line Binding';
end;
function TDupLineBinding.GetName:
string;
begin
Result := '
jdsi.dupline';
end;
procedure TDupLineBinding.BindKeyboard(
const BindingServices: IOTAKeyBindingServices);
begin
BindingServices.AddKeyBinding([Shortcut(Ord('
D'), [ssShift, ssCtrl])], Dupline,
nil);
// BindingServices.AddKeyBinding([Shortcut(Ord('C'), [ssShift, ssCtrl])], AppendComment, nil);
BindingServices.AddKeyBinding([Shortcut(VK_F1, [ssShift, ssCtrl])], CommentToggle,
nil);
// BindingServices.AddKeyBinding([Shortcut(VK_F1, [ssShift, ssCtrl])], CommentToggle1, nil);
// Add additional key bindings here
end;
procedure TDupLineBinding.Dupline(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
var
EditPosition: IOTAEditPosition;
EditBlock: IOTAEditBlock;
CurrentRow: Integer;
CurrentRowEnd: Integer;
BlockSize: Integer;
IsAutoIndent: Boolean;
CodeLine:
string;
begin
EditPosition := Context.EditBuffer.EditPosition;
EditBlock := Context.EditBuffer.EditBlock;
// Save the current edit block and edit position
EditBlock.Save;
EditPosition.Save;
try
// 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 no block is selected, or the selected block is a single line,
// then duplicate just the current line
if (BlockSize = 0)
or (EditBlock.StartingRow = EditPosition.Row)
or
((BlockSize <> 0)
and ((EditBlock.StartingRow + 1) = (EditPosition.Row))
and
(EditBlock.EndingColumn = 1))
then
begin
// Only a single line to duplicate
// 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);
// Add a line
EditPosition.InsertText(#13);
// Move to column 1
EditPosition.Move(CurrentRow, 1);
// Insert the copied line
EditPosition.InsertText(CodeLine);
end
else
begin
// More than one line selected. Get block text
CodeLine := EditBlock.Text;
// Move to the end of the block
EditPosition.Move(EditBlock.EndingRow, EditBlock.EndingColumn);
// Add a line
EditPosition.InsertText(#13);
// Insert block text
EditPosition.InsertText(CodeLine);
end;
// Restore AutoIndent, if necessary
if IsAutoIndent
then
Context.EditBuffer.BufferOptions.AutoIndent := True;
BindingResult := krHandled;
finally
// Move cursor to original position
EditPosition.Restore;
// Restore the original block (if one existed)
EditBlock.Restore;
end;
end;
procedure TDupLineBinding.AppendComment(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
var
EditPosition: IOTAEditPosition;
eColumn: Integer;
begin
EditPosition := Context.EditBuffer.EditPosition;
EditPosition.MoveEOL;
eColumn := EditPosition.Column;
EditPosition.InsertText('
// ' + DateTimeToStr(Now) + #13);
EditPosition.Move(EditPosition.Row, eColumn);
EditPosition.InsertText('
// Author: Cary Jensen');
BindingResult := krHandled;
end;
procedure TDupLineBinding.CommentToggle(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
var
EditPosition: IOTAEditPosition;
EditBlock: IOTAEditBlock;
StartRow: Integer;
EndRow: Integer;
Comment: Boolean;
begin
// original edit position
EditPosition := Context.EditBuffer.EditPosition;
EditPosition.Save;
// edit block
EditBlock := Context.EditBuffer.EditBlock;
// find the starting and ending rows to operate on
if EditBlock.Size = 0
then
begin
StartRow := EditPosition.Row;
EndRow := EditPosition.Row;
end
else if (EditBlock.EndingColumn = 1)
then
begin
StartRow := EditBlock.StartingRow;
EndRow := EditBlock.EndingRow - 1;
end
else
begin
StartRow := EditBlock.StartingRow;
EndRow := EditBlock.EndingRow;
end;
// toggle comments
repeat
begin
EditPosition.Move(StartRow, 1);
while EditPosition.IsWhiteSpace
do
EditPosition.MoveRelative(0, 1);
if EditPosition.Character = '
/'
then
begin
EditPosition.MoveRelative(0, 1);
if EditPosition.Character = '
/'
then
Comment := True
else
Comment := False
end
else
Comment := False;
if Comment
then
begin
EditPosition.MoveRelative(0, -1);
EditPosition.Delete(2);
end
else
begin
EditPosition.MoveBOL;
EditPosition.InsertText('
//');
end;
Inc(StartRow);
end;
until
(StartRow > EndRow);
// update caret position
EditPosition.Restore;
EditPosition.Move(StartRow, EditPosition.Column);
// All done
BindingResult := krHandled;
end;
procedure TDupLineBinding.CommentToggle1(
const Context: IOTAKeyContext; KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
begin
//
end;
end.