Skip to content

Commit

Permalink
Added a functional-style struct CharIter to replace TextIter
Browse files Browse the repository at this point in the history
  • Loading branch information
ktvoelker committed Dec 10, 2010
1 parent 13b32e7 commit b22aa4a
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 58 deletions.
154 changes: 154 additions & 0 deletions Di/CharIter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//
// CharIter.cs
//
// Author:
// Karl Voelker <[email protected]>
//
// Copyright (c) 2010 Karl Voelker
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using Gtk;
namespace Di
{
public struct CharIter
{
private TextIter _iter;

public CharIter LineStart
{
get
{
return this - _iter.LineOffset;
}
}

public CharIter LineEnd
{
get
{
var ret = this;
ret._iter.ForwardToLineEnd();
return ret;
}
}

public Gtk.TextIter GtkIter
{
get
{
return _iter;
}
}

public string Char
{
get
{
return _iter.Char;
}
}

public CharIter(TextIter i)
{
_iter = i;
}

public override bool Equals(object obj)
{
if (obj is CharIter)
{
return this == (CharIter) obj;
}
else
{
return false;
}
}

public override int GetHashCode()
{
return _iter.GetHashCode();
}

private static T OffsetOp<T>(CharIter i, CharIter j, Func<int, int, T> op)
{
return op(i._iter.Offset, j._iter.Offset);
}

public CharIter ForwardLines(int n)
{
var ret = this;
ret._iter.ForwardLines(n);
return ret;
}

public CharIter BackwardLines(int n)
{
var ret = this;
ret._iter.BackwardLines(n);
return ret;
}

public static CharIter operator +(CharIter i, int n)
{
i._iter.ForwardChars(n);
return i;
}

public static CharIter operator -(CharIter i, int n)
{
i._iter.BackwardChars(n);
return i;
}

public static int operator -(CharIter i, CharIter j)
{
return OffsetOp(i, j, (m, n) => m - n);
}

public static bool operator <(CharIter i, CharIter j)
{
return OffsetOp(i, j, (m, n) => m < n);
}

public static bool operator >(CharIter i, CharIter j)
{
return OffsetOp(i, j, (m, n) => m > n);
}

public static bool operator ==(CharIter i, CharIter j)
{
return OffsetOp(i, j, (m, n) => m == n);
}

public static bool operator !=(CharIter i, CharIter j)
{
return OffsetOp(i, j, (m, n) => m != n);
}

public static CharIter operator ++(CharIter i)
{
i._iter.ForwardChar();
return i;
}

public static CharIter operator --(CharIter i)
{
i._iter.BackwardChar();
return i;
}
}
}

13 changes: 6 additions & 7 deletions Di/Controller/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using Gtk;
namespace Di.Controller
{
public struct Movement
{
public TextIter CursorStart, CursorEnd, RangeStart, RangeEnd;
public Range CursorRange, ActionRange;
}

public interface ICommand
Expand Down Expand Up @@ -75,7 +74,7 @@ public abstract class MoveCommand : RepeatCommand
{
public override void Execute(Buffer b)
{
b.GtkTextBuffer.PlaceCursor(Evaluate(b).CursorEnd);
b.GtkTextBuffer.PlaceCursor(Evaluate(b).CursorRange.End.GtkIter);
}

public abstract Movement Evaluate(Buffer b);
Expand Down Expand Up @@ -107,8 +106,8 @@ public override Movement Evaluate(Buffer b)
if (_count >= 1)
{
var lastMovement = _cmd.Evaluate(b);
movement.CursorEnd = lastMovement.CursorEnd;
movement.RangeEnd = lastMovement.RangeEnd;
movement.CursorRange.End = lastMovement.CursorRange.End;
movement.ActionRange.End = lastMovement.ActionRange.End;
}
return movement;
}
Expand Down Expand Up @@ -142,10 +141,10 @@ public LoneCommand Complete(MoveCommand move)
public void Execute(Buffer b, MoveCommand move)
{
var movement = move.Evaluate(b);
Execute(b, movement.RangeStart, movement.RangeEnd);
Execute(b, movement.ActionRange);
}

public abstract void Execute(Buffer b, TextIter start, TextIter end);
public abstract void Execute(Buffer b, Range r);
}

