Add/Remove Keywords dynamically

May 5, 2010 at 6:04 AM
Is it possible to add/remove keywords dynamically? I have thought about using a in-memory xml file and then do a configure each time I need to add/remove keywords but isn't there an easier way to do it? Thank you Claudia
Developer
May 7, 2010 at 1:50 PM

Hello Claudia,

I wrote my own LoadConfig function, which is called every time the AutoCompleteList is updated.

 

Configuration config = new Configuration(doc.FileName, "SWoDL", true);
config.Lexing_Keywords.Add(new KeyWordConfig(3, dynamicKeywords, false));
this.sciDocument.ConfigurationManager.Configure(config);

 

dynamicKeywords is just a string with the Keywords separated by whitespaces.

Hope it helps.

Best Regards

Julius

May 7, 2010 at 3:29 PM

Hello Julius,

this helps a lot, thank you very much.

Slightly different approach than mine and much more elegant ;-)

Regards

Claudia

Oct 2, 2010 at 7:04 AM

Enclosed find Scintilla extensions to load keywords dynamically from text or xml file. Both methods have overloads whether to append or replace existing keyword set. Please find the xml format in the comments and take note of the Keywords 'Inherit' attribute, set it to false or you will find lot of unnecessary keyword copies in your set (I do not fully understand what Scintilla is doing internally). Hope that could be of use for someone.

How to use:

textEditor.LoadKeywordsFromText(2, "keywords.txt"); // replace existing

or

textEditor.LoadKeywordsFromText(2, "keywords.txt", true); // append to existing

or

textEditor.LoadKeywordsFromXml("keywords.xml"); // replace existing

or

textEditor.LoadKeywordsFromXml("keywords.xml", true); // append to existing

 

/// <summary>
/// Loads keywords from text file into a specified keyword set and replaces existing keyword set. 
/// Keywords must be space separated.
/// </summary>
public static bool LoadKeywordsFromText(this Scintilla scintilla, int keywordSet, string txtFileName)
{
	return LoadKeywordsFromText(scintilla, keywordSet, txtFileName, false);
}

/// <summary>
/// Loads keywords from text file into a specified keyword set.  
/// Specified append flag indicates whether keywords shall be appended to existing keyword set. 
/// Keywords must be space separated.
/// </summary>
public static bool LoadKeywordsFromText(this Scintilla scintilla, int keywordSet, string txtFileName, bool append)
{
	if (scintilla == null || String.IsNullOrEmpty(txtFileName) || !File.Exists(txtFileName))
	{
		return false;
	}

	try
	{
		System.IO.StreamReader streamReader = new System.IO.StreamReader(txtFileName);

		string keywords = streamReader.ReadToEnd();

		streamReader.Close();
		streamReader.Dispose();

		keywords = CleanUpKeywords(keywords);

		if (append)
		{
			string oldKeywords = scintilla.Lexing.Keywords[keywordSet];
			oldKeywords = CleanUpKeywords(oldKeywords);

			if (!oldKeywords.Contains(keywords))
			{
				scintilla.Lexing.Keywords[keywordSet] = oldKeywords + " \r\n" + keywords;
			}
		}
		else
		{
			scintilla.Lexing.Keywords[keywordSet] = keywords;
		}
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
		return false;
	}
	return true;
}


/// <summary>
/// Loads Scintilla keywords from xml file for a pre-defined lexer and replaces existing keyword set.
/// </summary>
public static bool LoadKeywordsFromXml(this Scintilla scintilla, string xmlFileName)
{
	//  XML Format:
	//  <KeywordsList>
	//      <Keywords List="number"  Inherit="False">
	//          xx ccc www xxx
	//      </Keywords>
	//      ...
	//  </KeywordsList>
	//
	// If custom languge contains a keyword list, do not specify the Keywords 'Inherit' attribute or set it to FALSE.
	// 
	return LoadKeywordsFromXml(scintilla, xmlFileName, true);
}

/// <summary>
/// Loads Scintilla keywords from xml file for a pre-defined lexer. 
/// Specified append flag indicates whether keywords shall be appended to existing keyword set.
/// </summary>
public static bool LoadKeywordsFromXml(this Scintilla scintilla, string xmlFileName, bool append)
{
	if (String.IsNullOrEmpty(xmlFileName) || !File.Exists(xmlFileName) || scintilla == null)
		return false;

	XmlDocument xmlDoc = new XmlDocument();
	try
	{
		xmlDoc.Load(xmlFileName);
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
		return false;
	}

	try
	{
		XmlElement xmlElement = xmlDoc.DocumentElement;
		XmlNodeList xmlKeywordsList = xmlElement.GetElementsByTagName("Keywords");
		
		foreach (XmlElement xmlKeywords in xmlKeywordsList)
		{
			// we need at least one attribute
			if (xmlKeywords.Attributes.Count < 1)
				continue;

			foreach (XmlAttribute xmlAttr in xmlKeywords.Attributes)
			{
				if (xmlAttr.Name.ToUpper() == "LIST")
				{
					int keywordSet;
					if (int.TryParse(xmlAttr.Value, out keywordSet))
					{
						string keywords = CleanUpKeywords(xmlKeywords.InnerText);

						if (append)
						{
							string oldKeywords = scintilla.Lexing.Keywords[keywordSet];
							oldKeywords = CleanUpKeywords(oldKeywords);

							if (!oldKeywords.Contains(keywords))
							{
								// this does not work for our purpose:
								// scintilla.Lexing.SetKeywords();
								scintilla.Lexing.Keywords[keywordSet] = oldKeywords + " \r\n" + keywords;
							}
						}
						else
						{
							scintilla.Lexing.Keywords[keywordSet] = keywords;
						}
					} // if TryParse
				} // if LIST
			} // foreach xmlAttr
		} // foreach xmlKeywords
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
		return false;
	}

	return true;
}

/// <summary>
/// Returns a single space delimited keyword list.
/// </summary>
static string CleanUpKeywords(string keywords)
{
	// replace all unnecessary junk to have a clean list
	keywords = keywords.Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ').Replace('\0', ' ').Trim();
	while (keywords.Contains("  "))
		keywords = keywords.Replace("  ", " ");
	return keywords;
}

 

 

Oct 26, 2010 at 11:08 AM

Hi,

 

        I have included "SciLexer.dll" and ScintillaNet.dll in c# ,it is showing a form but I want to add my own keyword list having "FOR FROM TO ENDFOR OUTPUT" and should change the color of these.But it not loading my keywords from file keywordlist.txt. Even I have followed above code but without any success.

 

Please help me in this.

Thank you.

Nov 9, 2010 at 10:08 AM

I've added two methods to add a keyword to the list of keywords (in Lexer.cs):

public void AddKeyword(int _keywordSet, string _keyword) { _keywords[_keywordSet] += " " + _keyword; }
and to add a word to the list of words for auto completion (in AutoComplete.cs):
        public void AddWord(string _value)
        {
            _list.Add(_value);
            _list.Sort();
        }