AutoHotkey Community

It is currently May 27th, 2012, 11:23 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 129 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9  Next
Author Message
 Post subject:
PostPosted: October 16th, 2010, 9:05 am 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
To achieve that, you need regular ahk commands too. The ini functions are used to read and store whole entries. You have to parse the value for yourself. It depends on the content, if the real content looks exact the same, then you could use the following lines. Lets see how this could be done: Note, the following examples are made for learning, not as fast and efficient as possible.
Code:
#Include *i ini.ahk ; by Tuncay

#NoEnv
SetWorkingDir, %A_ScriptDir%

; Define your ini variable.
ini =
(
[bla]
var1=a:b:c:d:e:f:
)
; Entry to delete from ini, without a colon.
delete_entry := "c"

; Show the ini content how it looks before any operation is done.
MsgBox BEFORE:`n`n%ini%

; Read the value from ini content.
value := ini_getValue(ini, "bla", "var1")

; Add a double colon to beginning of value,
; otherwise next command could replace an
; entry beginning with the search word.
; Now you can be sure every entry have a
; colon at start and end of itself.
value := ":" . value

; Replace the entry with one colon.
StringReplace, value, value, :%delete_entry%:, :

; Delete the first colon after the work is done,
; to get the initial format of value.
StringTrimLeft, value, value, 1

; Insert/replace the value to the ini content.
ini_replaceValue(ini, "bla", "var1", value)

; Show the ini content how it looks after the operations.
MsgBox AFTER:`n`n%ini%


For next example, you can easily delete whole sections. But if you want put a section in a specific order, you have to parse the whole ini content and rebuild it. There is no command to put a section at desired place. In general there is no need for that.
Also why do you delete it, if you want preserve the place for it? Sure, there are some possibilities. Hmm lets see how this could be solved...
Code:
#Include *i ini.ahk ; by Tuncay

#NoEnv
SetWorkingDir, %A_ScriptDir%

; Define your ini variable.
ini =
(
[1]
var1=a:b:c:d:e:f:
[2]
var1=a:b:c:d:e:f:
[3]
var1=a:b:c:d:e:f:
[4]
var1=a:b:c:d:e:f:
[5]
var1=a:b:c:d:e:f:
[6]
var1=a:b:c:d:e:f:
)

; Show the ini content how it looks before any operation is done.
MsgBox BEFORE:`n`n%ini%

; Get and save the whole section.
section4 := ini_getSection(ini, "4")

; Replace section with nothing, means deleting it.
ini_replaceSection(ini, "4")

MsgBox Section removed:`n`n%ini%

; Modify the content of section.
ini_replaceValue(section4, "4", "var1", "modified")

; Because the building process reads all data from ini variable,
; you have to make sure the section4 is added already into ini var.
ini .= "`n" . section4

; Rebuild the whole ini structure with you own order.
sections := ini_getAllSectionNames(ini)

; Sort the list of all section names in numerical order.
Sort, sections, N D,

; Rebuilding process in the order as defined in previous sorting.
Loop, Parse, sections, `, ; Parse by comma.
{
    newINI .= "`n" . ini_getSection(ini, A_Index)
}

; Delete the first newline character in newINI and assign the
; result to ini variable, overwriting the old ini with new one.
StringTrimLeft, ini, newINI, 1

MsgBox AFTER:`n`n%ini%

The more efficient way would be to generate global variables with ini_exportToGlobals() from the ini structure and work with them. The above example was just for showing and learning.

Also, you could add the section by first retrieving the position in string where you want and insert it at that place with internal commands of ahk. That is much faster.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2010, 5:07 pm 
Offline

Joined: April 30th, 2006, 6:23 pm
Posts: 358
Location: Shigle Springs
Wow, thank you for such detail. It has helped me learn. 8) :D

You see, I made a program that goes through the ini with a counter and when its done, and it sees no more, it exits.
counter += 1

So my INI is
[1]
stuff=1212321
stuff2=1231r3
[2]
omgoodness=wef3r
man=22dwfd
[3]
lala=3322

So my worry was, when I remove [2], my program would freak out.

