[MonoDevelop] Removing SourceEditor{View, Buffer} dependancy from CompletionListWindow.

Peter Johanson latexer at gentoo.org
Mon Jul 18 22:15:51 EDT 2005


On Fri, Jun 17, 2005 at 12:04:39PM +0200, Lluis Sanchez wrote:
> 
> Making it independent from SourceEditor is a first step, but we
> certainly need to be independent from TextView as well. For example, it
> would be nice to have completion in a text entry, which could be used in
> a "Go to declaration" dialog, or an "Add watch" dialog.
> 
> Of course, we should be able to reuse the completion window if we decide
> to switch to another text editor.
> 
> I think the best solution is to define an adaptor interface for code
> completable editors, and provide an implementation for Gtk.TextView
> (which could be used by the main editor and the boo shell). We can later
> write adaptors for other editors when needed. This code could go to
> MonoDevelop.Base/Gui.

Indeed, this makes a lot of sense. Here are two patches, the first
creates exactly that adaptor interface, ICompletionWidget, which I've
put in MonoDevelop.Base/Gui/Completion/. Note that none of the stuff
from the completion window is moved yet by this path. Those things would
also need to be moved out of the editor assembly and into the base one.

The second patch is to the Boo addin, and adds the necessary foo to get
code completion working for that, using the new interface. Note that I
did not provide a general implementation on a Gtk.TextView, as there's
deps on GtkSourceView for both, and I know the editor is trying *not* to
be so dependant on that currently, etc, etc, etc.

No ChangeLog included again, since I definitely want more feedback,
testing, whatnot on this before I even consider proposing this for
inclusion.

Thoughts? Problems with it? Regressions? Want me to implement completion
for some other random spot too to test this out?

-pete

-- 
Peter Johanson
<latexer at gentoo.org>
-------------- next part --------------
Index: Core/src/MonoDevelop.Base/Services/ParserService/DefaultParserService.cs
===================================================================
--- Core/src/MonoDevelop.Base/Services/ParserService/DefaultParserService.cs	(revision 2671)
+++ Core/src/MonoDevelop.Base/Services/ParserService/DefaultParserService.cs	(working copy)
@@ -255,8 +255,6 @@
 			IProjectService projectService = Runtime.ProjectService;
 			projectService.CombineOpened += new CombineEventHandler(OnCombineOpened);
 			projectService.CombineClosed += new CombineEventHandler(OnCombineClosed);
-			projectService.ReferenceAddedToProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
-			projectService.ReferenceRemovedFromProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
 		}
 		
 		internal IProgressMonitor GetParseProgressMonitor ()
@@ -367,6 +365,8 @@
 					GetDatabase (re.Uri);
 
 				project.NameChanged += new CombineEntryRenamedEventHandler (OnProjectRenamed);
+				project.ReferenceAddedToProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
+				project.ReferenceRemovedFromProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
 			}
 		}
 		
@@ -389,6 +389,8 @@
 			string uri = "Project:" + project.Name;
 			UnloadDatabase (uri);
 			project.NameChanged -= new CombineEntryRenamedEventHandler (OnProjectRenamed);
+			project.ReferenceAddedToProject -= new ProjectReferenceEventHandler (OnProjectReferencesChanged);
+			project.ReferenceRemovedFromProject -= new ProjectReferenceEventHandler (OnProjectReferencesChanged);
 		}
 		
 		void CleanUnusedDatabases ()
Index: Core/src/MonoDevelop.Base/Gui/Completion/ICompletionWidget.cs
===================================================================
--- Core/src/MonoDevelop.Base/Gui/Completion/ICompletionWidget.cs	(revision 0)
+++ Core/src/MonoDevelop.Base/Gui/Completion/ICompletionWidget.cs	(revision 0)
@@ -0,0 +1,27 @@
+
+using System;
+using MonoDevelop.Internal.Project;
+using Gtk;
+
+namespace MonoDevelop.Gui.Completion
+{
+
+	public interface ICompletionWidget
+	{
+		int X { get; }
+		int Y { get; }
+		int TextHeight { get; }
+
+		string Text { get; }
+
+		string CompletionText { get; }
+
+		void SetCompletionText (string partial_word, string complete_word);
+
+		int TriggerOffset { get; }
+		int TriggerLine { get; }
+		int TriggerLineOffset { get; }
+
+		Gtk.Style GtkStyle { get; }
+	}
+}
Index: Core/src/MonoDevelop.Base/Makefile.am
===================================================================
--- Core/src/MonoDevelop.Base/Makefile.am	(revision 2671)
+++ Core/src/MonoDevelop.Base/Makefile.am	(working copy)
@@ -87,6 +87,7 @@
 Gui/Components/SdMenuCheckBox.cs \
 Gui/Components/SdMenuCommand.cs \
 Gui/Components/SdToolbarCommand.cs \
+Gui/Completion/ICompletionWidget.cs \
 Gui/WorkbenchWindowCollection.cs \
 Gui/WorkbenchSingleton.cs \
 Gui/IMementoCapable.cs \
Index: Core/src/AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs	(working copy)
@@ -10,6 +10,7 @@
 using MonoDevelop.Core.AddIns;
 using MonoDevelop.Internal.Templates;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 using MonoDevelop.Core.Services;
 using MonoDevelop.SourceEditor.CodeCompletion;
 using MonoDevelop.SourceEditor.InsightWindow;
@@ -17,6 +18,7 @@
 using MonoDevelop.EditorBindings.FormattingStrategy;
 using MonoDevelop.Gui.Utils;
 using MonoDevelop.Gui;
+using MonoDevelop.Gui.Completion;
 using MonoDevelop.Services;
 using MonoDevelop.Commands;
 using MonoDevelop.DefaultEditor;
