# Rewind a port (file) or other method?

**URL:** https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837
**Category:** Questions & Answers
**Created:** [March 25, 2024, 3:10pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837 "2024-03-25T15:10:52Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)
#### Post date: [March 25, 2024, 3:10pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/1 "2024-03-25T15:10:53Z")

</div>

hello,

i just want to skip comments and blank lines at the beginning of a file, i find a solution that rewind the port/file using file-position but is there other method/solution?

```scheme

(require (only-in racket/base [do do-scheme])) ; backup original do

(include "while-do-when-unless.scm")

(include "SRFI-105.scm")

(define (test-blank-lines-or-comments li)
  (or (not (non-empty-string? li)) ; empty line
      (regexp-match #px"^[[:blank:]]*;+" li))) ; space, comments

(define (skip-comments-and-empty-lines in)
  
  (define li '())
  (define fpos '())
  (define cpt -1)

  (do
      (set! cpt (+ 1 cpt))
      (set! fpos (file-position in))
      (set! li (read-line in))
    while (test-blank-lines-or-comments li))

  (file-position in fpos) ;; rewind to the code to parse after comments or spaces

  (display "SRFI-105.rkt : skip-comments-and-empty-lines : number of skipped lines (comments, spaces) at beginning : ")
  (display cpt)
  (newline)
  )

(define (literal-read-syntax src in)

  (skip-comments-and-empty-lines in)
  
  (define lst-code (process-input-code-tail-rec in))
  lst-code)
   

```

note 'do' is defined this way:

```scheme
;; > (define i 0) 
;; > (do (display-nl "toto") (set! i (+ i 1)) while (< i 4)) 
;; toto
;; toto
;; toto
;; toto
;; Warning: this 'do' break the one of scheme !
(define-syntax do
  (syntax-rules (do)
    ((do b1 ...
       while pred)
     (let loop () b1 ... (when pred (loop))))))

```

it works:

```scheme
Welcome to DrRacket, version 8.12 [cs].
Language: reader "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/src/SRFI-105.rkt", with debugging; memory limit: 8192 MB.
SRFI-105.rkt : skip-comments-and-empty-lines : number of skipped lines (comments, spaces) at beginning : 12

```

regards

damien

---

<div class="post-metadata">

### Author: ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)
#### Post date: [March 25, 2024, 4:02pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/2 "2024-03-25T16:02:46Z")

</div>

The [regexp matching functions](https://docs.racket-lang.org/reference/regexp.html#%28part._.Regexp_.Matching%29) like `regexp-match` take a _pattern_ and an _input_.

The _pattern_ is `(or/c regexp? byte-regexp? string? bytes?)`.

The _input_ is `(or/c string? bytes? path? input-port?)`. The interesting point here is you can match a regexp directly on an input port. You don't need to read a string from the port first.

Also, the `regexp-try-match` variant doesn't consume non-matches from the port.

So I think you could simply do something like:

```scheme
(define in (open-input-string "\n;comment\n ;λ\n12 ;comment"))
(let loop ()
  (when (regexp-try-match #px"^(;.+)?\n" in)
    (loop)))
(require (only-in racket/port port->string))
(print (port->string in)) ; => "12

```

I didn't think much about that particular regexp, it doesn't try to handle all your cases, but you can take it from there. 😄

---

<div class="post-metadata">

### Author: ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)
#### Post date: [March 26, 2024, 2:55pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/3 "2024-03-26T14:55:36Z")

</div>

`regexp-try-match` is the solution because as you say it doesn't consume non-matches on the port. Previously i searched a solution as peek-char for read-line but it does not exist a peek-line in Racket or Scheme.

I suppose `regexp-try-match` do a lot of peek-char and it is a solution.

About the regexp there is a problem in both code, the mine had an error, it does not check well the lines containing only spaces, and there is no solution with a single regexp for comments and empty lines of spaces or tab. We must use 2 regexp.  
And we still have to iterate in a loop because regular expression are based on automata theory and they have no 'memory' : we can add a quantification on a pattern but we cannot add a quantification on clusters of patterns. So we cannot crunch many lines of comments and spaces in a single shot.

My corrected code should have be like this:

```scheme
(define (test-blank-lines-or-comments li)
 (or (not (non-empty-string? li)) ; empty line
		 (regexp-match #px"^[[:blank:]]*$" li) ; only spaces, tabs
		 (regexp-match #px"^[[:blank:]]*;+" li))) ; space,tabs, comments
  

```

but i will use this new version of code ,which is now more simple with regular expressions and `regexp-try-match`:

```scheme
(define (skip-comments-and-empty-lines in)
  (do
      while (or (regexp-try-match #px"^[[:space:]]" in) ; skip space,tab,new line,...
		       (regexp-try-match #px"^;[^\n]*\n" in))) ; and also comments

```

and the main code still looks like that:

```scheme
(display "Possibly skipping some header's lines containing space,tabs,new line,etc or comments.") (newline) (newline)
(skip-comments-and-empty-lines in)

(when (regexp-try-match #px"^#!r6rs[[:blank:]]*\n" in)
	(display "Detected R6RS code. (#!r6rs)") (newline) (newline))

```

tested on piece of file looking like:

;; Damien Mattei

;; 2024

; modify it to be recompiled by Racket ?

#!r6rs  
(module start-logic-racket racket  
(provide (all-defined-out))  
(require "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/Scheme+.rkt")  
(require "racket/operation+.rkt")

...

the result is:

```scheme
Possibly skipping some header's lines containing space,tabs,new line,etc or comments.

Detected R6RS code. (#!r6rs)

```

note: with this solution there is no way to know how many lines are skipped.

---

<div class="post-metadata">

### Author: ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)
#### Post date: [March 26, 2024, 3:05pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/4 "2024-03-26T15:05:35Z")

</div>

> [@damien\_mattei](#):
>
> note: with this solution there is no way to know how many lines are skipped.

Use `port-count-lines!` to enable automatic line counting.  
Then use `port-next-location` to get the line number before and after.

---

<div class="post-metadata">

### Author: ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)
#### Post date: [March 26, 2024, 5:00pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/5 "2024-03-26T17:00:27Z")

</div>

yes, i added the info (even if it is not necessary):

```scheme
  (port-count-lines! in) ; turn on counting on port
  
  (display "Possibly skipping some header's lines containing space,tabs,new line,etc or comments.") (newline) (newline)
  (skip-comments-and-empty-lines in)

  (when (regexp-try-match #px"^#!r6rs[[:blank:]]*\n" in)
	(display "Detected R6RS code. (#!r6rs)") (newline) (newline))

  (declare lc cc pc)
  (set!-values (lc cc pc) (port-next-location in))
  (display "SRFI-105.rkt : number of skipped lines (comments, spaces, directives,...) at header's beginning : ")
  (display lc)
  (newline)
  (newline)

```

and the output result:

```scheme
Possibly skipping some header's lines containing space,tabs,new line,etc or comments.

SRFI-105.rkt : number of skipped lines (comments, spaces, directives,...) at header's beginning : 15

```

fun thing is that it counts one more lines from the opening of file , counting an invisible to my procedure line catched by the Racket parser:  
#lang reader "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/src/SRFI-105.rkt"  
is in the count even if i cannot access to it from my parser that works after the Racket parser.

---

<div class="post-metadata">

### Author: ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)
#### Post date: [March 26, 2024, 6:17pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/6 "2024-03-26T18:17:14Z")

</div>

> [@damien\_mattei](#):
>
> fun thing is that it counts one more lines from the opening of file , counting an invisible to my procedure line catched by the Racket parser:  
> #lang reader "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/src/SRFI-105.rkt"  
> is in the count even if i cannot access to it from my parser that works after the Racket parser.

That might be because `port-count-lines` numbers lines starting from 1 not 0?

So if you've skipped 1 line, `port-next-location` is going to tell you "line number 2 is current".

* * *

I believe `port-count-lines` was added to support giving Racket syntax objects the kind of line and column numbers that would be useful in error messages -- where, because reasons, the convention is line numbers are from 1 but column numbers are from 0. 🤷

It's fine to use port line counting for other purposes, you just need to keep that in mind.

---

<div class="post-metadata">

### Author: ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)
#### Post date: [March 26, 2024, 10:36pm UTC](https://racket.discourse.group/t/rewind-a-port-file-or-other-method/2837/7 "2024-03-26T22:36:35Z")

</div>

yes it should start counting from 1 like in the Racket's GUI,see the screenshot:

 ![Capture d’écran 2024-03-26 à 23.30.28](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/5/5b6aa6a379836575ef9ec53049f67393108cf1ed.jpeg)

so 15 is the next line to be read in the buffer.

And #lang reader directive pass the file to SRFI-105.rkt procedure at the beginning with buffer positioned to line 2
