guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/3] utils: Add 'edit-expression'.


From: 宋文武
Subject: [PATCH 1/3] utils: Add 'edit-expression'.
Date: Wed, 6 Apr 2016 18:37:24 +0800

* guix/utils.scm (edit-expression): New procedure.
* tests/utils.scm (edit-expression): New test.
---
 guix/utils.scm  | 37 +++++++++++++++++++++++++++++++++++++
 tests/utils.scm | 13 +++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/guix/utils.scm b/guix/utils.scm
index de54179..1318dac 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -86,6 +86,7 @@
             split
             cache-directory
             readlink*
+            edit-expression
 
             filtered-port
             compressed-port
@@ -318,6 +319,42 @@ a list of command-line arguments passed to the compression 
program."
         (unless (every (compose zero? cdr waitpid) pids)
           (error "compressed-output-port failure" pids))))))
 
+(define* (edit-expression source-properties proc #:key (encoding "UTF-8"))
+  "Edit the expression specified by SOURCE-PROPERTIES using PROC, which should
+be a procedure that take the original expression in string and returns a new
+one.  ENCODING will be used to interpret all port I/O, it default to UTF-8."
+  (with-fluids ((%default-port-encoding encoding))
+    (let*-values (((file line column)
+                   (values
+                    (assoc-ref source-properties 'filename)
+                    (assoc-ref source-properties 'line)
+                    (assoc-ref source-properties 'column)))
+                  ((start end) ; start and end byte positions of the expression
+                   (call-with-input-file file
+                     (lambda (port)
+                       (values
+                        (begin (while (not (and (= line (port-line port))
+                                                (= column (port-column port))))
+                                 (when (eof-object? (read-char port))
+                                   (error 'end-of-file file)))
+                               (ftell port))
+                        (begin (read port)
+                               (ftell port))))))
+                  ((pre-bv expr post-bv)
+                   (call-with-input-file file
+                     (lambda (port)
+                       (values (get-bytevector-n port start)
+                               (get-string-n port (- end start))
+                               (get-bytevector-all port))))))
+      (with-atomic-file-output file
+        (lambda (port)
+          (put-bytevector port pre-bv)
+          (display (proc expr) port)
+          ;; post-bv maybe the end-of-file object.
+          (when (not (eof-object? post-bv))
+            (put-bytevector port post-bv))
+          #t)))))
+
 
 ;;;
 ;;; Advisory file locking.
diff --git a/tests/utils.scm b/tests/utils.scm
index 6b77255..d0ee02a 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -333,6 +333,19 @@
                "This is a journey\r\nInto the sound\r\nA journey ...\n")))
     (get-string-all (canonical-newline-port port))))
 
+
+(test-equal "edit-expression"
+  "(display \"GNU Guix\")\n(newline)\n"
+  (begin
+    (call-with-output-file temp-file
+      (lambda (port)
+        (display "(display \"xiuG UNG\")\n(newline)\n" port)))
+    (edit-expression `((filename . ,temp-file)
+                       (line     . 0)
+                       (column   . 9))
+                     string-reverse)
+    (call-with-input-file temp-file get-string-all)))
+
 (test-end)
 
 (false-if-exception (delete-file temp-file))
-- 
2.6.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]