<commit_before>;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
;;;
;;; --- OS interface.
;;;

(in-package :iolib.os)

;;;; Environment access

(defclass environment ()
  ((variables :initarg :variables
              :initform (make-hash-table :test #'equal)
              :accessor environment-variables)))

(defun %envar (env name)
  (gethash name (environment-variables env)))

(defun (setf %envar) (value env name)
  (setf (gethash name (environment-variables env))
        value))

(defun %remvar (env name)
  (remhash name (environment-variables env)))

(defun environment-variable (name &key env)
  "ENVIRONMENT-VARIABLE returns the environment variable
identified by NAME, or NIL if one does not exist.  NAME can
either be a symbol or a string.

SETF ENVIRONMENT-VARIABLE sets the environment variable
identified by NAME to VALUE.  Both NAME and VALUE can be either a
symbols or strings. Signals an error on failure."
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (%envar env name))
      (t
       (isys:%sys-getenv name)))))

(defun (setf environment-variable) (value name &key env (overwrite t))
  (check-type value string)
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (when (or overwrite
                 (null (nth-value 1 (%envar env name))))
         (setf (%envar env name) value)))
      (t
       (isys:%sys-setenv (string name) value overwrite))))
  value)

(defun makunbound-environment-variable (name &key env)
  "Removes the environment variable identified by NAME from the
current environment.  NAME can be either a string or a symbol.
Returns the string designated by NAME.  Signals an error on
failure."
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (%remvar env name))
      (t
       (isys:%sys-unsetenv (string name)))))
  (values name))

(defun %environment ()
  (loop :with env := (make-instance 'environment)
        :for i :from 0 :by 1
        :for string := (mem-aref isys:*environ* :string i)
        :for split := (position #\= string)
        :while string :do
        (let ((var (subseq string 0 split))
              (val (subseq string (1+ split))))
          (setf (environment-variable var :env env) val))
        :finally (return env)))

(defun environment (&optional env)
  "If ENV is non-NIL, ENVIRONMENT copies ENV, otherwise returns the
current global environment.
SETF ENVIRONMENT replaces the contents of the global environment
with that of its argument.

Often it is preferable to use SETF ENVIRONMENT-VARIABLE and
MAKUNBOUND-ENVIRONMENT-VARIABLE to modify the environment instead
of SETF ENVIRONMENT."
  (cond
    (env
     (check-type env environment)
     (make-instance 'environment
                    :variables (copy-hash-table
                                (environment-variables env))))
    (t
     (%environment))))

(defun (setf environment) (newenv)
  (check-type newenv environment)
  (let ((oldenv (environment)))
    (maphash (lambda (k v)
               (setf (environment-variable k) v)
               (makunbound-environment-variable k :env oldenv))
             (environment-variables newenv))<commit_msg>Fix docstring.<commit_after>;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
;;;
;;; --- OS interface.
;;;

(in-package :iolib.os)

;;;; Environment access

(defclass environment ()
  ((variables :initarg :variables
              :initform (make-hash-table :test #'equal)
              :accessor environment-variables)))

(defun %envar (env name)
  (gethash name (environment-variables env)))

(defun (setf %envar) (value env name)
  (setf (gethash name (environment-variables env))
        value))

(defun %remvar (env name)
  (remhash name (environment-variables env)))

(defun environment-variable (name &key env)
  "ENVIRONMENT-VARIABLE returns the environment variable
identified by NAME, or NIL if one does not exist.  NAME can
either be a symbol or a string.

SETF ENVIRONMENT-VARIABLE sets the environment variable
identified by NAME to VALUE.  Both NAME and VALUE can be either a
symbols or strings. Signals an error on failure."
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (%envar env name))
      (t
       (isys:%sys-getenv name)))))

(defun (setf environment-variable) (value name &key env (overwrite t))
  (check-type value string)
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (when (or overwrite
                 (null (nth-value 1 (%envar env name))))
         (setf (%envar env name) value)))
      (t
       (isys:%sys-setenv (string name) value overwrite))))
  value)

(defun makunbound-environment-variable (name &key env)
  "Removes the environment variable identified by NAME from the
current environment.  NAME can be either a string or a symbol.
Returns the string designated by NAME.  Signals an error on
failure."
  (let ((name (string name)))
    (cond
      (env
       (check-type env environment)
       (%remvar env name))
      (t
       (isys:%sys-unsetenv (string name)))))
  (values name))

(defun %environment ()
  (loop :with env := (make-instance 'environment)
        :for i :from 0 :by 1
        :for string := (mem-aref isys:*environ* :string i)
        :for split := (position #\= string)
        :while string :do
        (let ((var (subseq string 0 split))
              (val (subseq string (1+ split))))
          (setf (environment-variable var :env env) val))
        :finally (return env)))

(defun environment (&optional env)
  "If ENV is an ENVIRONMENT instance it is copied, otherwise return the
current global environment.
SETF ENVIRONMENT replaces the contents of the global environment
with that of its argument.

Often it is preferable to use SETF ENVIRONMENT-VARIABLE and
MAKUNBOUND-ENVIRONMENT-VARIABLE to modify the environment instead
of SETF ENVIRONMENT."
  (cond
    (env
     (check-type env environment)
     (make-instance 'environment
                    :variables (copy-hash-table
                                (environment-variables env))))
    (t
     (%environment))))

(defun (setf environment) (newenv)
  (check-type newenv environment)
  (let ((oldenv (environment)))
    (maphash (lambda (k v)
               (setf (environment-variable k) v)
               (makunbound-environment-variable k :env oldenv))
             (environment-variables newenv))
{'fraction_non_alphanumeric': 0.11377983063895304, 'fraction_numerical': 0.001539645881447267, 'mean_word_length': 2.830188679245283, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6676473', 'n_tokens_mistral': 1974, 'n_tokens_neox': 1929, 'n_words': 704}