Man, I understand most of your instructions, but I keep wondering if there is a better way to do this..
I will dive in now and test what you have given me. I am very thankful you put in the comments.

_________________
CPULOCK.com
virusSWAT.com
Computer Repair Computer Service.com
911PCFIX.com


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2010, 5:36 pm 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
Quote:
I keep wondering if there is a better way to do this..

Never loose this attitude (hope its the correct word for this).

I am sure that there are better ways. The examples are just for demonstration purpose (sorry I repeat me again :D).

It depends on your program and what you are really trying todo. Here is another idea. Do not completly delete the section. Leave the section header "[4]" without its keys. Later you can replace the empty section with your own section.

Example:
Code:
#Include *i ini.ahk ; by Tuncay

#NoEnv
SetWorkingDir, %A_ScriptDir%

; Define your ini variable.
ini =
(
[1]
var1=a:b:c:d:e:f:
[2]
var1=a:b:c:d:e:f:
[3]
var1=a:b:c:d:e:f:
[4]
var1=a:b:c:d:e:f:
[5]
var1=a:b:c:d:e:f:
[6]
var1=a:b:c:d:e:f:
)

; Show the ini content how it looks before any operation is done.
MsgBox BEFORE:`n`n%ini%

; Get and save the whole section.
section4 := ini_getSection(ini, "4")

; Replace section with nothing, means deleting it.
ini_replaceSection(ini, "4", "[4]")

MsgBox Section removed:`n`n%ini%

; Modify the content of section.
ini_replaceValue(section4, "4", "var1", "modified")

; Because the building process reads all data from ini variable,
; you have to make sure the section4 is added already into ini var.
ini_replaceSection(ini, "4", section4)

MsgBox AFTER:`n`n%ini%

But you have to be sure, the section 4 is all the time in the ini. Because ini_replace-functions do not insert if it is not already found.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2010, 6:56 pm 
Offline

Joined: April 30th, 2006, 6:23 pm
Posts: 358
Location: Shigle Springs
I see what you are saying and I have spent a lot of time with that additude. Sometimes, I get too caught up in it and my wife misses me :cry: ..

As for the thing I am trying to do is to store the information my program needs in the ini, and then I have it go through each,
[1]
bla=item23
blasubject=hi mom
placewhereitsat=California


so now my program uses the var like
iniread, bla, myini.ini, %counter%, bla
iniread, blasubject, myini.ini, %counter%, blasubject
iniread, placewhereitsat, myini.ini, %counter%, placewhereitsat

then my program uses that info do do what it does, then it increases the counter +=1

and does the next one...

It also has a total amount var that is also kept in the INI

It reads it at the beining of the code,

Code:
loop,
      
{
iniread, tmpbla, %path%\myini.ini, %a_index%, city
total := a_index
   
   
   IfEqual, tmpbla, error
   {
   total -= 1
   break
   }
}


IniWrite, %total%, %path%\myini.ini, mainstuff, total

that gives me the total and when running the program, when it reaches the end, it does the exitsub...

Code:
IniRead, total, %path%\myini.ini, mainstuff, total
   IfGreater, counter, %total%
   goto, exitsub


So, when I remove, [4] and replace it with "modified" or junk, my ini will freak out.
So, when it comes to it, and I delete one, I need to have real data in the right places, or maybe...
(I just thought of a way)
I could have an
"isactive=yes" instead of using the "city=" and ERROR
if yes, the counter goes up, if no, it does not and skips it..

That would be better, right?
Then I will not need to go through all this. :roll: :oops:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2010, 9:45 pm 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
I am not sure if I understand you. If you are using my ini library, then you should not need the internal IniRead commands from AutoHotkey.

Your code to get the total number looks quirky. :D To get the total number, try this:
Code:
#Include *i ini.ahk ; by Tuncay
#NoEnv
SetWorkingDir, %A_ScriptDir%

; Define your ini variable.
ini =
(
[1]
var1=a:b:c:d:e:f:
[3]
var1=a:b:c:d:e:f:
[5]
var1=a:b:c:d:e:f:
[6]
var1=a:b:c:d:e:f:
)
;~ ; Or load the ini file into the variable.
;~ ini_load(ini, path . "myini.ini")