@@ -25,7 +27,7 @@
 
 namespace MonoDevelop.SourceEditor.Gui
 {
-	public class SourceEditorView : SourceView, IFormattableDocument
+	public class SourceEditorView : SourceView, IFormattableDocument, ICompletionWidget
 	{	
 		public readonly SourceEditor ParentEditor;
 		internal IFormattingStrategy fmtr;
@@ -194,8 +196,9 @@
 				return;
 			triggerIter.ForwardChar ();
 			
-//			CompletionWindow.ShowWindow (triggerChar, triggerIter, true, new CodeCompletionDataProvider (true), this);
-			CompletionListWindow.ShowWindow (triggerChar, triggerIter, new CodeCompletionDataProvider (true), this);
+			prepareCompletionDetails(triggerIter);
+			CompletionListWindow.ShowWindow (triggerChar, new CodeCompletionDataProvider (true), this, this.ParentEditor.DisplayBinding.Project, this.ParentEditor.DisplayBinding.ContentName);
+			//CompletionListWindow.ShowWindow (triggerChar, triggerIter, new CodeCompletionDataProvider (true), this, this.ParentEditor.DisplayBinding.Project, this.ParentEditor.DisplayBinding.ContentName);
 		}
 
 		bool MonodocResolver ()
@@ -227,7 +230,7 @@
 			IParserService parser = (IParserService)ServiceManager.GetService (typeof (IParserService));
 			string fileName = ParentEditor.DisplayBinding.ContentName;
 			IExpressionFinder expressionFinder = parser.GetExpressionFinder(fileName);
-			string expression    = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(this, insertIter.Offset) : expressionFinder.FindExpression(buf.GetText(buf.StartIter, insertIter, true), insertIter.Offset - 2);
+			string expression    = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(this.Buffer.Text, insertIter.Offset) : expressionFinder.FindExpression(buf.GetText(buf.StartIter, insertIter, true), insertIter.Offset - 2);
 			if (expression == null) return false;
 			Console.WriteLine ("Expression: {" + expression + "}");
 			string type = parser.MonodocResolver (ParentEditor.DisplayBinding.Project, expression, insertIter.Line + 1, insertIter.LineOffset + 1, fileName, buf.Text);
@@ -375,8 +378,9 @@
 			case '.':
 				bool retval = base.OnKeyPressEvent (evnt);
 				if (EnableCodeCompletion && PeekCharIsWhitespace ()) {
-//					CompletionWindow.ShowWindow ((char)key, buf.GetIterAtMark (buf.InsertMark), false, new CodeCompletionDataProvider (), this);
-					CompletionListWindow.ShowWindow ((char)key, buf.GetIterAtMark (buf.InsertMark), new CodeCompletionDataProvider (), this);
+					prepareCompletionDetails(buf.GetIterAtMark (buf.InsertMark));
+					CompletionListWindow.ShowWindow ((char)key, new CodeCompletionDataProvider (), this, this.ParentEditor.DisplayBinding.Project, this.ParentEditor.DisplayBinding.ContentName);
+					//CompletionListWindow.ShowWindow ((char)key, buf.GetIterAtMark (buf.InsertMark), new CodeCompletionDataProvider (), this, this.ParentEditor.DisplayBinding.Project, this.ParentEditor.DisplayBinding.ContentName);
 				}
 				return retval;
 				/*case '(':
@@ -582,6 +586,20 @@
 			end.ForwardToLineEnd ();
 			Buffer.MoveMark ("selection_bound", end);
 		}
+
+		void prepareCompletionDetails(TextIter iter)
+		{
+			Gdk.Rectangle rect = GetIterLocation (Buffer.GetIterAtMark (Buffer.InsertMark));
+			int wx, wy;
+			BufferToWindowCoords (Gtk.TextWindowType.Widget, rect.X, rect.Y + rect.Height, out wx, out wy);
+			int tx, ty;
+			GdkWindow.GetOrigin (out tx, out ty);
+
+			this.completionX = tx + wx;
+			this.completionY = ty + wy;
+			this.textHeight = rect.Height;
+			this.triggerMark = buf.CreateMark (null, iter, true);
+		}
 #endregion
 
 #region IFormattableDocument
@@ -649,7 +667,7 @@
 		int IFormattableDocument.GetClosingBraceForLine (int ln, out int openingLine)
 		{
 			int offset = MonoDevelop.SourceEditor.CodeCompletion.TextUtilities.SearchBracketBackward
-				(this, Buffer.GetIterAtLine (ln).Offset - 1, '{', '}');
+				(this.Buffer.Text, Buffer.GetIterAtLine (ln).Offset - 1, '{', '}');
 			
 			openingLine = offset == -1 ? -1 : Buffer.GetIterAtOffset (offset).Line;
 			return offset;
@@ -661,7 +679,95 @@
 			offset = begin.Offset;
 			len = begin.CharsInLine;
 		}
+#endregion
 
+#region ICompletionWidget
+
+		private int completionX;
+		int ICompletionWidget.X
+		{
+			get
+			{
+				return completionX;
+			}
+		}
+
+		private int completionY;
+		int ICompletionWidget.Y
+		{
+			get
+			{
+				return completionY;
+			}
+		}
+
+		private int textHeight;
+		int ICompletionWidget.TextHeight
+		{
+			get
+			{
+				return textHeight;
+			}
+		}
+
+		string ICompletionWidget.CompletionText
+		{
+			get
+			{
+				return Buffer.GetText (Buffer.GetIterAtMark (triggerMark), Buffer.GetIterAtMark (Buffer.InsertMark), false);
+			}
+		}
+
+		void ICompletionWidget.SetCompletionText (string partial_word, string complete_word)
+		{
+			TextIter offsetIter = buf.GetIterAtMark(triggerMark);
+                        TextIter endIter = buf.GetIterAtOffset (offsetIter.Offset + partial_word.Length);
+                        buf.MoveMark (buf.InsertMark, offsetIter);
+                        buf.Delete (ref offsetIter, ref endIter);
+                        buf.InsertAtCursor (complete_word);
+		}
+		
+		string ICompletionWidget.Text
+		{
+			get
+			{
+				return buf.Text;
+			}
+		}
+
+		private TextMark triggerMark;
+		int ICompletionWidget.TriggerOffset
+		{
+			get
+			{
+				return buf.GetIterAtMark (triggerMark).Offset;
+			}
+		}
+
+		int ICompletionWidget.TriggerLine
+		{
+			get
+			{
+				return buf.GetIterAtMark (triggerMark).Line;
+			}
+		}
+
+		int ICompletionWidget.TriggerLineOffset
+		{
+			get
+			{
+				return buf.GetIterAtMark (triggerMark).LineOffset;
+			}
+		}
+
+		Gtk.Style ICompletionWidget.GtkStyle
+		{
+			get
+			{
+				return Style.Copy();
+			}
+		}
+
 		bool PeekCharIsWhitespace ()
 		{
 			TextIter start = buf.GetIterAtMark (buf.InsertMark);
Index: Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs	(working copy)
@@ -58,7 +58,7 @@
 			initialOffset = initialIter.Offset;
 			string text = textArea.Buffer.Text;
 			
-			string word         = TextUtilities.GetExpressionBeforeOffset(textArea, initialOffset);
+			string word         = TextUtilities.GetExpressionBeforeOffset(textArea.Buffer.Text, initialOffset);
 			string methodObject = word;
 			string methodName   =  null;
 			int idx = methodObject.LastIndexOf('.');
Index: Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs	(working copy)
@@ -54,7 +54,7 @@
 			Gtk.TextIter initialIter = textArea.Buffer.GetIterAtMark (textArea.Buffer.InsertMark);
 			initialOffset = initialIter.Offset;
 			
-			string word         = TextUtilities.GetExpressionBeforeOffset(textArea, initialOffset);
+			string word         = TextUtilities.GetExpressionBeforeOffset(textArea.Buffer.Text, initialOffset);
 			string methodObject = word;
 			
 			// the parser works with 1 based coordinates
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionData.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionData.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionData.cs	(working copy)
@@ -33,7 +33,7 @@
 			get;
 		}
 		
-		void InsertAction(SourceEditorView control);
+		void InsertAction(Gtk.TextView control);
 	}
 	
 	public interface ICompletionDataWithMarkup : ICompletionData
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionListWindow.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionListWindow.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionListWindow.cs	(working copy)
@@ -5,6 +5,7 @@
 using MonoDevelop.SourceEditor.Gui;
 using MonoDevelop.Internal.Project;
 using MonoDevelop.Gui;
+using MonoDevelop.Gui.Completion;
 
 namespace MonoDevelop.SourceEditor.CodeCompletion
 {
@@ -12,8 +13,7 @@
 	{
 		string fileName;
 		Project project;
-		SourceEditorView control;
-		TextMark triggeringMark;
+		ICompletionWidget completionWidget;
 		ICompletionData[] completionData;
 		DeclarationViewWindow declarationviewwindow = new DeclarationViewWindow ();
 		static DataComparer dataComparer = new DataComparer ();
@@ -40,14 +40,13 @@
 			SizeAllocated += new SizeAllocatedHandler (ListSizeChanged);
 		}
 		
-		public static void ShowWindow (char firstChar, TextIter trigIter, ICompletionDataProvider provider, SourceEditorView ctrl)
+		public static void ShowWindow (char firstChar, ICompletionDataProvider provider, ICompletionWidget completionWidget, Project project, string fileName)
 		{
-			if (!wnd.ShowListWindow (firstChar, trigIter, provider,  ctrl))
+			if (!wnd.ShowListWindow (firstChar, provider,  completionWidget, project, fileName))
 				return;
 			
 			// makes control-space in midle of words to work
-			TextBuffer buf = wnd.control.Buffer; 
-			string text = buf.GetText (trigIter, buf.GetIterAtMark (buf.InsertMark), false);
+			string text = wnd.completionWidget.CompletionText;
 			if (text.Length == 0)
 				return;
 			
@@ -63,32 +62,25 @@
 			wnd.PartialWord = wnd.CompleteWord;		
 		}
 		
-		bool ShowListWindow (char firstChar, TextIter trigIter, ICompletionDataProvider provider, SourceEditorView ctrl)
+		bool ShowListWindow (char firstChar, ICompletionDataProvider provider, ICompletionWidget completionWidget, Project project, string fileName)
 		{
-			this.control = ctrl;
-			this.fileName = ctrl.ParentEditor.DisplayBinding.ContentName;
-			this.project = ctrl.ParentEditor.DisplayBinding.Project;
-			triggeringMark = control.Buffer.CreateMark (null, trigIter, true);
+			this.completionWidget = completionWidget;
+			this.fileName = fileName;
+			this.project = project;
 			
-			completionData = provider.GenerateCompletionData (project, fileName, ctrl, firstChar, triggeringMark);
+			completionData = provider.GenerateCompletionData (project, fileName, completionWidget.Text, firstChar, completionWidget.TriggerOffset, completionWidget.TriggerLine, completionWidget.TriggerLineOffset);
+
 			if (completionData == null || completionData.Length == 0) return false;
 			
-			this.Style = ctrl.Style.Copy();
+			this.Style = completionWidget.GtkStyle;
 			
 			Array.Sort (completionData, dataComparer);
 			
 			DataProvider = this;
-			Gdk.Rectangle rect = control.GetIterLocation (control.Buffer.GetIterAtMark (triggeringMark));
 
-			int wx, wy;
-			control.BufferToWindowCoords (Gtk.TextWindowType.Widget, rect.X /*+ rect.Width*/, rect.Y + rect.Height, out wx, out wy);
+			int x = completionWidget.X;
+			int y = completionWidget.Y;
 			
