Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Operating on specific lines in multiline string
#1
Operating on specific lines in a multiline string can be quite useful. The following QM function comes from QM's extension resources.
Is there a similar member function in LA?

Member function str.ReplaceLineN
Code:
Copy      Help
function# $replacement lineindex [nlines]

;Replaces specified line(s).
;Returns index of first character of lineindex-th line, or -1 if lineindex is too big.

;replacement - replacement string.
;lineindex - zero-based line index.
;nlines - number of lines to replace. Default or 0: 1 line.

;EXAMPLE
;str s="zero[]one[]two"
;s.ReplaceLineN("ONE" 1)
;out s


if(nlines<1) nlines=1
int i=findl(this lineindex)
if(i>=0)
,int j=findl(this+i nlines)
,if(j>=0) j-2; if(j<i or this[i+j]!=13) j+1
,this.replace(replacement i j)
ret i

Member function str.RemoveLineN
Code:
Copy      Help
function# lineindex [nlines]

;Removes specified line(s).
;Returns index of first character of lineindex-th line, or -1 if lineindex is too big.

;lineindex - zero-based line index.
;nlines - number of lines to remove. Default or 0: 1 line.

;EXAMPLE
;str s="zero[]one[]two"
;s.RemoveLineN(1)
;out s


if(nlines<1) nlines=1
int i=findl(this lineindex)
if(i>=0) this.remove(i findl(this+i nlines))
ret i

Member function str.InsertLineN
Code:
Copy      Help
function# $insertstring lineindex

;Inserts line.
;Returns index of first character of lineindex-th line, or -1 if lineindex is too big.

;insertstring - string to be inserted. Does not have to end with new line.
;lineindex - zero-based line index where to insert insertstring.

;EXAMPLE
;str s="zero[]one[]two"
;s.InsertLineN("" 1) ;;inserts empty line
;out s


int i=findl(this lineindex)
if(i<0 and numlines(this)=lineindex) this+"[]"; i=this.len
if(i>=0)
,str s.from(insertstring "[]")
,this.insert(s i s.len)
ret i
#2
Code:
Copy      Help
print.clear();

var s = """
0
1
2
3

"""
;

//print.it(s.LineAppend("append"));
//print.it(s.LineReplace(2, "repl"));
//print.it(s.LineRemove(2));
//print.it(s.LineInsert(2, "ins"));
//print.it(s.LineGetRange(1, out var r), r);
//print.it(s.LineAt(6, out var r), r);


static class MyExtString {
    /// <summary>
    ///
Appends string as new line.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="s"></param>
    public static string LineAppend(this string t, string s)
        => t.NE() || t.Ends('\n') ? t + s + "\r\n" : t + "\r\n" + s + "\r\n";
    
    /// <summary>
    ///
Replaces the specified line.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="line">0-based line index.</param>
    ///
<param name="repl">Replacement string.</param>
    ///
<exception cref="ArgumentOutOfRangeException">Invalid line index.</exception>
    public static string LineReplace(this string t, int line, string repl) {
        if (!LineGetRange(t, line, out var r)) throw new ArgumentOutOfRangeException("line");
        return t.ReplaceAt(r.start..r.end, repl);
    }

    
    /// <summary>
    ///
Removes the specified line.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="line">0-based line index.</param>
    ///
<exception cref="ArgumentOutOfRangeException">Invalid line index.</exception>
    public static string LineRemove(this string t, int line) {
        if (!LineGetRange(t, line, out var r)) throw new ArgumentOutOfRangeException("line");
        return t.Remove(r.start..r.endRN);
    }

    
    /// <summary>
    ///
Inserts string as new line before the specified line.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="line">0-based line index.</param>
    ///
<param name="s"></param>
    ///
<exception cref="ArgumentOutOfRangeException">Invalid line index.</exception>
    public static string LineInsert(this string t, int line, string s) {
        if (!LineGetRange(t, line, out var r)) throw new ArgumentOutOfRangeException("line");
        return t.Insert(r.start, s + "\r\n");
    }

    
    /// <summary>
    ///
Finds start/end offsets of the specified line.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="line">0-based line index.</param>
    ///
<param name="r">Results. The <b>endRN</b> field is the start of next line or equal to <b>end</b>.</param>
    ///
<returns>true if found.</returns>
    ///
<exception cref="ArgumentOutOfRangeException">Negative <i>line</i>.</exception>
    public static bool LineGetRange(this string t, int line, out (int start, int end, int endRN) r) {
        if (line < 0) throw new ArgumentOutOfRangeException("line");
        int start = 0;
        while (line-- > 0) {
            start = t.IndexOf('\n', start) + 1;
            if (start == 0) { r = default; return false; }
        }

        int end = t.IndexOf('\n', start);
        r = end < 0 ? (start, t.Length, t.Length) : (start, end - (end > 0 && t[end - 1] == '\r' ? 1 : 0), end + 1);
        return true;
    }

    
    /// <summary>
    ///
Finds line containing the specified character index.
    /// </summary>
    ///
<param name="t"></param>
    ///
<param name="i">0-based character index.</param>
    ///
<param name="r">Results. The <b>endRN</b> field is the start of next line or equal to <b>end</b>.</param>
    ///
<returns>0-based line index.</returns>
    ///
<exception cref="ArgumentOutOfRangeException"><i>line</i> < 0 or > string length.</exception>
    public static int LineAt(this string t, int i, out (int start, int end, int endRN) r) {
        if ((uint)i > t.Length) throw new ArgumentOutOfRangeException("i");
        int line = 0, start = 0, end;
        for (; ; start = end, line++) {
            end = t.IndexOf('\n', start) + 1;
            if (end > i || end == 0) break;
        }

        r = end == 0 ? (start, t.Length, t.Length) : (start, end - (end > 0 && t[end - 2] == '\r' ? 2 : 1), end);
        return line;
    }
}
#3
Thank you, I'm accelerating the replacement of QM with LA.


Forum Jump:


Users browsing this thread: 1 Guest(s)