Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Overwrite line in textfile with "file"-command

    Hi,
    does anybody know a way to overwrite a line (or more) in a text file, which is opened by the "file"-command?
    For a bit more context:
    I try to write a parser for .ihlp files, so that I don't have to copy & paste some information like authorship, contacts, etc. every time again into my help files for my programs.
    In some sense, I try to emulate the behaviour of the viewer for the SMCL {INCLUDE} directive/command.
    The idea is that I write only once certain information, add an include directive to my help, process the help-file with the parser which includes the content of the .ihlp-file.
    The parser itself is relatively simple and a basic version exist, but I want to remove the line with the {INCLUDE help something} and start inserting the content of the something.ihlp file there.

    Below are test files and a shortened version of the parser.
    The parser
    Code:
    program define parseIhelp, rclass
        *Test preprocessing ihelp files and inserting them
        syntax using/
        tempname fh
        confirm file `"`using'"'
        file open `fh' using `"`using'"', read write
        file read `fh' line
        while r(eof)==0{
         if regexm(`"`line'"',"^({INCLUDE)"){
         local linesave "`line'"
         local arg = word("`line'",3)
            tempname fh2
            file open `fh2' using `arg'.ihlp, read
            file read `fh2' line2
            while r(eof)==0{
            if regexm(`"`line2'"',"^{\* ") continue //Ignore comments in the ihlp-file
            file write `fh' `"`line2'"' _n
            file read `fh2' line2
            }
            file close `fh2'
         }
         file read `fh' line
        }
        file close `fh'
    end
    The example test.sthlp file:
    Code:
    {smcl}
    {* Test file for parsing Ihelp files}
    {INCLUDE help author } <- Start inserting the author.ihlp file from here
    The example author.ihlp-file:
    Code:
    {title:Author}
    Name, Occupation, University,etc.
    
    {title:Bug Reporting}
    {psee}
    Please submit bugs, comments and suggestions via email to:    {p_end}
    {psee}
    Further Stata programs and development versions can be found under {p_end}
    My idea so far is to use a mixture of Mata and Stata code to overwrite the mentioned line.
    First read in the file with Mata to find the offset of the line ending before the {INCLUDE}. Then copy the found offset to Stata and open the same file and use "file seek `filehandle' offset" to go to the line before the {INCLUDE}. Then start inserting the content of the author.ihlp file.
    I have the idea only in my head for now and would like to hear better approaches.
    My idea would look roughly like this:

    Code:
    mata
    fh = fopen("test.sthlp","rw")
    line = fget(fh)
    offset =ftell(fh)
    //Here I don't know how to implement a while loop to test for the end of the file and use a regex to find the line containing the {INCLUDE} directive.
    st_local("offset",offset)
    end
    file open `fh' using test.sthlp, read write
    file seek `fh' `offset'
    //Start entering content of author.ihlp
    file write `fh' `line2' _n // `line2' being the line in the author.ihlp
    Let me know if you need more details to understand my problem.

  • #2
    Under similar circumstances, I find it easier to copy lines from the original file to a new file, making discards and substitutions as needed along the way. Overwriting an existing file is a prescription for problems and rarely confers any advantage over creating a new, edited copy.

    Here is sample code from a job I have that reads a pre-written do-file foolishly unhelpfully created with non-Stata syntax on a using clause.
    Code:
        // open new output file to receive edited do-file
        file open df using "new_`psidjob'.do", write text replace
        // open do-file to edit
        file open readjob using `"`dir'/`psidjob'.do"', read text
        // read the first line, which won't be an end-of file
        file read readjob line
        // if the most recent read got a line ...
        while r(eof)==0 {
            // make the substitution if it's on this line
            if substr(`"`line'"',1,12)=="using [path]" {
                local line `"using "`dir'/`psidjob'.txt""'
                }
            // write the line and read the next
            file write df `"`macval(line)'"' _newline
            file read readjob line
            }
        // shut up shop
        file close readjob
        file close df
    (For those playing along at home, if they had replaced "[path]" with "$psidpath" I could have defined the global psidpath before invoking the do-file instead of having to edit the do-file first.)

    Comment


    • #3
      Thanks a lot. I will use an approach similar to your code. I hoped, that there would be a more elegant solution.
      The idea was to process the help file once and have no need to rename the expanded help file to make it directly work with the "help"-command.
      I added a rename option to the command to achieve the same effect without having to write the same file.
      Thanks for your ideas.

      Comment

      Working...
      X