-			int tx, ty;
-			control.GdkWindow.GetOrigin (out tx, out ty);
-			
-			int x = tx + wx;
-			int y = ty + wy;
-			
 			int w, h;
 			GetSize (out w, out h);
 			
@@ -96,8 +88,10 @@
 				x = Screen.Width - w;
 			
 			if ((y + h) > Screen.Height)
-				y = y - rect.Height - h;
-							
+			{
+				y = y - completionWidget.TextHeight - h;
+			}
+
 			Move (x, y);
 			
 			Show ();
@@ -140,11 +134,7 @@
 		
 		void UpdateWord ()
 		{
-			TextIter offsetIter = wnd.control.Buffer.GetIterAtMark (wnd.triggeringMark);
-			TextIter endIter = wnd.control.Buffer.GetIterAtOffset (offsetIter.Offset + wnd.PartialWord.Length);
-			wnd.control.Buffer.MoveMark (wnd.control.Buffer.InsertMark, offsetIter);
-			wnd.control.Buffer.Delete (ref offsetIter, ref endIter);
-			wnd.control.Buffer.InsertAtCursor (wnd.CompleteWord);
+			completionWidget.SetCompletionText(wnd.PartialWord, wnd.CompleteWord);
 		}
 		
 		public new void Hide ()
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs	(working copy)
@@ -219,9 +219,9 @@
 			documentation = "";
 		}
 		
