How can I read file loaded in a variable in guile? - scheme

I am new to to guile and scheme and what I am trying to do right now is take a scheme file (file.scm) and load it up into a variable so I will be able to parse it, and I am having trouble finding how to do this anywhere.
What I have right now is
(define var (load "file.scm")) ; loads file scheme
but I am unsure how to start reading the lines.

load parses and runs the scheme code in a file. If you just want to read a file, use open-input-file.
(define file (open-input-file "file address here"))
(display (read-line file))

If you just want to read an entire file as a string, there's a function for that in the textual-ports module. You'd use it something like:
(define contents (call-with-input-file "file.txt" get-string-all))
(You can use call-with-input-file and with-input-from-file to avoid having to manually open and close a file port, which is handy)

Related

Execute file compiled by sbcl cannot make random or make with-open-file work

I write a script with using random and with-open-file, it works well in slime by emacs. But it cannot work when I use sbcl compile it to a execute file.
My purpose is using this code to choice the random video to open.;update at 1/1/2016
Code:;update at 1/1/2016
(setf *random-state* (make-random-state t))
(defun choice-file-to-open (files) ;file is a list content all pathspecs which I want to open
(let ((filePath (nth (random (length files)) files)))
(open-by-system filePath) ;use shell command "open" to open file
(with-open-file (file "./logs" :direction :output
:if-exists :append
:external-format '(:utf-8 :replacement #\?))
(format file "~S~%" (namestring filePath))) ;write filename in log file to record the open history
))
open-by-system is a function to open file.
My purpose is pick random file in the folder. But it always choice the same file to open when I use it. Only for the singer execute file compiled by sbcl, the slime during emacs work well.
Then I add the log file to record the filename every time I open. But there is no log file, as same as problem before, this problem only issues in executed file, and code works well in slime. with-open-file won't work in singer execute file compiled, but slime work well.
I found the answer (Random) in Common Lisp Not So Random? and it cannot solve the random problem.
What wrong with me? There are many differences between slime and sbcl?
I fix them by myself. There are two problems in my old codes. Firstly, random not work well. Secondly, the with-open-file don't work.
The codes worked below:
(defun choice-file-to-open (files) ;file is a list content all pathspecs which I want to open
(let ((filePath (nth (random (length files) (make-random-state t)) files)))
(open-by-system filePath) ;use shell command "open" to open file
(with-open-file (file "./logs"
:direction :output
:if-does-not-exist :create
:if-exists :append
:external-format '(:utf-8 :replacement #\?))
(format file "~S~%" (namestring filePath))) ;write filename in log file to record the open history
))
(make-random-state t) should be added at the end of random. Then fix the random problem.
:if-does-not-exist :create should be add because the log file don't existed. Then fix the log file can't create problem.

Special Emacs setup for a single file: Run lisp code at startup from command line

Suppose I have I file A.txt, which I often edit and also, into which I often insert the text "Test". It would then be nice if I could just press e.g. the F5 key to insert the text "Test" into the buffer. However, when I edit any other file I do not want the F5 key to be bound in this way.
It would then be nice if I could avoid messing up my .emacs init file with special code. Hence, consider defining a new file start.el located in the same directory as A.txt. The contents of start.el could be:
(defun insert-test-text ()
(interactive)
(insert "Test"))
(global-set-key '[f5] 'insert-test-text)
Then I write a bash script editA for editing the file A.txt in Emacs, e.g.
#! /bin/bash
emacs --run-code-on-init start.el A.txt &
The command line option run-code-on-init is unfortunately not a valid option.. Is there any good solution to this problem?
I think you could get the effect you want by doing
emacs -l start.el a.txt
out of the box. According to the man page, that should start up emacs editing a.txt, with the lisp code in start.el loaded.
Does that work, or is there a reason the simple solution doesn't work for your use case?
Here's my view of the solution:
(defun insert-test-text ()
(interactive)
(insert "test"))
(add-hook
'text-mode-hook
(lambda ()
(if (string= (file-name-nondirectory (buffer-file-name))
"A.txt")
(local-set-key (kbd "<f5>") 'insert-test-text))))
This will define the shortcut only for files named A.txt.
You should tweak the code to your needs, of course.
Also, don't forget to bookmark the file if you edit it a lot.
I've got a very quick setup (around two key chords) for ~20 files/directories.
that I edit a lot. The setup is described here.
UPD
If you want the binding for single file, just drop file-name-nondirectory like so:
(add-hook
'text-mode-hook
(lambda ()
(if (string= (buffer-file-name)
"~/A.txt")
(local-set-key (kbd "<f5>") 'insert-test-text))))
And here's what I do to keep my config manageable - in ~/.emacs:
(defvar dropbox.d "~/Dropbox/")
(defvar emacs.d (concat dropbox.d "source/site-lisp/"))
(add-to-list 'load-path emacs.d)
(defun add-subdirs-to-load-path (dir)
(let ((default-directory dir))
(normal-top-level-add-subdirs-to-load-path)))
(add-subdirs-to-load-path emacs.d)
(load "init")
;; you can put the code in "source/site-lisp/feature1.el"
(load "feature1")
That's about the whole content of my ~/.emacs - the rest of the config is
it the respective files in site-lisp dir.
You can comment out the (load "feature1") to turn it off temporarily.

Racket Scheme: Include externel rkt file with dynamic file name

I want to load external rkt file in racket scheme from a parameter of a function.
E.G.,
(define (test fileName)
(include fileName)
)
However, I am getting error indicating that fileName is not a pathname string, file' form, orlib' form.
Is there a way to fix this or is there another better way to include a file from dynamic filename?
The best way to do this is to make the external file a module, and use dynamic-require.

Create Files Through Racket

How would I use Racket to create a file to be able to store and edit user-inputted data, or, for example, a high score. I've read through some of the documentation and haven't found a clear answer on how to do this.
The Racket Guide has a chapter on Input and Output. The first section explains reading and writing files, with examples. It says
Files: The open-output-file function opens a file for writing, and
open-input-file opens a file for reading.
Examples:
> (define out (open-output-file "data"))
> (display "hello" out)
> (close-output-port out)
> (define in (open-input-file "data"))
> (read-line in)
"hello"
> (close-input-port in)
If a file exists already, then open-output-file raises an exception by
default. Supply an option like #:exists 'truncate or #:exists 'update
to re-write or update the file:
and so on.
There are some simple functions for reading and writing a file in the 2htdp/batch-io library: http://docs.racket-lang.org/teachpack/2htdpbatch-io.html . They are somewhat limited in that they access a file only in the same directory as the program itself, but you can do something like:
(require 2htdp/batch-io)
(write-file "highscore.txt" "Alice 25\nBob 40\n")
to write data to a file (the \n means a newline character), and then
(read-lines "highscore.txt")
to get back the lines of the file, as a list of strings.

How to append to a file using Scheme?

I am using TinyScheme (actually Script-Fu in GIMP), and cannot find a good way to open a file and append a line of text to it.
I am trying to log some info to the file for debugging, and transcript-on doesn't seem to be implemented...
Right now I am scraping along by reading the entire file (one character at a time!), concatenating that into a string, concatenating my text to the end of that, then writing it all out to the file again.
There must be a better way!
It's going to be something like
(open-file "myfile" (file-options append))
You want to look up the file-options function.
Update
Here's the guile version:
(open-file "myfilename.dat" "a")
Just had the same exact problem in GIMP and decided to use open-input-output-file. My solution is something like this:
(let* ((out (open-input-output-file "file.txt") ))
(display "hello world" out)
(newline out)
(close-output-port out))
Went through the TinyScheme source and checked that this function actually calls fopen with "a+". The file is open for reading and writing. For our purposes we only want to write, so just ignore reading.
I am writing a Script-Fu to write the values of gimp-selection-bounds to a file.

Resources