Ejemplo n.º 1
0
        private void Scintilla_BeforeTextDelete(object sender, TextModifiedEventArgs e)
        {
            if (!_isEnabled)
            {
                return;
            }

            if (_snippetLinks.IsActive && !_pendingUndo && !(e.UndoRedoFlags.IsUndo || e.UndoRedoFlags.IsRedo))
            {
                _pendingUndo = true;
                Scintilla.UndoRedo.BeginUndoAction();
                _snippetLinkTimer.Enabled = true;
            }

            ManagedRange undoneSnippetLinkRange = null;

            if (e.UndoRedoFlags.IsUndo && _snippetLinks.IsActive)
            {
                foreach (ManagedRange mr in Scintilla.ManagedRanges)
                {
                    if (mr.Start == e.Position && mr.Length == e.Length && mr.Length > 1)
                    {
                        undoneSnippetLinkRange = mr;

                        //	Expanding the range So that it won't get marked for deletion
                        mr.End++;
                    }
                }
            }

            //	It's possible that the end point may have been deleted. The endpoint
            //	is an ultra persistent marker that cannot be deleted until the Snippet
            //	Link mode is deactivated. Place a new EndPoint at the begining of the
            //	deleted range.
            if (_snippetLinks.IsActive && _snippetLinks.EndPoint != null && _snippetLinks.EndPoint.Scintilla == null)
            {
                SnippetLinkEnd eci = new SnippetLinkEnd(e.Position, Scintilla);
                Scintilla.ManagedRanges.Add(eci);
                _snippetLinks.EndPoint = eci;
            }

            //	Now collapse the Undone range in preparation for the
            //	newly inserted text that will be put in here
            if (undoneSnippetLinkRange != null)
            {
                undoneSnippetLinkRange.End = undoneSnippetLinkRange.Start;
            }

            //	Check to see if all SnippetLink ranges have been deleted.
            //	If this is the case we need to turn Deactivate SnippetLink
            //	mode.

            bool deactivate = true;

            foreach (SnippetLink sl in _snippetLinks.Values)
            {
                if (sl.Ranges.Count > 0)
                {
                    foreach (SnippetLinkRange slr in sl.Ranges)
                    {
                        if (slr.Scintilla != null)
                        {
                            deactivate = false;
                            break;
                        }
                    }
                }
                if (!deactivate)
                {
                    break;
                }
            }

            if (deactivate && IsActive)
            {
                IsActive = false;
            }
        }
Ejemplo n.º 2
0
		private void Scintilla_BeforeTextDelete(object sender, TextModifiedEventArgs e)
		{
			if (!_isEnabled)
				return;

			if (_snippetLinks.IsActive && !_pendingUndo && !(e.UndoRedoFlags.IsUndo || e.UndoRedoFlags.IsRedo))
			{
				_pendingUndo = true;
				Scintilla.UndoRedo.BeginUndoAction();
				_snippetLinkTimer.Enabled = true;
			}

			ManagedRange undoneSnippetLinkRange = null;
			if (e.UndoRedoFlags.IsUndo && _snippetLinks.IsActive)
			{
				foreach (ManagedRange mr in Scintilla.ManagedRanges)
				{
					if (mr.Start == e.Position && mr.Length == e.Length && mr.Length > 1)
					{
						undoneSnippetLinkRange = mr;

						//	Expanding the range So that it won't get marked for deletion
						mr.End++;
					}
				}
			}

			//	It's possible that the end point may have been deleted. The endpoint
			//	is an ultra persistent marker that cannot be deleted until the Snippet
			//	Link mode is deactivated. Place a new EndPoint at the begining of the
			//	deleted range.
			if (_snippetLinks.IsActive && _snippetLinks.EndPoint != null && _snippetLinks.EndPoint.Scintilla == null)
			{
				SnippetLinkEnd eci = new SnippetLinkEnd(e.Position, Scintilla);
				Scintilla.ManagedRanges.Add(eci);
				_snippetLinks.EndPoint = eci;
			}

			//	Now collapse the Undone range in preparation for the
			//	newly inserted text that will be put in here
			if (undoneSnippetLinkRange != null)
				undoneSnippetLinkRange.End = undoneSnippetLinkRange.Start;

			//	Check to see if all SnippetLink ranges have been deleted.
			//	If this is the case we need to turn Deactivate SnippetLink
			//	mode.

			bool deactivate = true;
			foreach (SnippetLink sl in _snippetLinks.Values)
			{
				if (sl.Ranges.Count > 0)
				{
					foreach (SnippetLinkRange slr in sl.Ranges)
					{
						if (slr.Scintilla != null)
						{
							deactivate = false;
							break;
						}
					}
				}
				if (!deactivate)
					break;
			}

			if (deactivate && IsActive)
				IsActive = false;
		}
