2019-07-08 21:58:12 +03:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using ICSharpCode.TextEditor.Document ;
using ICSharpCode.TextEditor ;
2019-07-13 12:01:16 +03:00
using System.Text.RegularExpressions ;
2019-07-08 21:58:12 +03:00
namespace VisualPascalABC
{
public partial class Form1
{
string Spaces ( int n ) = > new string ( ' ' , n ) ;
string GetLine ( int lineNum )
{
var ta = CurrentCodeFileDocument . TextEditor . ActiveTextAreaControl . TextArea ;
var doc = ta . Document ;
if ( lineNum < doc . TotalNumberOfLines )
2020-02-14 19:47:41 +03:00
return TextUtilities . GetLineAsString ( doc , lineNum ) ;
2019-07-08 21:58:12 +03:00
else return null ;
}
void GetCurNextLines ( out string Current , out string Next , out string Prev ) // Next - следующая непустая строка
{
var ta = CurrentCodeFileDocument . TextEditor . ActiveTextAreaControl . TextArea ;
Current = GetLine ( ta . Caret . Line ) ;
2019-08-02 10:17:49 +03:00
2019-07-08 21:58:12 +03:00
var i = ta . Caret . Line + 1 ;
do
{
Next = GetLine ( i ) ;
i + + ;
} while ( Next ! = null & & Next . Trim ( ) = = "" ) ;
2019-08-02 10:17:49 +03:00
2019-07-08 21:58:12 +03:00
Prev = null ;
2019-08-02 10:17:49 +03:00
if ( ta . Caret . Line = = 0 )
return ;
var j = ta . Caret . Line ;
do
2019-07-24 21:22:29 +03:00
{
2019-08-02 10:17:49 +03:00
j - - ;
Prev = GetLine ( j ) ;
} while ( j > 0 & & Prev . Trim ( ) = = "" ) ;
if ( Prev . Trim ( ) = = "" )
Prev = null ;
2019-07-08 21:58:12 +03:00
}
int Indent ( string s )
{
return Array . FindIndex ( s . ToCharArray ( ) , c = > c ! = ' ' ) ;
}
2019-07-13 12:01:16 +03:00
int CurrentOffset ( )
{
var editor = VisualPascalABCProgram . MainForm . CurrentCodeFileDocument . TextEditor ;
var ta = editor . ActiveTextAreaControl . TextArea ;
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
return editor . ActiveTextAreaControl . TextArea . Document . PositionToOffset ( tl_beg ) ;
}
2019-07-08 21:58:12 +03:00
private bool TextArea_KeyEventHandler ( char ch )
{
if ( ! tsAutoInsertCode . Checked )
return false ;
try
{
var editor = VisualPascalABCProgram . MainForm . CurrentCodeFileDocument . TextEditor ;
var ta = editor . ActiveTextAreaControl . TextArea ;
var doc = ta . Document ;
2019-07-13 12:01:16 +03:00
2019-08-15 23:54:13 +03:00
/ * if ( ch = = ' ' )
2019-07-13 12:01:16 +03:00
{
var caret1 = editor . ActiveTextAreaControl . Caret ;
int start1 = TextUtilities . FindPrevWordStart ( editor . Document , caret1 . Offset ) ;
var Text1 = editor . Document . GetText ( start1 , caret1 . Offset - start1 ) . TrimEnd ( ) ;
2019-07-24 15:45:12 +03:00
if ( Text1 . ToLower ( ) . StartsWith ( "for" ) | | Text1 . ToLower ( ) . StartsWith ( "foreach" ) )
2019-07-13 12:01:16 +03:00
{
2019-07-26 23:05:49 +03:00
var curline = TextUtilities . GetLineAsString ( editor . Document , caret1 . Line ) ;
var len = curline . TrimEnd ( ) . Length ;
if ( ta . Caret . Column = = len )
{
doc . Replace ( CurrentOffset ( ) , curline . Length - len , " var" ) ;
ta . Caret . Column = ta . Caret . Column + 4 ;
}
2019-07-13 12:01:16 +03:00
}
return false ;
2019-08-15 23:54:13 +03:00
} * /
2019-07-08 21:58:12 +03:00
/ * if ( ch = = '(' )
{
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
doc . Insert ( offset , ")" ) ;
return false ;
} * /
if ( ch ! = '\n' )
return false ;
var caret = editor . ActiveTextAreaControl . Caret ;
int start = TextUtilities . FindPrevWordStart ( editor . Document , caret . Offset ) ;
2019-08-07 15:24:12 +03:00
// Нужно, чтобы в Text было последнее слово в строке !!! Исключение - когда в следующей надо сделать просто сдвиг
2019-07-08 21:58:12 +03:00
var Text = editor . Document . GetText ( start , caret . Offset - start ) . TrimEnd ( ) ;
2020-02-14 19:47:41 +03:00
var TextToLower = Text . ToLower ( ) ;
2019-08-07 15:24:12 +03:00
//var curStrEnd = TextUtilities.GetLineAsString(editor.Document, caret.Line).Substring(caret.Column);
2019-07-08 21:58:12 +03:00
2020-02-14 19:47:41 +03:00
if ( TextToLower = = "begin" )
2019-07-08 21:58:12 +03:00
{
string cur , next , prev ;
GetCurNextLines ( out cur , out next , out prev ) ;
2019-08-07 15:24:12 +03:00
// Ничего не надо делать если begin - не последнее слово в строке
var curStrEnd = cur . Substring ( caret . Column ) ;
if ( ! string . IsNullOrWhiteSpace ( curStrEnd ) )
return false ;
2019-07-08 21:58:12 +03:00
// анализ предыдущей
var icur = Indent ( cur ) ;
if ( cur . Trim ( ) . ToLower ( ) = = "begin" & & ( next = = null | | Indent ( next ) < icur | | Indent ( next ) = = icur & & ! next . TrimStart ( ) . ToLower ( ) . StartsWith ( "end" ) ) ) // значит, это единственное слово begin в строке
{
// Проанализируем предыдущий оператор по первому слову
var pst = prev ? . TrimStart ( ) . ToLower ( ) ;
if ( pst ! = null )
2020-02-14 19:47:41 +03:00
//if (pst.StartsWith("if") || pst.StartsWith("for") || pst.StartsWith("loop") || pst.StartsWith("with") || pst.StartsWith("on") || pst.StartsWith("while") || pst.StartsWith("else") || pst.StartsWith("foreach")) // потом улучшу - для нескольких выборов
if ( Regex . IsMatch ( pst , "^(if|else|for|loop|while|foreach|with|on)" ) )
2019-07-24 20:11:01 +03:00
{
// Надо удалить в текущей строке пробелы чтобы выровнять begin по if
var iprev = Indent ( prev ) ;
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
2019-07-26 23:05:49 +03:00
var cls = doc . GetLineSegment ( ta . Caret . Line ) ;
// надо удалить всю строчку с begin и сформировать новую
doc . Replace ( cls . Offset , cls . Length , Spaces ( iprev ) + "begin" ) ;
ta . Caret . Column = iprev + 5 ;
icur = iprev ;
2019-07-24 20:11:01 +03:00
}
2019-07-08 21:58:12 +03:00
}
2019-07-13 12:01:16 +03:00
2019-07-08 21:58:12 +03:00
ta . InsertString ( "\n" + Spaces ( icur + 2 ) ) ;
if ( next = = null | | Indent ( next ) < icur | | Indent ( next ) = = icur & & ! next . TrimStart ( ) . ToLower ( ) . StartsWith ( "end" ) )
{
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
var send = "\n" + Spaces ( icur ) + "end" ;
2019-07-24 21:22:29 +03:00
if ( next = = null & & ( prev = = null | | ! ( prev . TrimStart ( ) . ToLower ( ) . StartsWith ( "procedure" ) | | prev . TrimStart ( ) . ToLower ( ) . StartsWith ( "function" ) ) ) )
2019-07-08 21:58:12 +03:00
send + = "." ;
else send + = ";" ;
doc . Insert ( offset , send ) ;
}
return true ;
}
2019-07-13 12:01:16 +03:00
2020-02-14 19:47:41 +03:00
else if ( TextToLower = = "repeat" ) // repeat .. until
2019-07-08 21:58:12 +03:00
{
string cur , next , prev ;
GetCurNextLines ( out cur , out next , out prev ) ;
2019-08-07 15:24:12 +03:00
if ( ! string . IsNullOrWhiteSpace ( cur . Substring ( caret . Column ) ) )
return false ;
2019-07-08 21:58:12 +03:00
var icur = Indent ( cur ) ;
ta . InsertString ( "\n" + Spaces ( icur + 2 ) ) ;
if ( next = = null | | Indent ( next ) < icur | | Indent ( next ) = = icur & & ! next . TrimStart ( ) . ToLower ( ) . StartsWith ( "until" ) )
{
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
var send = "\n" + Spaces ( icur ) + "until ;" ;
doc . Insert ( offset , send ) ;
}
return true ;
}
2019-07-13 12:01:16 +03:00
2020-02-14 19:47:41 +03:00
else if ( Regex . IsMatch ( TextToLower , "class|record" ) ) // class .. end, record .. end
2020-02-08 11:04:07 +03:00
{
string cur , next , prev ;
GetCurNextLines ( out cur , out next , out prev ) ;
if ( ! string . IsNullOrWhiteSpace ( cur . Substring ( caret . Column ) ) )
return false ;
var icur = Indent ( cur ) ;
ta . InsertString ( "\n" + Spaces ( icur + 2 ) ) ;
if ( next = = null | | Indent ( next ) < icur | | Indent ( next ) = = icur & & ! next . TrimStart ( ) . ToLower ( ) . StartsWith ( "until" ) )
{
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
var send = "\n" + Spaces ( icur ) + "end;" ;
doc . Insert ( offset , send ) ;
}
return true ;
}
2020-02-14 19:47:41 +03:00
else if ( TextToLower = = "of" )
2019-07-08 21:58:12 +03:00
{
string cur , next , prev ;
GetCurNextLines ( out cur , out next , out prev ) ;
2019-08-07 15:24:12 +03:00
if ( ! string . IsNullOrWhiteSpace ( cur . Substring ( caret . Column ) ) )
return false ;
2019-07-08 21:58:12 +03:00
var icur = Indent ( cur ) ;
ta . InsertString ( "\n" + Spaces ( icur + 2 ) ) ;
2019-07-13 12:01:16 +03:00
if ( cur . TrimStart ( ) . ToLower ( ) . StartsWith ( "case" ) & & next = = null | | Indent ( next ) < icur | | Indent ( next ) = = icur & & ! next . TrimStart ( ) . ToLower ( ) . StartsWith ( "end" ) )
{
var tl_beg = new TextLocation ( ta . Caret . Column , ta . Caret . Line ) ;
int offset = doc . PositionToOffset ( tl_beg ) ;
var send = "\n" + Spaces ( icur ) + "end;" ;
doc . Insert ( offset , send ) ;
}
2019-07-08 21:58:12 +03:00
return true ;
}
2019-07-13 12:01:16 +03:00
2020-02-14 19:47:41 +03:00
else if ( Regex . IsMatch ( TextToLower , "then|else|do|try|except|finally|var" ) )
2019-07-08 21:58:12 +03:00
{
2020-02-14 19:47:41 +03:00
if ( ta . Caret . Line > 0 & & TextToLower = = "else" )
{
var prevSeg = doc . GetLineSegment ( ta . Caret . Line - 1 ) ;
var prev = GetLine ( ta . Caret . Line - 1 ) . TrimEnd ( ) ;
if ( prev [ prev . Length - 1 ] = = ';' )
{
doc . Replace ( prevSeg . Offset + prevSeg . Length - 1 , 1 , "" ) ;
}
}
2019-07-13 12:01:16 +03:00
var cur = GetLine ( ta . Caret . Line ) ;
var icur = Indent ( cur ) ;
ta . InsertString ( "\n" + Spaces ( icur + 2 ) ) ;
2020-02-14 19:47:41 +03:00
2019-07-08 21:58:12 +03:00
return true ;
2019-07-13 12:01:16 +03:00
}
2020-02-14 19:47:41 +03:00
else
2019-07-13 12:01:16 +03:00
{
2020-02-08 11:04:07 +03:00
string cur , next , prev ;
GetCurNextLines ( out cur , out next , out prev ) ;
if ( ta . Caret . Column > = cur . Length )
{
2020-02-14 19:47:41 +03:00
var prevTrimEnd = prev . TrimEnd ( ) ;
2020-02-08 11:04:07 +03:00
// если prev заканчивается на then, а cur не начинается с begin, то отступ назад
2020-02-14 19:47:41 +03:00
if ( ( prevTrimEnd . EndsWith ( "then" , StringComparison . InvariantCultureIgnoreCase ) | |
prevTrimEnd . EndsWith ( "else" , StringComparison . InvariantCultureIgnoreCase ) | |
prevTrimEnd . EndsWith ( "do" , StringComparison . InvariantCultureIgnoreCase ) )
2020-02-08 11:04:07 +03:00
& &
! ( cur . TrimStart ( ) . StartsWith ( "begin" , StringComparison . InvariantCultureIgnoreCase ) ) )
{
var iprev = Indent ( prev ) ;
ta . InsertString ( "\n" + Spaces ( iprev ) ) ;
return true ;
}
/ * if ( Regex . IsMatch ( curline , @"^\s*\w+\s*:=" , RegexOptions . IgnoreCase ) ) // пока тут добавление ; после присваивания. Плохо перед else! И плохо если выражение продолжается на следующей строке! Убираем.
2019-07-24 20:11:01 +03:00
{
2019-08-15 23:54:13 +03:00
if ( curline . Length > 0 )
{
var last = curline [ curline . Length - 1 ] ;
if ( ! char . IsLetterOrDigit ( last ) & & last ! = ']' & & last ! = ')' )
return false ;
}
2020-02-08 11:04:07 +03:00
var curlinenew = Regex . Replace ( curline , @"(\s*)(\S+)(\s*):=(\s*)([^;]+)(\s*)(;?)$" , @"$1$2 := $5;" , RegexOptions . IgnoreCase ) ;
2019-07-24 20:11:01 +03:00
while ( curlinenew . EndsWith ( ";;" ) )
curlinenew = curlinenew . Remove ( curlinenew . Length - 1 ) ;
doc . Replace ( seg . Offset , curline . Length , curlinenew ) ;
ta . Caret . Column = curlinenew . Length ;
return false ;
2020-02-08 11:04:07 +03:00
} * /
}
2019-07-24 20:11:01 +03:00
}
2019-07-08 21:58:12 +03:00
return false ;
}
catch ( Exception e )
{
}
return false ;
}
}
}