-		public void InsertAction (SourceEditorView control)
+		public void InsertAction (Gtk.TextView view)
 		{
-			control.Buffer.InsertAtCursor (completionString);
+			view.Buffer.InsertAtCursor (completionString);
 		}
 
 		public static string GetDocumentation (string doc)
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TextUtilities.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TextUtilities.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TextUtilities.cs	(working copy)
@@ -74,23 +74,20 @@
 		/// That method is used in code completion to determine the expression given
 		/// to the parser for type resolve.
 		/// </remarks>
-		public static string GetExpressionBeforeOffset(SourceEditorView textArea, int offset)
+		public static string GetExpressionBeforeOffset(string text, int offset)
 		{
-			// FIXME: we should actually use GtkTextIter's
-			string text = textArea.Buffer.Text;
 			int origOffset = offset;
 			
 			while (offset - 1 > 0) {
 				switch (text [offset - 1]) {
 					case '}':
 						goto done;
-//						offset = SearchBracketBackward(document, offset - 2, '{','}');
 //						break;
 					case ']':
-						offset = SearchBracketBackward(textArea, offset - 2, '[',']');
+						offset = SearchBracketBackward(text, offset - 2, '[',']');
 						break;
 					case ')':
-						offset = SearchBracketBackward(textArea, offset - 2, '(',')');
+						offset = SearchBracketBackward(text, offset - 2, '(',')');
 						break;
 					case '.':
 						--offset;
@@ -119,11 +116,9 @@
 							--start;
 						}
 						
-						//Console.WriteLine("{0} -- {1}", offset, start);
-						Gtk.TextIter startIter = textArea.Buffer.GetIterAtOffset (start);
-						Gtk.TextIter endIter = textArea.Buffer.GetIterAtOffset (offset);
-						string word = textArea.Buffer.GetText (startIter, endIter, false).Trim();
-						//Console.WriteLine("word >{0}<", word);
+						Console.WriteLine("{0} -- {1}", offset, start);
+						string word = text.Substring(start, offset - start);
+						Console.WriteLine("word >{0}<", word);
 						switch (word) {
 							case "ref":
 							case "out":
@@ -142,11 +137,8 @@
 				}
 			}
 			done:
-//			Console.WriteLine("ofs : {0} cart:{1}", offset, document.Caret.Offset);
-//			Console.WriteLine("return:" + document.GetText(offset, document.Caret.Offset - offset).Trim());
-			Gtk.TextIter start_Iter = textArea.Buffer.GetIterAtOffset (origOffset);
-			Gtk.TextIter offset_Iter = textArea.Buffer.GetIterAtOffset (offset);
-			return textArea.Buffer.GetText (start_Iter, offset_Iter, false ).Trim();
+//			Console.WriteLine("offset : {0} origOffset: {1}", offset, origOffset);
+			return offset - origOffset > 0 ? text.Substring(origOffset, offset - origOffset).Trim() : "";
 		}
 		
 /*		
@@ -244,10 +236,8 @@
 			return document.GetText(line.Offset, line.Length);
 		}
 */