/// <summary>
Expand Down
40 changes: 17 additions & 23 deletions Di/Controller/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,14 @@ public override Movement Evaluate(Buffer b)
{
// TODO does CursorPosition return a char offset or a byte index?
// The rest of the logic uses char offsets because we only want to work in whole chars.
var pos = b.GtkTextBuffer.CursorPosition;
var cursorStart = b.GtkTextBuffer.GetIterAtOffset(pos);
var rangeStart = b.GtkTextBuffer.GetIterAtOffset(pos - cursorStart.LineOffset);
var rangeEnd = b.GtkTextBuffer.GetIterAtLine(cursorStart.Line + 1);
var cursorEnd = b.GtkTextBuffer.GetIterAtLineOffset(rangeEnd.Line, cursorStart.LineOffset);
var cursorStart = b.GtkTextBuffer.GetCursorIter();
var actionStart = cursorStart.LineStart;
var actionEnd = actionStart.ForwardLines(1);
var cursorEnd = actionEnd + (cursorStart - actionStart);
return new Movement()
{
CursorStart = cursorStart,
CursorEnd = cursorEnd,
RangeStart = rangeStart,
RangeEnd = rangeEnd
CursorRange = new Range(cursorStart, cursorEnd),
ActionRange = new Range(actionStart, actionEnd)
};
}
}
Expand Down Expand Up @@ -108,36 +105,33 @@ public override void Execute(Buffer b)

public class Delete : RangeCommand
{
public override void Execute(Buffer b, Gtk.TextIter start, Gtk.TextIter end)
public override void Execute(Buffer b, Range r)
{
b.GtkTextBuffer.DeleteInteractive(ref start, ref end, true);
b.GtkTextBuffer.Delete(r);
}
}

public class Backspace : MoveCommand
{
public override Movement Evaluate(Buffer b)
{
Gtk.TextIter start = b.GtkTextBuffer.GetIterAtOffset(b.GtkTextBuffer.CursorPosition);
Gtk.TextIter end = start;
Gtk.TextIter line = start;
line.BackwardChars(line.LineOffset);
if (start.LineOffset <= 1)
CharIter start = b.GtkTextBuffer.GetCursorIter();
CharIter end = start;
CharIter line = start.LineStart;
if (start - line <= 1)
{
end.BackwardChar();
--end;
}
else
{
string xs = new Model.Range(line, end).Chars.Trim();
string xs = new Range(line, end).Chars.Trim();
int n = xs == string.Empty ? 2 : 1;
end.BackwardChars(n);
end -= n;
}
return new Movement()
{
CursorStart = start,
CursorEnd = end,
RangeStart = start,
RangeEnd = end
CursorRange = new Range(start, end),
ActionRange = new Range(start, end)
};
}
}
Expand Down
3 changes: 2 additions & 1 deletion Di/Di.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
<Compile Include="Controller\KeyMap.cs" />
<Compile Include="Controller\UnparsedCommand.cs" />
<Compile Include="Controller\Command.cs" />
<Compile Include="Model\Range.cs" />
<Compile Include="Range.cs" />
<Compile Include="CharIter.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
Expand Down
17 changes: 17 additions & 0 deletions Di/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,22 @@ public static Func<U, V, W> Apply<T, U, V, W>(this Func<T, U, V, W> f, T t)
{
return (u, v) => f(t, u, v);
}

public static CharIter Item(this Gtk.TextBuffer buffer, int index)
{
return new CharIter(buffer.GetIterAtOffset(index));
}

public static CharIter GetCursorIter(this Gtk.TextBuffer buffer)
{
return buffer.Item(buffer.CursorPosition);
}

public static void Delete(this Gtk.TextBuffer buffer, Range r)
{
var start = r.Start.GtkIter;
var end = r.End.GtkIter;
buffer.DeleteInteractive(ref start, ref end, true);
}
}
}
34 changes: 13 additions & 21 deletions Di/Model/Range.cs → Di/Range.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,33 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using Gtk;
namespace Di.Model
using System.Text;
namespace Di
{
public class Range
public struct Range
{
private TextIter _start;
private TextIter _end;
public CharIter Start;
public CharIter End;

public string Chars
{
get
{
char[] chars = new char[_end.Offset - _start.Offset];
for (TextIter i = _start; i.Offset < _end.Offset; i.ForwardChar())
var sb = new StringBuilder(End - Start);
for (CharIter i = Start; i < End; ++i)
{
foreach (char c in i.Char)
{
chars[i.Offset - _start.Offset] = c;
}
sb.Append(i.Char);
}
return new string(chars);
return sb.ToString();
}
}

public Range(TextIter i, int n)
{
_start = i;
_end = i;
_end.ForwardChars(n);
}
public Range(CharIter i, int n) : this(i, i + n) { }

public Range(TextIter s, TextIter e)
public Range(CharIter s, CharIter e)
{
_start = s;
_end = e;
Start = s;
End = e;
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions Di/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
TODO
====

Define a more functional class to replace TextIter

Use it instead of TextIter in Range

Create extension methods allowing it to be used with GtkTextBuffer

Implement remaining basic commands:
Up line
Left char
Expand Down

0 comments on commit b22aa4a

Please sign in to comment.