list := ini_getAllSectionNames(ini, count)
MsgBox Count of sections in the ini: %count%`n`nList of sections in the ini: %list%

There is also one function to make global variables out of a ini file or structure. Then you can work faster on these variables.
Code:
#Include *i ini.ahk ; by Tuncay
#NoEnv
SetWorkingDir, %A_ScriptDir%

; Define your ini variable.
ini =
(
[1]
var1=a:b:
[3]
var1=c:d:
[5]
var1=e:f:
[6]
var1=a:f:
)
;~ ; Or load the ini file into the variable.
;~ ini_load(ini, path . "myini.ini")

allkeycount := ini_exportToGlobals(ini, true, "ini", "_")
ListVars
MsgBox Count of sections: %ini_0%
MsgBox Name of the third section: %ini_3%
MsgBox Section [1], key var1 value:`n%ini_5_var1%

Is it possible that you post your full code and ini file? Seeing it could help to understand better. In example, I do not know why your examples are with the Ahk commands IniRead and IniWrite, if you are using my library.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 18th, 2010, 9:03 pm 
Offline

Joined: June 7th, 2010, 3:40 pm
Posts: 553
I'm not sure if your interested in this, but.

I created a faster ini_insertvalue() function by editing yours a little. It's faster then the normal way and gets faster compared to the normal way the larger the ini variable gets.

Code:
ini_insertValue(ByRef _Content, _Section, _Key, _Value, _PreserveSpace = False, _New = 0)
{
    If Not _PreserveSpace
    {
        _Value = %_Value% ; Trim spaces.
        FirstChar := SubStr(_Value, 1, 1)
        If (FirstChar = """" AND SubStr(_Value, 0, 1)= """"
            OR FirstChar = "'" AND SubStr(_Value, 0, 1)= "'")
        {
            StringTrimLeft, _Value, _Value, 1
            StringTrimRight, _Value, _Value, 1
        }
    }
   
   If (_New = 0){
      If (_Section = "")
         _Section = (?:\[.*])?
      Else
         _Section = \[\s*?\Q%_Section%\E\s*?]
      ; Note: The regex of this function was written by Mystiq.
      RegEx = S`aiU)((?:\R|^)\s*%_Section%\s*(?:\R\s*|\R\s*.+\s*=\s*.*?\s*(?=\R)|\R\s*[;#].*?(?=\R))*\R\s*\Q%_Key%\E\s*=.*?)((?=\R|$))
      _Content := RegExReplace(_Content, RegEx, "$1" . _Value . "$2", isInserted, 1)
   } else {
      StrLen_Content := StrLen(_Content), StrLen_Key := StrLen(_Key) + 1, _Section_Location := InStr(_Content,"[" . _Section . "]") + StrLen(_Section) + 2, _Second_Section_Location := InStr(_Content,"`r`n[",false,_Section_Location), _Key_Location := InStr(_Content,"`r`n" . _Key . "=",false,_Section_Location) + StrLen_Key
      If (_Key_Location = StrLen_Key)
         _Key_Location := InStr(_Content,"`n" . _Key . "=",false,_Section_Location) + StrLen_Key
      If (_Second_Section_Location = 0)
         _Second_Section_Location := InStr(_Content,"`n[",false,_Section_Location)
      If (_Second_Section_Location = 0)
         _Second_Section_Location := StrLen_Content
      If (_Key_Location = StrLen_Key or _Key_Location > _Second_Section_Location){
         ErrorLevel := 1, isInserted := 0
         Return isInserted
      }
      _Key_Value_Length := InStr(_Content,"`r`n",false,_Key_Location) - _Key_Location
      If (_Key_Value_Length <= 0)
         _Key_Value_Length := StrLen_Content
      _Content := SubStr(_Content,1,_Key_Location + _Key_Value_Length - 1) . _Value . SubStr(_Content,_Key_Location + _Key_Value_Length), isInserted := 1
   }
    If isInserted
        ErrorLevel = 0
    Else
        ErrorLevel = 1
    Return isInserted
}


I tested it with a few basic things and it seems to function correctly. It's a optional code section, you can use the normal way by passing ini_insertValue(ini, "header", "key", "AndMoreText") or you can use the new way by passing ini_insertValue(ini, "header", "key", "AndMoreText", False,1).

I haven't 100% tested it because I don't know what all can go wrong with inis. I tried to follow how yours worked for error checking and such.

All the tests I did do seemed to work perfectly.

-Robert


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 19th, 2010, 3:17 am 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
Hi rseding91,
I consider your changes and will test them. Unfortunately, in the past I lost my comprehensive test suite for this library, due to a hardware crash. We have now 04:15 here and I do not have time to inspect your code. I thank you for the suggestion. First I will write a test suite again. Then I report my results.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 21st, 2010, 9:24 pm 
Offline

Joined: April 30th, 2006, 6:23 pm
Posts: 358
Location: Shigle Springs
Tuncay wrote:
I am not sure if I understand you. If you are using my ini library, then you should not need the internal IniRead commands from AutoHotkey.

Your code to get the total number looks quirky. :D To get the total number, try this:


Yes, I am using it, thankyou for helping me, your INI took some learning, but man is it fast and smart!

_________________
CPULOCK.com
virusSWAT.com
Computer Repair Computer Service.com
911PCFIX.com


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 22nd, 2010, 9:56 am 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
Quote:
I am using it, thankyou for helping me

Quote:
man is it fast and smart!

These words make me happy. :)