-		static bool ScanLineComment(SourceEditorView document, int offset)
+		static bool ScanLineComment(string text, int offset)
 		{
-			// FIXME: use iters
-			string text = document.Buffer.Text;
 			while (offset > 0 && offset < text.Length) {
 				char ch = text [offset];
 				switch (ch) {
@@ -265,10 +255,9 @@
 			return false;
 		}
 		
-		public static int SearchBracketBackward(SourceEditorView document, int offset, char openBracket, char closingBracket)
+		public static int SearchBracketBackward(string text, int offset, char openBracket, char closingBracket)
 		{
 			// FIXME: use iters
-			string text = document.Buffer.Text;			
 			int brackets = -1;		
 			bool inString = false;
 			bool inChar   = false;	
@@ -290,22 +279,22 @@
 						}
 						break;
 					case '"':
-						if (!inChar && !blockComment && !ScanLineComment(document, offset)) {
+						if (!inChar && !blockComment && !ScanLineComment(text, offset)) {
 							inString = !inString;
 						}
 						break;
 					case '\'':
-						if (!inString && !blockComment && !ScanLineComment(document, offset)) {
+						if (!inString && !blockComment && !ScanLineComment(text, offset)) {
 							inChar = !inChar;
 						}
 						break;
 					default :
 						if (ch == closingBracket) {
-							if (!(inString || inChar || blockComment) && !ScanLineComment(document, offset)) {
+							if (!(inString || inChar || blockComment) && !ScanLineComment(text, offset)) {
 								--brackets;
 							}
 						} else if (ch == openBracket) {
-							if (!(inString || inChar || blockComment) && !ScanLineComment(document, offset)) {
+							if (!(inString || inChar || blockComment) && !ScanLineComment(text, offset)) {
 								++brackets;
 								if (brackets == 0) {
 									return offset;
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs	(working copy)
@@ -334,7 +334,9 @@
 		
 		void FillList (bool firstTime, char ch)
 		{
-			ICompletionData[] completionData = completionDataProvider.GenerateCompletionData(project, fileName, control, ch, triggeringMark);
+			TextIter offsetIter = control.Buffer.GetIterAtMark (triggeringMark);
+			ICompletionData[] completionData = completionDataProvider.GenerateCompletionData(project, fileName, control.Buffer.Text, ch, offsetIter.Offset, offsetIter.Line, offsetIter.LineOffset);
+
 			if (completionData == null || completionData.Length == 0) {
 				return;
 			}
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs	(working copy)
@@ -63,7 +63,7 @@
 			return row >= region.BeginLine && (row <= region.EndLine || region.EndLine == -1);
 		}
 		
-		public ICompletionData[] GenerateCompletionData (Project project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData (Project project, string fileName, string text, char charTyped, int triggerOffset, int caret_line, int caret_column)
 		{
 			/*caretLineNumber = textArea.Caret.Line;
 			caretColumn     = textArea.Caret.Column;
@@ -114,7 +114,7 @@
 				}
 			}
 			
-			public void InsertAction (SourceEditorView control)
+			public void InsertAction (Gtk.TextView view)
 			{
 				//((SharpDevelopTextAreaControl)control).ActiveTextAreaControl.TextArea.InsertString(text);
 			}
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs	(working copy)
@@ -17,6 +17,6 @@
 
 namespace MonoDevelop.SourceEditor.CodeCompletion {
 	public interface ICompletionDataProvider {
-		ICompletionData[] GenerateCompletionData(Project project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark mark);
+		ICompletionData[] GenerateCompletionData(Project project, string fileName, string text, char charTyped, int triggerOffset, int caret_line, int caret_column);
 	}
 }
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs	(working copy)
@@ -55,29 +55,26 @@
 		
 		ArrayList completionData = null;
 		
-		public ICompletionData[] GenerateCompletionData(Project project, string fileName, SourceEditorView textArea, char charTyped, TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData(Project project, string fileName, string text, char charTyped, int triggerOffset, int caret_line, int caret_column)
 		{
 			completionData = new ArrayList();
 			this.fileName = fileName;
 			
-			Gtk.TextIter insertIter = textArea.Buffer.GetIterAtMark (triggerMark);
-			
 			// the parser works with 1 based coordinates
-			
-			caretLineNumber      = insertIter.Line + 1;
-			caretColumn          = insertIter.LineOffset + 1;
+			caretLineNumber      = caret_line + 1;
+			caretColumn          = caret_column + 1;
 			//string expression    = TextUtilities.GetExpressionBeforeOffset (textArea, insertIter.Offset);
 			ResolveResult results;
 			
 			IParserService parserService = (IParserService)MonoDevelop.Core.Services.ServiceManager.GetService(typeof(IParserService));
 			IExpressionFinder expressionFinder = parserService.GetExpressionFinder(fileName);
-			string expression    = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(textArea, insertIter.Offset) : expressionFinder.FindExpression(textArea.Buffer.GetText(textArea.Buffer.StartIter, insertIter, true), insertIter.Offset - 2);
+			string expression    = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(text, triggerOffset) : expressionFinder.FindExpression(text.Substring(0, triggerOffset), triggerOffset - 2);
 			if (expression == null) return null;
 			Console.WriteLine ("Expr: |{0}|", expression);
 			//FIXME: This chartyped check is a fucking *HACK*
 			if (expression == "is" || expression == "as") {
-				string expr = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset (textArea, insertIter.Offset - 3) : expressionFinder.FindExpression (textArea.Buffer.GetText (textArea.Buffer.StartIter, insertIter, true), insertIter.Offset - 5);
-				AddResolveResults (parserService.IsAsResolve (project, expr, caretLineNumber, caretColumn, fileName, textArea.Buffer.Text));
+				string expr = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset (text, triggerOffset - 3) : expressionFinder.FindExpression (text.Substring(0, triggerOffset), triggerOffset - 5);
+				AddResolveResults (parserService.IsAsResolve (project, expr, caretLineNumber, caretColumn, fileName, text));
 				return (ICompletionData[])completionData.ToArray (typeof (ICompletionData));
 			}
 			if (ctrlspace && charTyped != '.') {
@@ -92,7 +89,7 @@
 			} else {
 				//FIXME: I added the null check, #D doesnt need it, why do we?
 				if (fileName != null) {
-					results = parserService.Resolve(project, expression, caretLineNumber, caretColumn, fileName, textArea.Buffer.Text);
+					results = parserService.Resolve(project, expression, caretLineNumber, caretColumn, fileName, text);
 					AddResolveResults(results);
 				}
 			}
Index: Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs
===================================================================
--- Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs	(revision 2671)
+++ Core/src/AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs	(working copy)
@@ -27,7 +27,7 @@
 			}
 		}
 		
-		public ICompletionData[] GenerateCompletionData(Project project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData(Project project, string fileName, string text, char charTyped, int triggerOffset, int caret_line, int caret_column)
 		{
 			CodeTemplateGroup templateGroup = CodeTemplateLoader.GetTemplateGroupPerFilename(fileName);
 			if (templateGroup == null) {
@@ -74,7 +74,7 @@
 				}
 			}
 			
-			public void InsertAction(SourceEditorView control)
+			public void InsertAction(Gtk.TextView control)
 			{
 				//((SharpDevelopTextAreaControl)control).InsertTemplate(template);
 			}
-------------- next part --------------
Index: Extras/BooBinding/Gui/IShellModel.boo
===================================================================
--- Extras/BooBinding/Gui/IShellModel.boo	(revision 2671)
+++ Extras/BooBinding/Gui/IShellModel.boo	(working copy)
@@ -20,6 +20,7 @@
 namespace BooBinding.Gui
 
 import System
+import System.Collections
 import BooBinding.Properties
 
 interface IShellModel:
@@ -45,9 +46,16 @@
 		pass
 
 	Properties as ShellProperties:
-		get:
-			pass
+		get
 
+	LanguageName as string:
+		get
+
 	MimeType as string:
-		get:
-			pass
+		get
+	
+	MimeTypeExtension as string:
+		get
+	
+	References as IList:
+		get
Index: Extras/BooBinding/Gui/ShellTextView.boo
===================================================================
--- Extras/BooBinding/Gui/ShellTextView.boo	(revision 2671)
+++ Extras/BooBinding/Gui/ShellTextView.boo	(working copy)
@@ -31,11 +31,13 @@
 import GtkSourceView
 
 import MonoDevelop.Gui.Widgets
+import MonoDevelop.Gui.Completion
 import MonoDevelop.Core.Services
 import MonoDevelop.Services
 import MonoDevelop.Core.Properties
 import MonoDevelop.Internal.Project
 
+import MonoDevelop.SourceEditor.CodeCompletion
 
 /*
  * TODO
@@ -44,9 +46,10 @@
  * 2) Don't record lines with errors in the _scriptLines buffer
  */
 
-class ShellTextView (SourceView):
+class ShellTextView (SourceView, ICompletionWidget):
 	private static _promptRegular = ">>> "
 	private static _promptMultiline = "... "
+	private static _fakeFileName as string
 	
 	[Getter(Model)]
 	model as IShellModel
@@ -68,9 +71,14 @@
 	private _proj as Project
 
 	private _assembliesLoaded as bool
+
+	private _fakeProject as DotNetProject
+	private _parserService as DefaultParserService
+	private _fileInfo as FileStream
 	
 	def constructor(model as IShellModel):
 		service = cast(SourceViewService,ServiceManager.GetService(typeof(SourceViewService)))
+		_parserService = cast(IParserService, ServiceManager.GetService (typeof (DefaultParserService)))
 		buf = SourceBuffer(service.GetLanguageFromMimeType(model.MimeType))
 
 		// This freaks out booc for some reason.
@@ -82,6 +90,14 @@
 		self.WrapMode = Gtk.WrapMode.Word
 		self.ModifyFont(Model.Properties.Font)
 
+		_fakeFileName = "/tmp/shell-dummy-file.${Model.MimeTypeExtension}"
+		_fileInfo  = System.IO.File.Create (_fakeFileName)
+
+		# FIXME: Put the project file somewhere other than /tmp
+		_fakeProject = DotNetProject(Model.LanguageName, Name: "___ShellProject", FileName: "/tmp/shell-project.mdp")
+
+		_parserService.LoadProjectDatabase(_fakeProject)
+
 		Model.Properties.InternalProperties.PropertyChanged += OnPropertyChanged
 		Model.RegisterOutputHandler (HandleOutput)
 
@@ -155,6 +171,10 @@
 			for line as string in output:
 				processOutput (line )
 		prompt (true)
+		for assembly in Model.References:
+			_fakeProject.AddReference(assembly)
+
+		GLib.Idle.Add( { _parserService.ParseFile (_fakeFileName, _scriptLines) } )
 		return false
 			
 	override def Dispose():
@@ -208,6 +228,9 @@
 		_reset.Show()
 	
 	override def OnKeyPressEvent (ev as Gdk.EventKey):
+		if CompletionListWindow.ProcessKeyEvent (ev):
+			return true
+		
 		// Short circuit to avoid getting moved back to the input line
 		// when paging up and down in the shell output
 		if ev.Key in Gdk.Key.Page_Up, Gdk.Key.Page_Down:
@@ -219,6 +242,9 @@
 			Buffer.MoveMark (Buffer.SelectionBound, InputLineEnd)
 			Buffer.MoveMark (Buffer.InsertMark, InputLineEnd)
 		
+		if (ev.State == Gdk.ModifierType.ControlMask) and ev.Key == Gdk.Key.space:
+			TriggerCodeCompletion ()
+
 		if ev.Key == Gdk.Key.Return:
 			if _inBlock:
 				if InputLine == "":
@@ -237,7 +263,7 @@
 			else:
 				// Special case for start of new code block
 				if InputLine.Trim()[-1:] == ":":
-					_inBlock = true;
+					_inBlock = true
 					_blockText = InputLine
 					prompt (true, true)
 					if _auto_indent:
@@ -268,7 +294,7 @@
 		elif ev.Key == Gdk.Key.Up:
 			if (not _inBlock) and _commandHistoryPast.Count > 0:
 				if _commandHistoryFuture.Count == 0:
-					_commandHistoryFuture.Push(InputLine);
+					_commandHistoryFuture.Push(InputLine)
 				else:
 					if _commandHistoryPast.Count == 1:
 						return true
@@ -297,6 +323,12 @@
 				Buffer.MoveMark (Buffer.SelectionBound, InputLineBegin)
 			return true
 
+		elif ev.Key == Gdk.Key.period:
+			ret = super.OnKeyPressEvent(ev)
+			prepareCompletionDetails (Buffer.GetIterAtMark (Buffer.InsertMark))
+			CompletionListWindow.ShowWindow(char('.'), CodeCompletionDataProvider (true), self, _fakeProject, _fakeFileName)
+			return ret
+
 		// Short circuit to avoid getting moved back to the input line
 		// when paging up and down in the shell output
 		elif ev.Key in Gdk.Key.Page_Up, Gdk.Key.Page_Down:
@@ -304,8 +336,41 @@
 		
 		return super (ev)
 	
+	protected override def OnFocusOutEvent (e as EventFocus):
+		CompletionListWindow.HideWindow ()
+		return super.OnFocusOutEvent(e)
+	
 	#endregion
 
+	private def TriggerCodeCompletion():
+		iter = Cursor
+		triggerChar = char('\0')
+		triggerIter = TextIter.Zero
+		if (iter.Char != null and  iter.Char.Length > 0):
+			if iter.Char[0] in (char(' '), char('\t'), char('.'), char('('), char('[')):
+				triggerIter = iter
+				triggerChar = iter.Char[0]
+
+		while iter.LineOffset > 0 and triggerIter.Equals (TextIter.Zero):
+			if (iter.Char == null or iter.Char.Length == 0):
+				iter.BackwardChar ()
+				continue
+
+			if iter.Char[0] in (char(' '), char('\t'), char('.'), char('('), char('[')):
+				triggerIter = iter
+				triggerChar = iter.Char[0]
+				break
+
+			iter.BackwardChar ()
+		
+		if (triggerIter.Equals (TextIter.Zero)):
+			return
+
+		triggerIter.ForwardChar ()
+		
+		prepareCompletionDetails (triggerIter)
+		CompletionListWindow.ShowWindow (triggerChar, CodeCompletionDataProvider (true), self, _fakeProject, _fakeFileName)
+
 	// Mark to find the beginning of our next input line
 	private _endOfLastProcessing as TextMark
 
@@ -403,3 +468,63 @@
 		return
 
 	#endregion
+
+	private def prepareCompletionDetails (triggerIter as TextIter):
+		rect = GetIterLocation (Buffer.GetIterAtMark (Buffer.InsertMark))
+
+		wx as int
+		wy as int
+		BufferToWindowCoords (Gtk.TextWindowType.Widget, rect.X, rect.Y + rect.Height, wx, wy)
+
+		tx as int
+		ty as int
+		GdkWindow.GetOrigin (tx, ty)
+
+		self.completionX = tx + wx
+		self.completionY = ty + wy
+		self.textHeight = rect.Height
+		self.triggerMark = Buffer.CreateMark (null, triggerIter, true)
+
+	#region ICompletionWidget
+
+	[Getter(ICompletionWidget.X)]
+	private completionX
+
+	[Getter(ICompletionWidget.Y)]
+	private completionY
+	
+	[Getter(ICompletionWidget.TextHeight)]
+	private textHeight as int
+	
+	ICompletionWidget.Text:
+		get:
+			return Buffer.Text
+	
+	ICompletionWidget.CompletionText:
+		get:
+			return Buffer.GetText (Buffer.GetIterAtMark (triggerMark), Buffer.GetIterAtMark (Buffer.InsertMark), false)
+	
+	def ICompletionWidget.SetCompletionText (partial_word as string, complete_word as string):
+		offsetIter = Buffer.GetIterAtMark(triggerMark)
+		endIter = Buffer.GetIterAtOffset (offsetIter.Offset + partial_word.Length)
+		Buffer.MoveMark (Buffer.InsertMark, offsetIter)
+		Buffer.Delete (offsetIter, endIter)
+		Buffer.InsertAtCursor (complete_word)
+	
+	private triggerMark as TextMark
+	ICompletionWidget.TriggerOffset:
+		get:
+			return Buffer.GetIterAtMark (triggerMark).Offset
+
+	ICompletionWidget.TriggerLine:
+		get:
+			return Buffer.GetIterAtMark (triggerMark).Line
+
+	ICompletionWidget.TriggerLineOffset:
+		get:
+			return Buffer.GetIterAtMark (triggerMark).LineOffset
+	
+	ICompletionWidget.GtkStyle:
+		get:
+			return self.Style.Copy();
+	#endregion
Index: Extras/BooBinding/Gui/BooShellModel.boo
===================================================================
--- Extras/BooBinding/Gui/BooShellModel.boo	(revision 2671)
+++ Extras/BooBinding/Gui/BooShellModel.boo	(working copy)
@@ -49,24 +49,32 @@
 		get:
 			return "text/x-boo"
 
+	LanguageName as string:
+		get:
+			return "Boo"
+
+	MimeTypeExtension as string:
+		get:
+			return "boo"
+	
 	Properties as ShellProperties:
 		get:
 			return _props
 	
-	def constructor ():
-		pass
-
-	def constructor (program_path as string, socket_path as string):
-		GetRemoteShellObject ()
+	References as IList:
+		get:	
+			return _booShell.References
+	
+	def constructor():
+		getRemoteShellObject()
 		_booShell.Run ()
 
-	def GetRemoteShellObject ():
+	private def getRemoteShellObject ():
 		_procService as ProcessService = ServiceManager.GetService (typeof (ProcessService))
 		_booShell = _procService.CreateExternalProcessObject ("../AddIns/BackendBindings/BooShell.dll", "BooBinding.BooShell.BooShell", false)
 		if _booShell is null:
 			raise Exception ("Unable to instantiate remote BooShell object")
-
-			
+	
 	def Reset () as bool:
 		_booShell.Reset()
 		return true
Index: Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo
===================================================================
--- Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo	(revision 2671)
+++ Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo	(working copy)
@@ -105,9 +105,7 @@
 		labelCompileTarget.Markup = String.Format ("{0} :", GettextCatalog.GetString ("Output Assembly"))
 		
 
-		typeArray = array(System.Type, 1)
-		typeArray[0] = typeof(string)
-		store = ListStore (typeArray)
+		store = ListStore ((typeof(string),))
 
 		stringArray = array(System.String, 1)
 		stringArray[0] = GettextCatalog.GetString ("Executable")
Index: Extras/BooBinding/Properties/ShellProperties.boo
===================================================================
--- Extras/BooBinding/Properties/ShellProperties.boo	(revision 2671)
+++ Extras/BooBinding/Properties/ShellProperties.boo	(working copy)
@@ -17,7 +17,7 @@
 	private propertyService = cast (PropertyService, ServiceManager.GetService (typeof(PropertyService)))
 	private properties = cast (IProperties, propertyService.GetProperty (PropertyName, DefaultProperties()))
 
-	public virtual PropertyName as string:
+	public abstract PropertyName as string:
 		get:
 			pass
 
Index: Extras/BooBinding/Parser/BooParser.boo
===================================================================
--- Extras/BooBinding/Parser/BooParser.boo	(revision 2671)
+++ Extras/BooBinding/Parser/BooParser.boo	(working copy)
@@ -67,8 +67,8 @@
 	def Parse(fileName as string, fileContent as string) as ICompilationUnitBase:
 		//print "Parse ${fileName} with content"
 		
-		cr = '\r'[0]
-		ln = '\n'[0]
+		cr = char('\r')
+		ln = char('\n')
 		linecount = 1
 		for c as Char in fileContent:
 			linecount += 1 if c == ln
@@ -87,15 +87,20 @@
 		compiler = BooCompiler()
 		compiler.Parameters.Input.Add(StringInput(fileName, fileContent))
 		project as Project
-		for entry as Project in MonoDevelop.Services.Runtime.ProjectService.CurrentOpenCombine.GetAllProjects():
-			if entry.IsFileInProject(fileName):
-				project = entry
-				
-		return Parse(fileName, lineLength, compiler, project)
+		if MonoDevelop.Services.Runtime.ProjectService.CurrentOpenCombine is not null:
+			for entry as Project in MonoDevelop.Services.Runtime.ProjectService.CurrentOpenCombine.GetAllProjects():
+				if entry.IsFileInProject(fileName):
+					project = entry
+		
+		if project is not null and project.ProjectReferences is not null:
+			for projectRef as ProjectReference in project.ProjectReferences:
+				compiler.Parameters.References.Add(System.Reflection.Assembly.LoadFile(projectRef.GetReferencedFileName()))
+		
+		return Parse(fileName, lineLength, compiler)
 	
-	private def Parse(fileName as string, lineLength as (int), compiler as BooCompiler, project as Project):
+	private def Parse(fileName as string, lineLength as (int), compiler as BooCompiler):
 		compiler.Parameters.OutputWriter = StringWriter()
-		compiler.Parameters.TraceSwitch.Level = TraceLevel.Warning;
+		compiler.Parameters.TraceSwitch.Level = TraceLevel.Warning
 		
 		compilePipe = Compile()
 		parsingStep as Boo.Lang.Parser.BooParsingStep = compilePipe[0]
@@ -117,8 +122,6 @@
 		
 		compilePipe.BreakOnErrors = false
 		compiler.Parameters.Pipeline = compilePipe
-		for projectRef as ProjectReference in project.ProjectReferences:
-			compiler.Parameters.References.Add(System.Reflection.Assembly.LoadFile(projectRef.GetReferencedFileName()))
 		
 		try:
 			compiler.Run()
Index: Extras/BooBinding/BooShellPadContent.boo
===================================================================
--- Extras/BooBinding/BooShellPadContent.boo	(revision 2671)
+++ Extras/BooBinding/BooShellPadContent.boo	(working copy)
@@ -35,23 +35,23 @@
 
 	override Control:
 		get:
+			if _scroller is null:
+				CreateBooShell()
 			return _scroller
 	
 	def constructor():
 		super( "Boo Shell", "md-boo-binding-base" )
-		CreateBooShell()
 	
 	def CreateBooShell():
 		_scroller = Gtk.ScrolledWindow()
-		_user = System.Environment.GetEnvironmentVariable("USER")
-		_model = BooShellModel ("../AddIns/BackendBindings/BooShellServer.exe", "/tmp/md-booshell-${_user}")
+		_model = BooShellModel ()
 		_shellView = ShellTextView (_model)
 		_scroller.Add(_shellView)
 		_scroller.ShowAll()
 
 	override def RedrawContent():
-		OnTitleChanged(null);
-		OnIconChanged(null);
+		OnTitleChanged(null)
+		OnIconChanged(null)
 
 	override def Dispose():
 		_shellView.Dispose()
Index: Extras/BooBinding/BooShell/BooShell.boo
===================================================================
--- Extras/BooBinding/BooShell/BooShell.boo	(revision 2671)
+++ Extras/BooBinding/BooShell/BooShell.boo	(working copy)
@@ -52,6 +52,19 @@
 		EnqueueCommand (ShellCommand (ShellCommandType.Load, assemblyPath))
 		return true
 	
+	References as IList:
+		get:
+			list = []
+			Monitor.Enter (_interpreter)
+			for assembly as System.Reflection.Assembly in _interpreter.References.List:
+				try:
+					loc = assembly.Location
+					list.Add (loc)
+				except x:
+					continue
+			Monitor.Exit (_interpreter)
+			return list
+	
 	def GetOutput() as (string):
 		ret as (string)
 		try:
@@ -78,7 +91,7 @@
 		GLib.Idle.Add(ProcessCommands)
 		Application.Run()
 
-	def ProcessCommands() as bool:
+	private def ProcessCommands() as bool:
 		com as ShellCommand
 		try:
 			Monitor.Enter (_commandQueue)
@@ -89,6 +102,7 @@
 
 			com = _commandQueue.Dequeue()
 
+			Monitor.Enter(_interpreter)
 			if com.Type == ShellCommandType.Eval:
 				if com.Data is not null:
 					_interpreter.LoopEval(com.Data)
@@ -97,7 +111,9 @@
 			elif com.Type == ShellCommandType.Load:
 				if com.Data is not null:
 					_interpreter.load(com.Data)
-	
+
+			Monitor.Exit(_interpreter)
+
 			com.Type = ShellCommandType.NoOp
 	
 			if _commandQueue.Count == 0:
@@ -115,15 +131,16 @@
 
 	
 	private def kickOffGuiThread():
-		_thread = System.Threading.Thread(ThreadRun)
-		_thread.Start()
+		_start as ThreadStart = ThreadRun
+		_thread = System.Threading.Thread (_start)
+		_thread.Start ()
 	
-	def print(obj):
+	private def print(obj):
 		Monitor.Enter (_outputQueue)
 		_outputQueue.Enqueue(obj)
 		Monitor.Exit (_outputQueue)
 	
-	def EnqueueCommand (command as ShellCommand):
+	private def EnqueueCommand (command as ShellCommand):
 		if not _thread.IsAlive:
 			kickOffGuiThread()
 


More information about the Monodevelop-list mailing list