Jump to content


Photo

[Lib] lineNum - Numbering lines to a string


  • Please log in to reply
8 replies to this topic

#1 Tuncay

Tuncay
  • Members
  • 1943 posts

Posted 03 October 2010 - 07:03 PM

Ahk Compatible: Vanilla / Mainstream
License: New BSD License

Download (~13 kb)
The archive contains the library, a demo script and the documentation.Online Documentation

Description

Adding lines to a text is not hard task. The fun begins, if the numbers should be right justified or printed at lines containing any text only. This function / library adds to an existing string the corresponding line numbers.

It tries todo the job fast as possible, but readability of source code takes precedence over speed. Comments, flexibility and ease of use have slightly higher priority.

Example

This script
#Include lineNum.ahk
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%

text =
(

Hello world!
    foo bar

Following and preceding line contains 4 spaces.

...
This is line 8
Line 9 follows.
Following line is empty

)

text := lineNum(text)

Generates following output at default
1
 2 Hello world!
 3     foo bar
 4
 5 Following and preceding line contains 4 spaces.
 6
 7 ...
 8 This is line 8
 9 Line 9 follows.
10 Following line is empty
11


#2 fincs

fincs
  • Fellows
  • 1530 posts

Posted 03 October 2010 - 07:37 PM

Works on AutoHotkey_L as well, although this line needs to be changed in order to keep the "performance improvement":
VarSetCapacity(string, StrLen(_source))
to:
VarSetCapacity(string, StrLen(_source) [color=red]* (!!A_IsUnicode + 1)[/color])
The code I've highlighted also works on vanilla.

#3 Tuncay

Tuncay
  • Members
  • 1943 posts

Posted 03 October 2010 - 07:52 PM

fincs, is your mission to make AHK_L more popular? :D
If you test code and verify that it works under your environment, how far goes your tests? Basic tests could be no problem, where more complicated stuff under special circumstances fails. Thats why I do not test under AHK_L currently. It would double the test time. What about files with Unicode and regular expression? I mean some things are not covered in the function, so you never can be sure that it works correctly under AHK_L exikos.

#4 fincs

fincs
  • Fellows
  • 1530 posts

Posted 03 October 2010 - 08:20 PM

I'm promoting the writing of AutoHotkey_L compatible scripts because it's time for hardcore AHKers to switch. The benefits are simply too much (real arrays, Debugger, variadic functions, built-in Unicode, x64 and COM support, etc). I like to think of it as AutoHotkey v1.1 8)

PD: AHK_L handles file encodings & RegEx stuff automatically.

#5 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 03 October 2010 - 10:42 PM

fincs, is your mission to make AHK_L more popular?

There will be increasing number of people using AHKL in the light of abandoned AHK development. Its also not certain for how long AHKL will be developed but it still goes on every day and many important things asked for years have been developed rendering new developments slightly less important comparing to vanilla ahk.

After all, its not that hard to make cross-ahk code (as fincs pointed out in this case). But to do that, you need to switch to AHKL for good. It might be hard at the start but benefits outweight the learning curve, plus you can limit yourself to understandable stuff. I use AHK only to see what I need to change in order for the script to work there, not vice-versa.

#6 SoLong&Thx4AllTheFish

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts

Posted 04 October 2010 - 08:44 AM

@Tuncay if you want to add some more options, look at
<!-- m -->http://www.autohotke... ... LineNumber<!-- m -->
- restart
- padding with char (leading zero or space or whatever)

#7 Tuncay

Tuncay
  • Members
  • 1943 posts

Posted 04 October 2010 - 06:49 PM

hugov, if you would look in the documentation, you would see that I implemented some options already, and even more than you :D. Like your function, padding of line numbers to right justify them is possible. My version uses padding with spaces at default. The features of the two functions are different:

Same features:
[*:3lck3cff]They two can pad line numbers, but lineNum() can use zeros or spaces only (3rd Option: format),
where TF_LineNumber() can use any character for that (2nd and 4rd Options: Leading and Char).lineNum only features:
[*:3lck3cff]Can start the initial line number different than 1, i.e. 0 or any other positive value. (5rd Option: start)
[*:3lck3cff]Separator string between the line numbers and the actual original lines can be specified other than space, i.e. double colon and space. (3rd Option: sep)
[*:3lck3cff]Its possible to add line numbers to lines with printable characters only. (2rd Option: mode)TF_LineNumber only features:
[*:3lck3cff]Line numbering can be reseted at specified interval of processed lines. (3rd Option: Restart)Benchmark

