An ini module for slope-lang
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sloum 7e21635f6b Merges in namespace support 5 months ago Adds namespace support 5 months ago
main.slo Merges in namespace support 5 months ago
module.json Adds namespace support 5 months ago


ini is an ini parsing module for the slope programming language.

The current state of the module allows for parsing an ini file into a lambda closure allowing for dynamically reading/updating the underlying data without having to call set! over and over again. It is also possible to create a new ini instance and start from scratch.

  • The parser is case sensitive for all values, which is a deviation from the old windows 3.1 ini style where section names were not case sensitive
  • The parser does not support multi-line keys/values
  • Comments using the ; character are supported both on their own line as at the end of a key/value pair line


Three procedures are intended for general use within the module:

  1. (ini::parse [source-data: io-handle] [close-io-handle?: bool]) => procedure|#f
    • ini::parse takes an io-handle rather than a file path in order to facilitate easily taking in network data or data from a string buffer in addition to only using files
    • The second argument tells ini::parse whether to close the io-handle once parsing is complete
  2. (ini::pretty-print [ini::assoc: list]) => string
    • The procedure returned by ini::parse will output the needed association when called with no arguments: (ini::pretty-print (my-ini-instance))
  3. (ini::create) => procedure
    • Returns the same procedure as ini::parse, but with no data in the ini

the ini "object"

Both ini::parse and ini::create return a procedure. This procedure can be called in a number of ways. In the below examples we will be using a procedure that has been saved as my-ini-instance.

The procedure signature is:

(my-ini-instance [[section: string]] [[key: string]] [[value: string]]) => list|string

To get/return the whole ini as an associative list:

(my-ini-instance) => list, ex. (("SETTINGS" (("theme" "light") ("version" "1.2.1"))))

To get/return a single section as an associative list:

(my-ini-instance [section: string]) => list, ex. (("theme" "light") ("version" "1.2.1"))

To get a value for a given key in a given section (the most common use case when reading an ini file):

(my-ini-instance [section: string] [key: string]) => string, ex. "1.2.1"

To set a value, creating the section and key if need be:

(my-ini-instance [section: string] [key: string] [value: string]) => list, ex. (("SETTINGS" (("theme" "light") ("version" "1.2.1"))) ("FAVORITES" (("lang" "slope"))))

Example: Working with existing ini files

;; Load the module (assumes the module is in your modules directory)
(load-mod "ini")

;; For use later, we'll create a var for the filepath
(define inputfile "/home/slope/test.ini")

;; Open a file for reading, lets assume the following (overly simplified) file contents:
;;   version=1.2.1
;;   theme=dark
(define my-ini-file (file-open-read inputfile))

;; Parse the ini file and assign it to a variable.
;; 'ini::parse' returns a closure/procedure that can
;; be used to look up/update values from the ini file
;; that was passed in. ini::parse expects an io-handle
;; and _not_ a file path.
;; (ini::parse [io-handle] [close-io-handle: bool]) => procedure/#f
(define my-ini (ini::parse my-ini-file #t))

;; The resulting procedure can take 0-4 arguments with
;; the following call structure/results:
(my-ini)                            ; => (("SETTINGS" (("version" "1.2.1") ("theme" "dark"))))
(my-ini "SETTINGS")                 ; => (("version" "1.2.1") ("theme" "dark"))
(my-ini "SETTINGS" "theme")         ; => "dark"
(my-ini "SETTINGS" "theme" "light") ; => (("SETTINGS" (("version" "1.2.1") ("theme" "light"))))
(my-ini "FAVORITES" "lang" "slope") ; => (("SETTINGS" (("version" "1.2.1") ("theme" "light"))) ("FAVORITES" (("lang" "slope"))))

;; Now that the above data has been updated, it could be written back to
;; a file easily...
(define my-ini-file (file-open-write inputfile #t))  ; open the file
(write (ini::pretty-print (my-ini)) my-ini-file)     ; write the "pretty-printed" ini file
(close my-ini-file)                                  ; close the file

Example: Creating new ini files

;; Load the module (assumes the module is in your modules directory)
(load-mod "ini")

;; Create a new ini instance
(define my-ini (ini::create))

;; Add some data
(my-ini "SETTINGS" "version" "1.2.1")
(my-ini "SETTINGS" "theme" "dark")

;; Update some data
(my-ini "SETTINGS" "theme" "light")

;; Open a file to save to
(define f (file-open-write (path-abs "~/my-config.ini")))

;; Write the data to the file using `ini::pretty-print`
;; to convert the slope representation into an actual
;; ini formatted string
(write (ini::pretty-print (my-ini)) f)

;; Close the file
(close f)