Ejemplo n.º 3
0
        internal void InsertSnippet(Snippet snip, int startPos)
        {
            NativeScintilla.BeginUndoAction();
            IsActive = false;

            string snippet = snip.RealCode;

            //	First properly indent the template. We do this by
            //	getting the indent string of the current line and
            //	adding it to all newlines
            int    indentPoint = 0;
            string line        = Scintilla.Lines.Current.Text;

            if (line != string.Empty)
            {
                while (indentPoint < line.Length)
                {
                    char c = line[indentPoint];
                    if (c != ' ' && c != '\t')
                    {
                        break;
                    }

                    indentPoint++;
                }
            }

            //	Grab the current selected text in case we have a surrounds with scenario.
            string selText = Scintilla.Selection.Text;

            //	Now we clear the selection
            if (selText != string.Empty)
            {
                Scintilla.Selection.Clear();
            }

            if (indentPoint > 0)
            {
                string indent = line.Substring(0, indentPoint);

                //	This is a bit of a tough decision, but I think the best way to handle it
                //	is to assume that the Snippet's Eol Marker matches the Platform DOCUMENT_DEFAULT
                //	but the target Eol Marker should match the Document's.
                snippet = snippet.Replace(Environment.NewLine, Scintilla.EndOfLine.EolString + indent);

                //	Same deal with the selected text if any
                selText = selText.Replace(Environment.NewLine, Scintilla.EndOfLine.EolString + indent);
            }

            int anchorPos = -1;
            int caretPos  = -1;
            int endPos    = -1;
            int selPos    = -1;
            SortedList <int, int> dropMarkers = new SortedList <int, int>();
            SortedList <int, SnippetLinkRange> indexedRangesToActivate   = new SortedList <int, SnippetLinkRange>();
            List <SnippetLinkRange>            unindexedRangesToActivate = new List <SnippetLinkRange>();
            Match m = snippetRegex1.Match(snippet);

            while (m.Success)
            {
                //	Did it match a $DropMarker$ token?
                if (m.Groups["dm"].Success)
                {
                    //	Yep, was it an indexed or unindexed DropMarker
                    if (m.Groups["dmi"].Success)
                    {
                        //	Indexed, set the indexed drop marker's character offset
                        //	if it is specified more than once the last one wins.
                        dropMarkers[int.Parse(m.Groups["dmi"].Value)] = m.Groups["dm"].Index;
                    }
                    else
                    {
                        //	Unindexed, just tack it on at the end
                        dropMarkers[dropMarkers.Count] = m.Groups["dm"].Index;
                    }

                    //	Take the token out of the string
                    snippet = snippet.Remove(m.Groups["dm"].Index, m.Groups["dm"].Length);
                }
                else if (m.Groups["c"].Success)
                {
                    //	We matched the $Caret$ Token. Since there can be
                    //	only 1 we set the caretPos. If this is specified
                    //	more than once the last one wins
                    caretPos = m.Groups["c"].Index;

                    //	Take the token out of the string
                    snippet = snippet.Remove(m.Groups["c"].Index, m.Groups["c"].Length);
                }
                else if (m.Groups["a"].Success)
                {
                    //	We matched the $Anchor$ Token. Since there can be
                    //	only 1 we set the anchorPos. If this is specified
                    //	more than once the last one wins
                    anchorPos = m.Groups["a"].Index;

                    //	Take the token out of the string
                    snippet = snippet.Remove(m.Groups["a"].Index, m.Groups["a"].Length);
                }
                else if (m.Groups["e"].Success)
                {
                    //	We matched the $End$ Token. Since there can be
                    //	only 1 we set the endPos. If this is specified
                    //	more than once the last one wins
                    endPos = m.Groups["e"].Index;

                    //	Take the token out of the string
                    snippet = snippet.Remove(m.Groups["e"].Index, m.Groups["e"].Length);
                }
                else if (m.Groups["s"].Success)
                {
                    //	We matched the $Selection$ Token. Simply insert the
                    //	selected text at this position
                    selPos = m.Groups["s"].Index;

                    //	Take the token out of the string
                    snippet = snippet.Remove(m.Groups["s"].Index, m.Groups["s"].Length);
                    snippet = snippet.Insert(m.Groups["s"].Index, selText);
                }
                else if (m.Groups["l"].Success)
                {
                    //	Finally match for Snippet Link Ranges. This is at the bottom of the if/else
                    //	because we want the more specific regex groups to match first so that this
                    //	generic expression group doesn't create a SnippetLinkRange for say the
                    //	$Caret$ Token.
                    Group g = m.Groups["l"];

                    int    rangeIndex;
                    string groupKey;

                    if (m.Groups["li"].Success)
                    {
                        //	We have a subindexed SnippetLinkRange along the lines of $sometoken[1]$
                        Group sg = m.Groups["li"];

                        //	At this point g.Value = $sometoken[1]$
                        //	and sg.Value = [1].
                        //	We want the range's Key, which would be sometoken
                        groupKey = g.Value.Substring(1, g.Value.Length - sg.Length - 2);

                        //	Now we need the range's Index which would be 1 in our fictitional case
                        rangeIndex = int.Parse(sg.Value.Substring(1, sg.Value.Length - 2));

                        //	Now we need to determine the actual start and end positions of the range.
                        //	Keep in mind we'll be stripping out the 2 $ and the subindex string (eg [1])
                        int start = startPos + g.Index;
                        int end   = start + g.Length - sg.Length - 2;

                        //	And now we add (or replace) the snippet link range at the index
                        //	keep in mind duplicates will stomp all over each other, the last
                        //	one wins. Replaced tokens won't get a range
                        indexedRangesToActivate[rangeIndex] = new SnippetLinkRange(start, end, Scintilla, groupKey);;

                        //	And remove all the token info including the subindex from the snippet text
                        //	leaving only the key
                        snippet = snippet.Remove(g.Index, 1).Remove(g.Index - 2 + g.Length - sg.Length, sg.Length + 1);
                    }
                    else
                    {
                        //	We have a regular old SnippetLinkRange along the lines of $sometoken$

                        //	We want the range's Key, which would be sometoken
                        groupKey = g.Value.Substring(1, g.Value.Length - 2);

                        //	Now we need to determine the actual start and end positions of the range.
                        //	Keep in mind we'll be stripping out the 2 $
                        int start = startPos + g.Index;
                        int end   = start + g.Length - 2;

                        //	Now create the range object
                        unindexedRangesToActivate.Add(new SnippetLinkRange(start, end, Scintilla, groupKey));

                        //	And remove all the token info from the snippet text
                        //	leaving only the key
                        snippet = snippet.Remove(g.Index, 1).Remove(g.Index + g.Length - 2, 1);
                    }
                }
                //	Any more matches? Note that I'm rerunning the regexp query
                //	on the snippet string becuase it's contents have been modified
                //	and we need to get the updated index values.
                m = snippetRegex1.Match(snippet);
            }

            //	Replace the snippet Keyword with the snippet text. Or if this
            //	isn't triggered by a shortcut, it will insert at the current
            //	Caret Position
            Scintilla.GetRange(startPos, NativeScintilla.GetCurrentPos()).Text = snippet;

            //	Now that we have the text set we can activate our link ranges
            //	we couldn't do it before becuase they were managed ranges and
            //	would get offset by the text change

            //	Since we are done adding new SnippetLinkRanges we can tack
            //	on the unindexed ranges to the end of the indexed ranges
            SnippetLinkRange[] allLinks = new SnippetLinkRange[indexedRangesToActivate.Count + unindexedRangesToActivate.Count];
            for (int i = 0; i < indexedRangesToActivate.Values.Count; i++)
            {
                allLinks[i] = indexedRangesToActivate[i];
            }

            for (int i = 0; i < unindexedRangesToActivate.Count; i++)
            {
                allLinks[i + indexedRangesToActivate.Count] = unindexedRangesToActivate[i];
            }

            foreach (SnippetLinkRange slr in allLinks)
            {
                addSnippetLink(slr);
            }

            foreach (SnippetLinkRange slr in allLinks)
            {
                slr.Init();
            }

            //	Now we need to activate the Snippet links. However we have a bit
            //	of a styling confilct. If we set the indicator styles before the
            //	SQL Lexer styles the newly added text it won't get styled. So to
            //	make sure we set the Indicator Styles after we put the call on
            //	a timer.
            if (_snippetLinks.Count > 0)
            {
                Timer t = new Timer();
                t.Interval = 10;

                //	Oh how I love anonymous delegates, this is starting to remind
                //	me of JavaScript and SetTimeout...
                t.Tick += new EventHandler(delegate(object sender, EventArgs te)
                {
                    t.Dispose();
                    IsActive = true;
                });
                t.Start();
            }

            //	Add all the Drop markers in the indexed order. The
            //	order is reversed of course because drop markers work
            //	in a FILO manner
            for (int i = dropMarkers.Count - 1; i >= 0; i--)
            {
                Scintilla.DropMarkers.Drop(startPos + dropMarkers.Values[i]);
            }

            //	Place the caret at either the position of the token or
            //	at the end of the snippet text.
            if (caretPos >= 0)
            {
                Scintilla.Caret.Goto(startPos + caretPos);
            }
            else
            {
                Scintilla.Caret.Goto(startPos + snippet.Length);
            }

            //	Ahoy, way anchor!
            if (anchorPos >= 0)
            {
                Scintilla.Caret.Anchor = startPos + anchorPos;
            }

            //	Do we have an end cursor?
            if (endPos >= 0)
            {
                //	If they have snippet link ranges activated in this snippet
                //	go ahead and set up an EndPoint marker
                if (allLinks.Length > 0)
                {
                    SnippetLinkEnd eci = new SnippetLinkEnd(endPos + startPos, Scintilla);
                    Scintilla.ManagedRanges.Add(eci);
                    _snippetLinks.EndPoint = eci;
                }
                else
                {
                    //	Otherwise we treat it like an Anchor command because
                    //	the SnippetLink mode isn't activated
                    Scintilla.Caret.Goto(endPos + startPos);
                }
            }

            NativeScintilla.EndUndoAction();
        }
