Roger, I guess for now we should hold off on the culture stuff ... We'll discuss it post 0.85.
Something else : should <replacetokens> also be able to use a case-insensitive search&replace ? Gert ----- Original Message ----- From: "Dahlman, Roger" <[EMAIL PROTECTED]> To: "Gert Driesen" <[EMAIL PROTECTED]> Cc: "Nant-Developers (E-Mail)" <[EMAIL PROTECTED]> Sent: Tuesday, July 27, 2004 5:14 PM Subject: RE: [nant-commits] CVS: nant/src/NAnt.Core/Filters ReplaceString.cs,NONE,1.1 ExpandProperties.cs,1.2,1.3 ReplaceTokens.cs,1.2,1.3 TabsToSpaces.cs,1.2,1.3 I think that culture should really be specific to a file. In the case of nAnt it might make since for it to be specific to a <fileset>. I think that collections of files defined by a file set should usually have a common culture. In the case of localizing an application it is probable that resources of a given application for a given culture will be grouped by directory and thus in the same <fileset>. Does this sound reasonable to you? We could place the culture attribute on the filter or filterset but that would not be flexible if a global filterset was defined that was referenced in a task. I can look into this if you like but I can't commit to finishing it for several days. What do you think? Roger From: Gert Driesen Sent: Sun 7/25/2004 8:08 AM To: Dahlman, Roger Cc: Nant-Developers (E-Mail) Subject: Re: [nant-commits] CVS: nant/src/NAnt.Core/Filters ReplaceString.cs,NONE,1.1 ExpandProperties.cs,1.2,1.3 ReplaceTokens.cs,1.2,1.3 TabsToSpaces.cs,1.2,1.3 > ----- Original Message ----- > From: "Dahlman, Roger" <[EMAIL PROTECTED]> > To: "Gert Driesen" <[EMAIL PROTECTED]> > Sent: Saturday, July 24, 2004 3:18 AM > Subject: RE: [nant-commits] CVS: nant/src/NAnt.Core/Filters ReplaceString.cs,NONE,1.1 > ExpandProperties.cs,1.2,1.3 ReplaceTokens.cs,1.2,1.3 >TabsToSpaces.cs,1.2,1.3 > > You have to excuse my knowledge of Ant. For some reason I was under the > impression it did not support the <replacestring> filter so I just > choose arbitrary attributes. Sure we can rename them! It makes more > since. I'll commit these changes to cvs in a minute ... > The code I implemented will get its cultural information from the thread > it is executing on. If there is a place I can get cultural information > that is not that of the thread of execution but that of the nAnt project > I can easily use it when I do my string comparisons. There are several > schemes we can use. Do you have on in mind? Is the culture a member of > an Element? No it's not a member of Element. We might allow a culture to be set on individual filters themselves, or we could have it set on filterchain (which can then pass it on to the individual filters behind the scene), not sure what approach is best ... > I can take a look at the <replaceregex> and see what it will take. Great. > You're right about the buffer. We need a buffer to read ahead to process > the expressions. It seems like it will have to be rather large but I > will need to think about this a little. Sure, no problem. Gert -----Original Message----- From: Gert Driesen [mailto:[EMAIL PROTECTED] Sent: Friday, July 23, 2004 5:27 PM To: Roger A. Dahlman Subject: Re: [nant-commits] CVS: nant/src/NAnt.Core/Filters ReplaceString.cs,NONE,1.1 ExpandProperties.cs,1.2,1.3 ReplaceTokens.cs,1.2,1.3 TabsToSpaces.cs,1.2,1.3 Roger, Is it ok if I rename the name of the attributes of the <replacestring> filter to better match those of the Ant filter ? I guess it would've been better if we could also support culture-sensitive comparison (using a user-specified culture), but I don't think that would be easy (but I guess you can better estimate the effort) ... Something else : should we also add a <replaceregex> filter (http://ant.apache.org/manual/CoreTypes/filterchain.html#replaceregex) ? We're limited to a certain number of character that we can buffer to execute a regex on, right ? Thanks for the big effort you did again ! Gert ----- Original Message ----- From: "Roger A. Dahlman" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Saturday, July 24, 2004 12:02 AM Subject: [nant-commits] CVS: nant/src/NAnt.Core/Filters ReplaceString.cs,NONE,1.1 ExpandProperties.cs,1.2,1.3 ReplaceTokens.cs,1.2,1.3 TabsToSpaces.cs,1.2,1.3 > Update of /cvsroot/nant/nant/src/NAnt.Core/Filters > In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2294/src/NAnt.Core/Filters > > Modified Files: > ExpandProperties.cs ReplaceTokens.cs TabsToSpaces.cs > Added Files: > ReplaceString.cs > Log Message: > Updated Docs and added ReplaceString filter > > --- NEW FILE: ReplaceString.cs --- > // NAnt - A .NET build tool > // Copyright (C) 2001 Gerry Shaw > // > // 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 2 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, write to the Free Software > // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > // > > using System; > using System.Collections; > using System.Collections.Specialized; > using System.Globalization; > using System.IO; > using System.Text; > using System.Xml; > > using NAnt.Core; > using NAnt.Core.Attributes; > using NAnt.Core.Types; > > namespace NAnt.Core.Filters { > /// <summary> > /// Replaces all occurrences of a given string in the original input with > /// user-supplied replacement string. > /// </summary> > /// <remarks> > /// <para> > /// This filter replaces all occurrences of a given string in the original input stream with > /// a user-supplied replacement string. By default string comparisons are case > /// sensitive but this can be changed by setting the optional <see cref="IgnoreCase"/> attribute to true. > /// </para> > /// <para> > /// To use this filter specify the string to be replaced with the <see cref="TargetString"/> attribute and > /// the string to replace it with using the <see cref="ReplacementString"/> attribute. Both the target and > /// replacement strings can contain from 1 to n character but may not be empty. > /// </para> > /// <para> > /// Filters are intended to be used as a element of a <see cref="FilterChain"/>. A FilterChain can > /// be applied to a given task. > /// </para> > /// </remarks> > /// <example> > /// <para>Standard Syntax</para> > /// <code> > /// <![CDATA[ > /// //Replaces all occurrences of 3.14 with PI > /// <replacestring targetstring="3.14" replacementstring="PI"/> > /// > /// //Replaces string, String, etc with System.String > /// <replacestring targetstring="String" replacementstring="System.String" /> > /// ]]> > /// </code> > /// </example> > [ElementName("replacestring")] > public class ReplaceString : Filter { > /// <summary> > /// Delegate for Read and Peek. Allows the same implementation > /// to be used for both methods. > /// </summary> > delegate int AcquireCharDelegate(); > > #region Private Instance Fields > > private string _targetString; > private string _replacementString; > private string _outputBuffer; > private bool _endStreamAfterBuffer; > private int _bufferPosition = 0; > private bool _stringNotFound = true; > private bool _ignoreCase = false; > > //Methods used for Read and Peek > private AcquireCharDelegate ReadChar = null; > private AcquireCharDelegate PeekChar = null; > > #endregion Private Instance Fields > > > #region Public Instance Properties > > /// <summary> > /// String to replace with the value specified by <see cref="ReplacementString"/>. > /// </summary> > [TaskAttribute("targetstring", Required=true)] > [StringValidator(AllowEmpty=false)] > public string TargetString { > get { return _targetString; } > set { _targetString = value; } > } > > /// <summary> > /// String the replaces all instances of the string specified by <see cref="TargetString"/>. > /// </summary> > [TaskAttribute("replacementstring", Required=true)] > [StringValidator(AllowEmpty=false)] > public string ReplacementString { > get { return _replacementString; } > set { _replacementString = value; } > } > > /// <summary> > /// Determines if case will be ignored > /// The default is <see langword="false"/>. > /// </summary> > [TaskAttribute("ignorecase", Required=false)] > [BooleanValidator()] > public bool IgnoreCase > { > get { return _ignoreCase; } > set { _ignoreCase = value; } > } > #endregion Public Instance Properties > > #region Override implementation of ChainableReader > > /// <summary> > /// Construct that allows this filter to be chained to the one > /// in the parameter chainedReader. > /// </summary> > /// <param name="chainedReader">Filter that the filter will be chained to</param> > public override void Chain(ChainableReader chainedReader) { > base.Chain(chainedReader); > ReadChar = new AcquireCharDelegate(base.Read); > PeekChar = new AcquireCharDelegate(base.Peek); > } > > /// <summary> > /// Reads the next character applying the filter logic. > /// </summary> > /// <returns>Char as an int or -1 if at the end of the stream</returns> > public override int Read() { > return GetNextCharacter(ReadChar); > } > > /// <summary> > /// Reads the next character applying the filter logic without > /// advancing the current position in the stream. > /// > /// Peek currently is not supported. > /// </summary> > /// <returns> > /// Char as an int or -1 if at the end of the stream. > /// </returns> > public override int Peek() { > //Need to maintain seperate state for Read and Peek for this to work > throw new ApplicationException("Peek currently is not supported."); > //return GetNextCharacter(PeekChar); > } > > #endregion Override implementation of ChainableReader > > #region Override implementation of Element > > /// <summary> > /// Initialize the filter by setting its parameters. > /// </summary> > protected override void InitializeElement(XmlNode elementNode) { > > if (this._targetString.Length == 0) { > throw new BuildException("The target string can not be empty.", Location); > } > } > > #endregion Override implementation of Element > > #region Private Instance Methods > > /// <summary> > /// <para> > /// Helper function used to search for the filter's traget string. If the string > /// is found the result is true. If the string was not found false is returned and > /// nonMatchingChars contains the characters that were read to determine if the > /// string is present. > /// </para> > /// > /// <para> > /// It is assumed the stream is positioned at the character after the first character > /// in the target string. > /// </para> > /// </summary> > /// <param name="startChar">First character in target string</param> > /// <param name="streamEnded">Ture if the stream ended while search for the string.</param> > /// <param name="nonMatchingChars">Characters that were read while searching for the string.</param> > /// <returns></returns> > private bool FindString(int startChar, out bool streamEnded, out string nonMatchingChars) { > > //Init output parameters > streamEnded = false; > nonMatchingChars = ""; > > //create a new buffer > StringBuilder buffer = new StringBuilder(_targetString.Length, _targetString.Length); > > //Add first char that initiate the FindString > buffer.Append((char)startChar); > > //Try to read each character of the string to replace. > //Store the characters in the output buffer until we know > //we have found the string. > int streamChar; > for (int pos = 1 ; pos < _targetString.Length ; pos++) > { > //Read a character > streamChar = base.Read(); > > //Store the character if it is not the end of the buffer character > if (streamChar != -1) > { > buffer.Append((char)streamChar); > } > > //Is it the correct character? > if (CompareCharacters(streamChar, _targetString[pos]) == false) > { > //Check for end of stream > if (streamChar == -1) > { > streamEnded = true; > } > > //Put any characters that were read into the output buffer since > //the string was not found. > nonMatchingChars = buffer.ToString(); > > return false; > } > } > > > //The string was found > return true; > } > > /// <summary> > /// Returns the next character in the stream replacing the specified character. Using the > /// <see cref="AcquireCharDelegate"/> allows for the same implementation for Read and Peek > /// </summary> > /// <param name="AcquireChar">Delegate to acquire the next character. (Read/Peek)</param> > /// <returns>Char as an int or -1 if at the end of the stream</returns> > private int GetNextCharacter(AcquireCharDelegate AcquireChar) { > int ch; > > //Either read the next character or if there is a buffer output the next character > if (_outputBuffer == null) { > ch = base.Read(); > } else { > //Characters left in the buffer? > if (_bufferPosition < _outputBuffer.Length) { > > //If this is the last character of a buffer that was not the replacemant string > //process the last charactor again since it might be the beginning of another token. > if ((_stringNotFound == true) && (_bufferPosition == _outputBuffer.Length - 1)) { > //Process token end char again. It could be the same as token begin. > ch = _outputBuffer[_outputBuffer.Length - 1]; > _bufferPosition++; > } else { > //Pass along buffer character > return _outputBuffer[_bufferPosition++]; > } > } else {//End of buffer > > //Reset buffer and get next char > _outputBuffer = null; > _bufferPosition = 0; > > //Read the next character or end the stream the end of the stream > //was encountered while reading the buffer. > if (!_endStreamAfterBuffer) { > ch = ReadChar(); > } else { > return -1; > } > } > } > > //If the character matches the first character of the target string then search > //for the string. > if (CompareCharacters(ch, _targetString[0])) { > > //Search for the target string > if (FindString(ch, out _endStreamAfterBuffer, out _outputBuffer) == true) > { > //Target was found > > _stringNotFound = false; > _outputBuffer = _replacementString; > _bufferPosition = 1; > return _replacementString[0]; > } > else > { > //Target not found > > _stringNotFound = true; > _bufferPosition = 1; > return ch; > } > > } else { > //This was not a beginning token so just pass it through > return ch; > } > > } > > /// <summary> > /// Compares to characters taking into account the _ignoreCase flag. > /// </summary> > /// <param name="char1"></param> > /// <param name="char2"></param> > /// <returns></returns> > private bool CompareCharacters(int char1, int char2) > { > //Compare chars with or without case > if (_ignoreCase == true) > { > > return (char.ToUpper((char)char1) == char.ToUpper((char)char2)); > } > else > { > return char1 == char2; > } > > } > > #endregion Private Instance Methods > } > } > > > Index: ExpandProperties.cs > =================================================================== > RCS file: /cvsroot/nant/nant/src/NAnt.Core/Filters/ExpandProperties.cs,v > retrieving revision 1.2 > retrieving revision 1.3 > diff -C2 -d -r1.2 -r1.3 > *** ExpandProperties.cs 15 Jul 2004 19:45:29 -0000 1.2 > --- ExpandProperties.cs 23 Jul 2004 22:02:37 -0000 1.3 > *************** > *** 36,39 **** > --- 36,41 ---- > /// characters are not guaranteed to be expanded. > /// </para> > + /// Filters are intended to be used as a element of a <see cref="FilterChain"/>. A FilterChain can > + /// be applied to a given task. > /// </remarks> > /// <example> > > Index: ReplaceTokens.cs > =================================================================== > RCS file: /cvsroot/nant/nant/src/NAnt.Core/Filters/ReplaceTokens.cs,v > retrieving revision 1.2 > retrieving revision 1.3 > diff -C2 -d -r1.2 -r1.3 > *** ReplaceTokens.cs 11 Jul 2004 13:13:02 -0000 1.2 > --- ReplaceTokens.cs 23 Jul 2004 22:02:37 -0000 1.3 > *************** > *** 30,55 **** > > namespace NAnt.Core.Filters { > ! /// <summary> > ! /// Replaces tokens in the original input with user-supplied values. > ! /// </summary> > ! /// <remarks> > ! /// <para> > ! /// Replaces all tokens between the beginning and ending > ! /// token. > ! /// </para> > ! /// <para> > ! /// Tokens are specified using <see cref="Token" /> elements. > ! /// </para> > ! /// </remarks> > ! /// <example> > ! /// <para>Standard Syntax</para> > ! /// <code> > ! /// <![CDATA[ > ! /// <replacetokens begintoken="@" endtoken="@"> > ! /// <token key="DATE" value="${TODAY}" /> > ! /// </replacetokens> > ! /// ]]> > ! /// </code> > ! /// </example> > [ElementName("replacetokens")] > public class ReplaceTokens : Filter { > --- 30,69 ---- > > namespace NAnt.Core.Filters { > ! /// <summary> > ! /// Replaces tokens in the original input with user-supplied values. > ! /// </summary> > ! /// <remarks> > ! /// <para> > ! /// This filter replaces all token surrounded by a beginning and ending > ! /// token. The default beginning and ending tokens both default to '@'. The > ! /// optional <see cref="BeginToken"/> and <see cref="EndToken "/> can > ! /// be specified to change either token. > ! /// </para> > ! /// <para> > ! /// Tokens are specified by using the <see cref="Token"/> element. It is possiable > ! /// to specify from 1 to n tokens and replacement values. Values can be any valid NAnt > ! /// expression > ! /// </para> > ! /// <para> > ! /// Filters are intended to be used as a element of a <see cref="FilterChain"/>. A FilterChain can > ! /// be applied to a given task. > ! /// </para> > ! /// </remarks> > ! /// <example> > ! /// <para>Standard Syntax</para> > ! /// <code> > ! /// <![CDATA[ > ! /// <replacetokens> > ! /// <token key="DATE" value="${TODAY}" /> > ! /// </replacetokens> > ! /// > ! /// <replacetokens begintoken="~" endtoken="@"> > ! /// <token key="DATE" value="${TODAY}" /> > ! /// </replacetokens> > ! /// ]]> > ! /// </code> > ! /// </example> > ! > ! > [ElementName("replacetokens")] > public class ReplaceTokens : Filter { > *************** > *** 104,107 **** > --- 118,122 ---- > /// <summary> > /// Tokens and replacement values. > + /// See <see cref="Token"/> > /// </summary> > [BuildElementArray("token")] > > Index: TabsToSpaces.cs > =================================================================== > RCS file: /cvsroot/nant/nant/src/NAnt.Core/Filters/TabsToSpaces.cs,v > retrieving revision 1.2 > retrieving revision 1.3 > diff -C2 -d -r1.2 -r1.3 > *** TabsToSpaces.cs 11 Jul 2004 13:13:02 -0000 1.2 > --- TabsToSpaces.cs 23 Jul 2004 22:02:37 -0000 1.3 > *************** > *** 30,33 **** > --- 30,37 ---- > /// The <see cref="TabsToSpaces" /> filter replaces tabs in a text file > /// with spaces. > + /// <para> > + /// Filters are intended to be used as a element of a <see cref="FilterChain"/>. A FilterChain can > + /// be applied to a given task. > + /// </para> > /// </remarks> > /// <example> > > > > ------------------------------------------------------- > This SF.Net email is sponsored by BEA Weblogic Workshop > FREE Java Enterprise J2EE developer tools! > Get your free copy of BEA WebLogic Workshop 8.1 today. > http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click > _______________________________________________ > nant-commits mailing list > [EMAIL PROTECTED] > https://lists.sourceforge.net/lists/listinfo/nant-commits > ------------------------------------------------------- This SF.Net email is sponsored by BEA Weblogic Workshop FREE Java Enterprise J2EE developer tools! Get your free copy of BEA WebLogic Workshop 8.1 today. http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click _______________________________________________ nant-developers mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/nant-developers