@rseding91
I am building new test cases for the library. This can take some time, as I have very little time for Ahk. Your change will be tested too, but first I need to understand what you have done.
After looking into the code, I have some critcism:
Quote:
Code:
_Section_Location := InStr(_Content,"[" . _Section . "]") + StrLen(_Section) + 2

That is one of the reason why I made this library. It works with one regex call. The regex works in far more situations than this construct. If I would use this construct, then I had to alter all other regexes too. Yes InStr() is faster that RegEx, but InStr is not rock solid and flexible.
In example, a keys value could contain the "[" and "]" characters. Or whitespace between "[" and section name.
And similiar arguments apply to following construct too
Quote:
Code:
_Key_Location := InStr(_Content,"`r`n" . _Key . "=",false,_Section_Location) + StrLen_Key

Correct: The key is searched after the sections location. ...but...
Your construct does not cover whitespace before, between the "=" and keyname.
And also it could interfere with out commented keys or sections, which should not be detected by the parser.
And I like to have one Return command per function. It might be faster to return immadiately, readability is important to me too (old rule: Just one return per function).

Sorry to say that, but this construct is too unsure to me. The regex covers many things in one call. If a full regex compatible construct would be created, then it would may be slower than the counterpart. Also have in mind, someone "can" use regular expression to find a key. Also the ability to search for a key without knowing the section could be used sometimes too. (And comments and different sets of newlines are not covered in my example too.) Example:
Code:
ini =
(
[Tip]
File=Timestamp=0
TimeStamp = 20090716194758
[Recent File List]
File=
File5=[Z:\tempfile.tmp]
File2= 'F:\testfile.ahk '
)
msgbox % ini_getValue(ini, "", "\Efile\d+\Q")

Would find the first found one with a digit. Its just a possibility. (Example is done via getValue to show what the regex can. This applies to other functions too.)
Here is an example What i mean. Try this with your modified version:
Code:
ini =
(
[Tip]
File=Timestamp=0
TimeStamp = 20090716194758
[Recent File List]
File=
File5=[Z:\tempfile.tmp]
File2= 'F:\testfile.ahk '
)

msgbox %ini%
ini_insertValue(ini, "Tip", "Timestamp", "test", false, 1) ; set to 0, then it works with the regex
msgbox %ini%

I know, in most cases it would work. But I have to disappoint you. The change will not be integrated. :cry:

For big ini sources, it would be wise not to work with regex. Then I suggest to export the whole structure to variables and after work, build the ini from the variables. Or just read the one key to modify, and modify its content how often you like with simple assignment operators, and then reassign the keys content "once" with insertValue.