Ejemplo n.º 4
0
		internal void InsertSnippet(Snippet snip, int startPos)
		{
			NativeScintilla.BeginUndoAction();
			IsActive = false;

			string snippet = snip.RealCode;

			//	First properly indent the template. We do this by
			//	getting the indent string of the current line and
			//	adding it to all newlines
			int indentPoint = 0;
			string line = Scintilla.Lines.Current.Text;
			if(line != string.Empty)
			{				
				while (indentPoint < line.Length)
				{
					char c = line[indentPoint];
					if (c != ' ' && c != '\t')
						break;

					indentPoint++;
				}
			}

			//	Grab the current selected text in case we have a surrounds with scenario.
			string selText = Scintilla.Selection.Text;
			//	Now we clear the selection
			if (selText != string.Empty)
				Scintilla.Selection.Clear();

			if (indentPoint > 0)
			{
				string indent = line.Substring(0, indentPoint);

				//	This is a bit of a tough decision, but I think the best way to handle it
				//	is to assume that the Snippet's Eol Marker matches the Platform DOCUMENT_DEFAULT
				//	but the target Eol Marker should match the Document's.
				snippet = snippet.Replace(Environment.NewLine, Scintilla.EndOfLine.EolString + indent);

				//	Same deal with the selected text if any				
				selText = selText.Replace(Environment.NewLine, Scintilla.EndOfLine.EolString + indent);
			}

			int anchorPos = -1;
			int caretPos = -1;
			int endPos = -1;
			int selPos = -1;
			SortedList<int, int> dropMarkers = new SortedList<int, int>();
			SortedList<int, SnippetLinkRange> indexedRangesToActivate = new SortedList<int, SnippetLinkRange>();
			List<SnippetLinkRange> unindexedRangesToActivate = new List<SnippetLinkRange>();
			Match m = snippetRegex1.Match(snippet);

			while (m.Success)
			{
				//	Did it match a $DropMarker$ token?
				if (m.Groups["dm"].Success)
				{
					//	Yep, was it an indexed or unindexed DropMarker
					if (m.Groups["dmi"].Success)
					{
						//	Indexed, set the indexed drop marker's character offset
						//	if it is specified more than once the last one wins.
						dropMarkers[int.Parse(m.Groups["dmi"].Value)] = m.Groups["dm"].Index;
					}
					else
					{
						//	Unindexed, just tack it on at the end
						dropMarkers[dropMarkers.Count] = m.Groups["dm"].Index;
					}

					//	Take the token out of the string
					snippet = snippet.Remove(m.Groups["dm"].Index, m.Groups["dm"].Length);
				}
				else if (m.Groups["c"].Success)
				{
					//	We matched the $Caret$ Token. Since there can be 
					//	only 1 we set the caretPos. If this is specified
					//	more than once the last one wins
					caretPos = m.Groups["c"].Index;

					//	Take the token out of the string
					snippet = snippet.Remove(m.Groups["c"].Index, m.Groups["c"].Length);
				}
				else if (m.Groups["a"].Success)
				{
					//	We matched the $Anchor$ Token. Since there can be 
					//	only 1 we set the anchorPos. If this is specified
					//	more than once the last one wins
					anchorPos = m.Groups["a"].Index;

					//	Take the token out of the string
					snippet = snippet.Remove(m.Groups["a"].Index, m.Groups["a"].Length);
				}
				else if (m.Groups["e"].Success)
				{
					//	We matched the $End$ Token. Since there can be 
					//	only 1 we set the endPos. If this is specified
					//	more than once the last one wins
					endPos = m.Groups["e"].Index;

					//	Take the token out of the string
					snippet = snippet.Remove(m.Groups["e"].Index, m.Groups["e"].Length);
				}
				else if (m.Groups["s"].Success)
				{
					//	We matched the $Selection$ Token. Simply insert the
					//	selected text at this position
					selPos = m.Groups["s"].Index;

					//	Take the token out of the string
					snippet = snippet.Remove(m.Groups["s"].Index, m.Groups["s"].Length);
					snippet = snippet.Insert(m.Groups["s"].Index, selText);
				}
				else if (m.Groups["l"].Success)
				{
					//	Finally match for Snippet Link Ranges. This is at the bottom of the if/else
					//	because we want the more specific regex groups to match first so that this
					//	generic expression group doesn't create a SnippetLinkRange for say the 
					//	$Caret$ Token.
					Group g = m.Groups["l"];

					int rangeIndex;
					string groupKey;

					if (m.Groups["li"].Success)
					{
						//	We have a subindexed SnippetLinkRange along the lines of $sometoken[1]$
						Group sg = m.Groups["li"];

						//	At this point g.Value = $sometoken[1]$
						//	and sg.Value = [1].
						//	We want the range's Key, which would be sometoken
						groupKey = g.Value.Substring(1, g.Value.Length - sg.Length - 2);

						//	Now we need the range's Index which would be 1 in our fictitional case
						rangeIndex = int.Parse(sg.Value.Substring(1, sg.Value.Length - 2));

						//	Now we need to determine the actual start and end positions of the range.
						//	Keep in mind we'll be stripping out the 2 $ and the subindex string (eg [1])
						int start = startPos + g.Index;
						int end = start + g.Length - sg.Length - 2;

						//	And now we add (or replace) the snippet link range at the index
						//	keep in mind duplicates will stomp all over each other, the last
						//	one wins. Replaced tokens won't get a range
						indexedRangesToActivate[rangeIndex] = new SnippetLinkRange(start, end, Scintilla, groupKey); ;

						//	And remove all the token info including the subindex from the snippet text 
						//	leaving only the key
						snippet = snippet.Remove(g.Index, 1).Remove(g.Index - 2 + g.Length - sg.Length, sg.Length + 1);
					}
					else
					{
						//	We have a regular old SnippetLinkRange along the lines of $sometoken$

						//	We want the range's Key, which would be sometoken
						groupKey = g.Value.Substring(1, g.Value.Length - 2);

						//	Now we need to determine the actual start and end positions of the range.
						//	Keep in mind we'll be stripping out the 2 $
						int start = startPos + g.Index;
						int end = start + g.Length - 2;

						//	Now create the range object
						unindexedRangesToActivate.Add(new SnippetLinkRange(start, end, Scintilla, groupKey));

						//	And remove all the token info from the snippet text 
						//	leaving only the key
						snippet = snippet.Remove(g.Index, 1).Remove(g.Index + g.Length - 2, 1);
					}
				}
				//	Any more matches? Note that I'm rerunning the regexp query
				//	on the snippet string becuase it's contents have been modified
				//	and we need to get the updated index values.
				m = snippetRegex1.Match(snippet);
			}

			//	Replace the snippet Keyword with the snippet text. Or if this
			//	isn't triggered by a shortcut, it will insert at the current
			//	Caret Position
			Scintilla.GetRange(startPos, NativeScintilla.GetCurrentPos()).Text = snippet;

			//	Now that we have the text set we can activate our link ranges
			//	we couldn't do it before becuase they were managed ranges and
			//	would get offset by the text change

			//	Since we are done adding new SnippetLinkRanges we can tack
			//	on the unindexed ranges to the end of the indexed ranges
			SnippetLinkRange[] allLinks = new SnippetLinkRange[indexedRangesToActivate.Count + unindexedRangesToActivate.Count];
			for (int i = 0; i < indexedRangesToActivate.Values.Count; i++)
				allLinks[i] = indexedRangesToActivate[i];

			for (int i = 0; i < unindexedRangesToActivate.Count; i++)
				allLinks[i + indexedRangesToActivate.Count] = unindexedRangesToActivate[i];

			foreach (SnippetLinkRange slr in allLinks)
				addSnippetLink(slr);

			foreach (SnippetLinkRange slr in allLinks)
				slr.Init();

			//	Now we need to activate the Snippet links. However we have a bit
			//	of a styling confilct. If we set the indicator styles before the
			//	SQL Lexer styles the newly added text it won't get styled. So to
			//	make sure we set the Indicator Styles after we put the call on
			//	a timer.
			if (_snippetLinks.Count > 0)
			{
				Timer t = new Timer();
				t.Interval = 10;

				//	Oh how I love anonymous delegates, this is starting to remind
				//	me of JavaScript and SetTimeout...
				t.Tick += new EventHandler(delegate(object sender, EventArgs te)
				{
					t.Dispose();
					IsActive = true;
				});
				t.Start();
			}

			//	Add all the Drop markers in the indexed order. The
			//	order is reversed of course because drop markers work
			//	in a FILO manner
			for (int i = dropMarkers.Count - 1; i >= 0; i--)
				Scintilla.DropMarkers.Drop(startPos + dropMarkers.Values[i]);

			//	Place the caret at either the position of the token or
			//	at the end of the snippet text.
			if (caretPos >= 0)
				Scintilla.Caret.Goto(startPos + caretPos);
			else
				Scintilla.Caret.Goto(startPos + snippet.Length);

			//	Ahoy, way anchor!
			if (anchorPos >= 0)
				Scintilla.Caret.Anchor = startPos + anchorPos;

			//	Do we have an end cursor?
			if (endPos >= 0)
			{
				//	If they have snippet link ranges activated in this snippet
				//	go ahead and set up an EndPoint marker
				if (allLinks.Length > 0)
				{
					SnippetLinkEnd eci = new SnippetLinkEnd(endPos + startPos, Scintilla);
					Scintilla.ManagedRanges.Add(eci);
					_snippetLinks.EndPoint = eci;
				}
				else
				{
					//	Otherwise we treat it like an Anchor command because
					//	the SnippetLink mode isn't activated
					Scintilla.Caret.Goto(endPos + startPos);
				}
			}

			NativeScintilla.EndUndoAction();
		}