I wanted to know which of them operates faster. Results with benchmark settings iter=100 and high=1 on VanillaAHK: (lower is better)

0.125147     -> lineNum_settings1 (by Tuncay, default settings)
0.229914     -> TF_LineNumber_settings1 (by hugov, default settings)

0.133491     -> lineNum_settings2 (by Tuncay, mimic TFs default)
0.236031     -> TF_LineNumber_settings2 (by hugov, mimic lineNums default)


Only default settings are covered, because if someone needs a feature not present in one of the functions, the time savings are not a selection-criterion. And this is the benchmark script:

#Include Z:\ahkstdlib\lib\qpx.ahk
#Include Z:\myAhkScripts\lib\lineNum\lineNum.ahk
#Include Z:\ahkstdlib\lib\tf.ahk

#NoEnv
SendMode Input 
SetWorkingDir %A_ScriptDir% 

iter := 100 ; iteration, number of how many times the text should be replicated and function called
high := 1 ; false=use actual A_BatchLines and priority, true =use SetBatchLines, -1 and high priority

text_template =
(

Hello world!
    foo bar

Following and preceding line contains 4 spaces.

...
This is line 8
Line 9 follows.
Following line is empty

)

out .= "`n" . benchmark("lineNum_settings1", "by Tuncay, default settings", text_template, iter, high)
out .= "`n" .   benchmark("TF_LineNumber_settings1", "by hugov, default settings", text_template, iter, high)

out .= "`n`n" . benchmark("lineNum_settings2", "by Tuncay, mimic TFs default", text_template, iter, high)
out .= "`n" .   benchmark("TF_LineNumber_settings2", "by hugov, mimic lineNums default", text_template, iter, high)

MsgBox, 1, Benchmark results, Ok copies to clipboard`n`n%out%
IfMsgBox Ok
    Clipboard := out

RETURN

benchmark_lineNum_settings1(ByRef _param)
{
    lineNum(_param)
}

benchmark_lineNum_settings2(ByRef _param)
{
    lineNum(_param, 1, " ", 0)
}

benchmark_TF_LineNumber_settings1(ByRef _param)
{
    TF_LineNumber(_param)
}

benchmark_TF_LineNumber_settings2(ByRef _param)
{
    TF_LineNumber(_param, true, false, " ")
}

benchmark(_func, _desc="", _param="", _i=100, _high=false)
{
    BatchLines := A_BatchLines
    SetBatchLines, -1
    If (_param = "")
    {
        Loop, %_i%
        {
            text .= "`n" . A_Index
        }
    }
    {
        VarSetCapacity(_text, StrLen(_param) * _i)
        Loop, % _i - 1
        {
            text .= _param
        }
    }    
    If (_high) ; Do not change prior call of SetBatchLines, -1
    {
        Process, priority, , High
    }
    else
    {
        SetBatchLines, %BatchLines%
    }
    if IsFunc("benchmark_" . _func) 
    {
        StartTime := isFunc("QPX") ? QPX(true) : A_TickCount
        Loop, %_i%
        {
            benchmark_%_func%(text)
        }
        ElapsedTime := isFunc("QPX") ? QPX(false) : A_TickCount - StartTime
        result := ElapsedTime . "`t -> " . _func . " (" . _desc . ")"
    }
    else
    {
        result := "---" . "`t -> " . _func . " <function not found>"
    }
    SetBatchLines, %BatchLines%
    return result
}
The benchmark script uses QPX, if it is included or in stdlib folder), otherwise simple A_TickCount is used.
Mine version is faster. And there is a lot of room for optimizations. ;)

#8 SoLong&Thx4AllTheFish

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts

Posted 04 October 2010 - 07:13 PM

@Tuncay: I didn't see the 0 padding in the basic example you provided above that is why I mentioned it. In general TF isn't built for speed so any function you will make will no doubt be faster as a similar/related TF one.

#9 Tuncay

Tuncay
  • Members
  • 1943 posts

Posted 04 October 2010 - 07:21 PM

TF isn't built for speed

I know that, mines are not made for speed too. I was just offended :D:D:D (not really...)