If you really like to work with your modified version, then I suggest to make a lib called "inialt.ahk" (alt for alternative) and rename the function to "inialt_insertValue". Or something similiar. Then you have the one alternative version in coexistence with the "official" version in another file.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 22nd, 2010, 5:46 pm 
Offline

Joined: June 7th, 2010, 3:40 pm
Posts: 553
Ah that's ok.

I just made it to see if I could :)

I knew it wasn't perfect - it was limited in that it only worked if you had your ini setup properly(the way your fix ini function sets it up).

If you want to use anything in it feel free. I had a thought on how you could make the entire function SUPER fast but it would require some fancy code :)

Set each Header/key to a variable name such as:

Code:
[Tip]
File=Timestamp=0
TimeStamp = 20090716194758
[Other]
Something = 12

becomes:

Headers = [Tip]`r`n[Other]
Keys = [Tip]_File`r`n[Tip]_TimeStamp`r`n[Other]_Something
[Tip]_File = Timestamp=0
[Tip]_TimeStamp = 20090716194758
[Other]_Something = 12


But that would get into all of the "can this text be a variable name?" stuff and I don't know what else :P


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 22nd, 2010, 6:55 pm 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
Hmm... to make the functions faster, we could provide alternative functions. The new functions would require (if not already in right format) to call the ini with the repair function ini_repair() once. Then the alternative functions can be sure to have the ini in "correct" or "strict" format.

Currently I have not time to build such functions; building new correct unit tests take my time now. And I am not sure if someone need such faster alternatives.

How many people use ini files? Is it still common today with AutoHotkey?

I myself use the ini functions to store some settings in one variable, which they are accessible from any function in a script, without being globals (with the exception of one variable, if it is not encapsulated in another function via static).

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 25th, 2010, 1:09 am 
Offline

Joined: July 31st, 2008, 10:27 pm
Posts: 336
Hi Tuncay

I have a feature request.

I have an ini file with the same keys under different sections.

[Section1]
Key1=A
[Section2]
Key1=B
[Section3]
Key1=C

I would like to see a function that returns a list of the values of all keys named Key1, without necessarily know the names of the sections.

Key1Values := ini_getAllValuesOfKey(Key1)

Would return A,B,C

Does that seem like a worthwhile option?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 25th, 2010, 9:32 am 
Offline

Joined: November 7th, 2006, 9:47 pm
Posts: 1934
Location: Germany
I don`t think that I would make a new regex based function to resolve request. It is easy to combine functions to get what you need. You can
Code:
sections := ini_getAllSectionNames(ini)

And then parse the list with
Code:
Loop, Parse, sections, `,
{
    values .= ini_getValue(ini, A_LoopField, "Key1") . "`n"
}


I think it is too specific to make a dedicated function. Currently, I stopped the development. Just wrap these calls as a single function. I could do this for you, but have currently no time for that.

Does this the job get done? Hope there is no speed concern.

_________________
{1:"ahkstdlib", 2:"my libs", 3:"my apps", 4:"my license"}
--> Don't feed the troll! <--


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 25th, 2010, 12:27 pm 
Offline

Joined: July 31st, 2008, 10:27 pm
Posts: 336
That makes perfect sense. Thank you for your reply.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 1st, 2010, 9:43 pm 
Offline

Joined: March 10th, 2008, 12:55 am
Posts: 1907
Location: Minnesota, USA
Hi, me again.
uhh.. Ini_Write doesn't seem to work?
Code:
;other working code
Ini_Write("this is a new value", settings, "Misc", "Hello")
ini_save(settings, A_ScriptDir "\settings.ini")
msgbox %settings%

and I get this: http://i51.tinypic.com/73nn0o.png

i've tried many combos. nothing works. I've even tried ini_replaceValue().

is anything special needed for ini_write?

edit: I worked around it by doing this:
Code:
ini_insertKey(settings, Section, name "=" myfile)

_________________
rawr. be very afraid
*poke*
Note: My name is all lowercase for a reason.
"I think Bigfoot is blurry, that's the problem. It's not the photographer's fault, Bigfoot is blurry. So there's a large, out-of-focus monster roaming the countryside."


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 129 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Google Feedfetcher, MSN [Bot], nomissenrojb, Rajat and 58 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group