unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#19274: tar-mode.el: allow for adding new archive members
@ 2014-12-04 21:17 Ivan Shmakov
  2014-12-05  2:10 ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-04 21:17 UTC (permalink / raw)
  To: 19274

[-- Attachment #1: Type: text/plain, Size: 442 bytes --]

Package:  emacs
Severity: wishlist

	Please consider the patch MIMEd.

	* tar-mode.el: Allow for adding new archive members.
	(tar--pad-to, tar--put-at, tar-header-serialize): New functions.
	(tar-current-position): Split from tar-current-descriptor.
	(tar-current-descriptor): Use it.
	(tar-new-entry): New command.
	(tar-mode-map): Bind it.

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/diff, Size: 4769 bytes --]

--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -369,6 +369,58 @@
 	string)
   (tar-parse-octal-integer string))
 
+(defun tar--pad-to (pos)
+  (make-string (+ pos (- (point)) (point-min)) 0))
+
+(defun tar--put-at (pos val)
+  (when val
+    (insert (tar--pad-to pos) val)))
+
+(defun tar-header-serialize (header &optional update-checksum)
+  (with-temp-buffer
+    (set-buffer-multibyte nil)
+    (let ((encoded-name
+	   (encode-coding-string (tar-header-name header)
+				 tar-file-name-coding-system)))
+      (unless (< (length encoded-name) 99)
+	;; FIXME: implement it
+	(error "Long file name support is not implemented"))
+      (insert encoded-name))
+    (insert (tar--pad-to tar-mode-offset)
+	    (format "%6o\0 " (logand #o777777 (tar-header-mode header)))
+	    (format "%6o\0 " (logand #o777777 (tar-header-uid  header)))
+	    (format "%6o\0 " (logand #o777777 (tar-header-gid  header))))
+    (insert (tar--pad-to tar-size-offset)
+	    (format "%11o " (tar-header-size header)))
+    (insert (tar--pad-to tar-time-offset)
+	    (tar-octal-time (tar-header-date header))
+	    " ")
+    ;; omit tar-header-checksum (tar-chk-offset) for now
+    (tar--put-at   tar-linkp-offset (tar-header-link-type header))
+    (tar--put-at   tar-link-offset  (tar-header-link-name header))
+    (when (tar-header-magic header)
+      (tar--put-at tar-magic-offset (tar-header-magic header))
+      (tar--put-at tar-uname-offset (tar-header-uname header))
+      (tar--put-at tar-gname-offset (tar-header-gname header))
+      (let ((dmaj (tar-header-dmaj header))
+	    (dmin (tar-header-dmin header)))
+	(tar--put-at tar-dmaj-offset
+		     (and dmaj (format "%7o\0" (logand #o7777777 dmaj))))
+	(tar--put-at tar-dmin-offset
+		     (and dmin (format "%7o\0" (logand #o7777777 dmin))))))
+    (tar--put-at 512 "")
+    (let ((ck (tar-header-block-checksum (buffer-string))))
+      (goto-char (+ (point-min) tar-chk-offset))
+      (delete-char 8)
+      (insert (format "%6o\0 " ck))
+      (when update-checksum
+	(setf (tar-header-checksum header) ck))
+      (tar-header-block-check-checksum (buffer-string)
+				       (tar-header-checksum header)
+				       (tar-header-name header)))
+    ;; .
+    (buffer-string)))
+
 
 (defun tar-header-block-checksum (string)
   "Compute and return a tar-acceptable checksum for this block."
@@ -547,6 +599,7 @@ defvar tar-mode-map
     (define-key map "p" 'tar-previous-line)
     (define-key map "\^P" 'tar-previous-line)
     (define-key map [up] 'tar-previous-line)
+    (define-key map "I" 'tar-new-entry)
     (define-key map "R" 'tar-rename-entry)
     (define-key map "u" 'tar-unflag)
     (define-key map "v" 'tar-view)
@@ -731,10 +784,14 @@
   (interactive "p")
   (tar-next-line (- arg)))
 
+(defun tar-current-position ()
+  "Return the `tar-parse-info' index for the current line."
+  (count-lines (point-min) (line-beginning-position)))
+
 (defun tar-current-descriptor (&optional noerror)
   "Return the tar-descriptor of the current line, or signals an error."
   ;; I wish lines had plists, like in ZMACS...
-  (or (nth (count-lines (point-min) (line-beginning-position))
+  (or (nth (tar-current-position)
 	   tar-parse-info)
       (if noerror
 	  nil
@@ -948,6 +1005,45 @@
 	(write-region start end to-file nil nil nil t)))
     (message "Copied tar entry %s to %s" name to-file)))
 
+(defun tar-new-entry (filename &optional index)
+  "Insert a new empty regular file before point."
+  (interactive "*sNew file name: ")
+  (let* ((buffer  (current-buffer))
+	 (index   (or index (tar-current-position)))
+	 (d-list  (and (not (zerop index))
+		       (nthcdr (+ -1 index) tar-parse-info)))
+	 (pos     (if d-list
+		      (tar-header-data-end (car d-list))
+		    (point-min)))
+	 (new-descriptor
+	  (make-tar-header
+	   nil
+	   filename
+	   #o644 0 0 0
+	   (current-time)
+	   nil				; checksum
+	   nil nil
+	   nil nil nil nil nil)))
+    ;; update the data buffer; fill the missing descriptor fields
+    (with-current-buffer tar-data-buffer
+      (goto-char pos)
+      (insert (tar-header-serialize new-descriptor t))
+      (setf  (tar-header-data-start new-descriptor)
+	     (copy-marker (point) nil)))
+    ;; update tar-parse-info
+    (if d-list
+	(setcdr d-list     (cons new-descriptor (cdr d-list)))
+      (setq tar-parse-info (cons new-descriptor
+				 tar-parse-info)))
+    ;; update the listing buffer
+    (save-excursion
+      (goto-char (point-min))
+      (forward-line index)
+      (let ((inhibit-read-only t))
+	(insert (tar-header-block-summarize new-descriptor) ?\n)))
+    ;; .
+    index))
+
 (defun tar-flag-deleted (p &optional unflag)
   "In Tar mode, mark this sub-file to be deleted from the tar file.
 With a prefix argument, mark that many files."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-04 21:17 bug#19274: tar-mode.el: allow for adding new archive members Ivan Shmakov
@ 2014-12-05  2:10 ` Stefan Monnier
  2014-12-05 20:20   ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2014-12-05  2:10 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> 	* tar-mode.el: Allow for adding new archive members.
> 	(tar--pad-to, tar--put-at, tar-header-serialize): New functions.
> 	(tar-current-position): Split from tar-current-descriptor.
> 	(tar-current-descriptor): Use it.
> 	(tar-new-entry): New command.
> 	(tar-mode-map): Bind it.

Thanks, looks good, please install (with appropriate etc/NEWS entry).
See nitpicks below,


        Stefan


> +    ;; omit tar-header-checksum (tar-chk-offset) for now

Please capitalize and punctuate your comments.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-05  2:10 ` Stefan Monnier
@ 2014-12-05 20:20   ` Ivan Shmakov
  2014-12-06  5:09     ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-05 20:20 UTC (permalink / raw)
  To: 19274

>>>>> Stefan Monnier <monnier@iro.umontreal.ca> writes:

[…]

 >> + ;; omit tar-header-checksum (tar-chk-offset) for now

 > Please capitalize and punctuate your comments.

	Even the one-line ones?

	Given that I have some time to improve this patch, could someone
	please suggest a good place to add a menu entry for
	tar-new-entry in tar-mode-map?  (I never use Emacs’ menus
	myself, so I’m rather clueless on this.)

	BTW, I wonder if it makes sense to split the make-tar-header
	form (with all the nil’s there) off tar-new-entry into a new
	(tar-new-regular-file-header filename &optional size time)
	function?  I guess that’d ease the creation of Tar archives from
	Emacs Lisp code; (and I already imagine some uses to that.)

	I’ll also write a proper docstring for tar-header-serialize, so
	to make it clear this function is part of the module’s external
	interface.

PS.  you know you may be a mathematician if your sentences start with a
	lower-case letter and end with a semicolon;

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-05 20:20   ` Ivan Shmakov
@ 2014-12-06  5:09     ` Stefan Monnier
  2014-12-06 19:17       ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2014-12-06  5:09 UTC (permalink / raw)
  To: 19274

>>> + ;; omit tar-header-checksum (tar-chk-offset) for now
>> Please capitalize and punctuate your comments.
> 	Even the one-line ones?

Yes, we do that for all comments, since this poor little sentence would
feel disrespected otherwise.

> 	BTW, I wonder if it makes sense to split the make-tar-header
> 	form (with all the nil’s there) off tar-new-entry into a new
> 	(tar-new-regular-file-header filename &optional size time)
> 	function?  I guess that’d ease the creation of Tar archives from
> 	Emacs Lisp code; (and I already imagine some uses to that.)

BTW, if you're interested in hacking on tar-mode, I keep dreaming of
plugging it into file-name-handler-alist so you can just visit
/foo/bar.tar.gz/somefile, use dired on it, ...


        Stefan





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06  5:09     ` Stefan Monnier
@ 2014-12-06 19:17       ` Ivan Shmakov
  2014-12-06 19:33         ` Eli Zaretskii
  2014-12-06 23:13         ` Stefan Monnier
  0 siblings, 2 replies; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-06 19:17 UTC (permalink / raw)
  To: 19274

[-- Attachment #1: Type: text/plain, Size: 1552 bytes --]

>>>>> Stefan Monnier <monnier@iro.umontreal.ca> writes:

	Please consider the revised patch MIMEd.

	* tar-mode.el: Allow for adding new archive members.
	(tar-new-regular-file-header, tar--pad-to, tar--put-at)
	(tar-header-serialize): New functions.
	(tar-current-position): Split from tar-current-descriptor.
	(tar-current-descriptor): Use it.
	(tar-new-entry): New command.
	(tar-mode-map): Bind it.

[…]

 >> BTW, I wonder if it makes sense to split the make-tar-header form
 >> (with all the nil’s there) off tar-new-entry into a new
 >> (tar-new-regular-file-header filename &optional size time) function?

	(Done.)

 >> I guess that’d ease the creation of Tar archives from Emacs Lisp
 >> code; (and I already imagine some uses to that.)

 > BTW, if you're interested in hacking on tar-mode, I keep dreaming of
 > plugging it into file-name-handler-alist so you can just visit
 > /foo/bar.tar.gz/somefile, use dired on it, ...

	I’m not all that familiar with file-name-handler-alist, but I
	guess I could check it out.  (Although at this point I’m simply
	interested in creating Tar archives from the contents of Emacs
	buffers, – without having them saved into files, that is.)

	Curiously, what would be the sensible behavior for Emacs when
	the copy of the Tar archive kept in the *tar-data* buffer
	happens to differ to the on-disk state of the respective file?

-- 
FSF associate member #7257  np. Вселенская большая любовь — Гражданская Оборона

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/diff, Size: 6431 bytes --]

--- a/etc/NEWS	2014-11-27 11:36:08 +0000
+++ b/etc/NEWS	2014-12-06 19:03:35 +0000
@@ -340,6 +340,9 @@
 `tildify-ignored-environments-alist' variables (as well as a few
 helper functions) obsolete.
 
+** tar-mode: new `tar-new-entry' command, allowing for new members to
+be added to the archive.
+
 ** Obsolete packages
 
 ---
--- a/lisp/tar-mode.el	2014-08-28 19:18:24 +0000
+++ b/lisp/tar-mode.el	2014-12-06 19:04:02 +0000
@@ -50,9 +50,6 @@
 ;;
 ;; o  chmod should understand "a+x,og-w".
 ;;
-;; o  It's not possible to add a NEW file to a tar archive; not that
-;;    important, but still...
-;;
 ;; o  The code is less efficient that it could be - in a lot of places, I
 ;;    pull a 512-character string out of the buffer and parse it, when I could
 ;;    be parsing it in place, not garbaging a string.  Should redo that.
@@ -369,6 +366,83 @@ write-date, checksum, link-type, and link-name."
 	string)
   (tar-parse-octal-integer string))
 
+(defun tar-new-regular-file-header (filename &optional size time)
+  "Return a Tar header for a regular file.
+The header will lack a proper checksum; use `tar-header-block-checksum'
+to compute one, or request `tar-header-serialize' to do that.
+
+Other tar-mode facilities may also require the data-start header
+field to be set to a valid value.
+
+If SIZE is not given or nil, it defaults to 0.
+If TIME is not given or nil, assume now."
+  (make-tar-header
+   nil
+   filename
+   #o644 0 0 (or size 0)
+   (or time (current-time))
+   nil				; checksum
+   nil nil
+   nil nil nil nil nil))
+
+(defun tar--pad-to (pos)
+  (make-string (+ pos (- (point)) (point-min)) 0))
+
+(defun tar--put-at (pos val)
+  (when val
+    (insert (tar--pad-to pos) val)))
+
+(defun tar-header-serialize (header &optional update-checksum)
+  "Return the serialization of a Tar HEADER as a string.
+This function calls `tar-header-block-check-checksum' to ensure the
+checksum is correct.
+
+When UPDATE-CHECKSUM is non-nil, update HEADER with the newly-computed
+checksum before doing the check."
+  (with-temp-buffer
+    (set-buffer-multibyte nil)
+    (let ((encoded-name
+	   (encode-coding-string (tar-header-name header)
+				 tar-file-name-coding-system)))
+      (unless (< (length encoded-name) 99)
+	;; FIXME: implement it
+	(error "Long file name support is not implemented"))
+      (insert encoded-name))
+    (insert (tar--pad-to tar-mode-offset)
+	    (format "%6o\0 " (logand #o777777 (tar-header-mode header)))
+	    (format "%6o\0 " (logand #o777777 (tar-header-uid  header)))
+	    (format "%6o\0 " (logand #o777777 (tar-header-gid  header))))
+    (insert (tar--pad-to tar-size-offset)
+	    (format "%11o " (tar-header-size header)))
+    (insert (tar--pad-to tar-time-offset)
+	    (tar-octal-time (tar-header-date header))
+	    " ")
+    ;; omit tar-header-checksum (tar-chk-offset) for now
+    (tar--put-at   tar-linkp-offset (tar-header-link-type header))
+    (tar--put-at   tar-link-offset  (tar-header-link-name header))
+    (when (tar-header-magic header)
+      (tar--put-at tar-magic-offset (tar-header-magic header))
+      (tar--put-at tar-uname-offset (tar-header-uname header))
+      (tar--put-at tar-gname-offset (tar-header-gname header))
+      (let ((dmaj (tar-header-dmaj header))
+	    (dmin (tar-header-dmin header)))
+	(tar--put-at tar-dmaj-offset
+		     (and dmaj (format "%7o\0" (logand #o7777777 dmaj))))
+	(tar--put-at tar-dmin-offset
+		     (and dmin (format "%7o\0" (logand #o7777777 dmin))))))
+    (tar--put-at 512 "")
+    (let ((ck (tar-header-block-checksum (buffer-string))))
+      (goto-char (+ (point-min) tar-chk-offset))
+      (delete-char 8)
+      (insert (format "%6o\0 " ck))
+      (when update-checksum
+	(setf (tar-header-checksum header) ck))
+      (tar-header-block-check-checksum (buffer-string)
+				       (tar-header-checksum header)
+				       (tar-header-name header)))
+    ;; .
+    (buffer-string)))
+
 
 (defun tar-header-block-checksum (string)
   "Compute and return a tar-acceptable checksum for this block."
@@ -547,6 +621,7 @@ MODE should be an integer which is a file mode value."
     (define-key map "p" 'tar-previous-line)
     (define-key map "\^P" 'tar-previous-line)
     (define-key map [up] 'tar-previous-line)
+    (define-key map "I" 'tar-new-entry)
     (define-key map "R" 'tar-rename-entry)
     (define-key map "u" 'tar-unflag)
     (define-key map "v" 'tar-view)
@@ -731,10 +806,14 @@ tar-file's buffer."
   (interactive "p")
   (tar-next-line (- arg)))
 
+(defun tar-current-position ()
+  "Return the `tar-parse-info' index for the current line."
+  (count-lines (point-min) (line-beginning-position)))
+
 (defun tar-current-descriptor (&optional noerror)
   "Return the tar-descriptor of the current line, or signals an error."
   ;; I wish lines had plists, like in ZMACS...
-  (or (nth (count-lines (point-min) (line-beginning-position))
+  (or (nth (tar-current-position)
 	   tar-parse-info)
       (if noerror
 	  nil
@@ -948,6 +1027,37 @@ the current tar-entry."
 	(write-region start end to-file nil nil nil t)))
     (message "Copied tar entry %s to %s" name to-file)))
 
+(defun tar-new-entry (filename &optional index)
+  "Insert a new empty regular file before point."
+  (interactive "*sFile name: ")
+  (let* ((buffer  (current-buffer))
+	 (index   (or index (tar-current-position)))
+	 (d-list  (and (not (zerop index))
+		       (nthcdr (+ -1 index) tar-parse-info)))
+	 (pos     (if d-list
+		      (tar-header-data-end (car d-list))
+		    (point-min)))
+	 (new-descriptor
+	  (tar-new-regular-file-header filename)))
+    ;; Update the data buffer; fill the missing descriptor fields.
+    (with-current-buffer tar-data-buffer
+      (goto-char pos)
+      (insert (tar-header-serialize new-descriptor t))
+      (setf  (tar-header-data-start new-descriptor)
+	     (copy-marker (point) nil)))
+    ;; Update tar-parse-info.
+    (if d-list
+	(setcdr d-list     (cons new-descriptor (cdr d-list)))
+      (setq tar-parse-info (cons new-descriptor tar-parse-info)))
+    ;; Update the listing buffer.
+    (save-excursion
+      (goto-char (point-min))
+      (forward-line index)
+      (let ((inhibit-read-only t))
+	(insert (tar-header-block-summarize new-descriptor) ?\n)))
+    ;; .
+    index))
+
 (defun tar-flag-deleted (p &optional unflag)
   "In Tar mode, mark this sub-file to be deleted from the tar file.
 With a prefix argument, mark that many files."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 19:17       ` Ivan Shmakov
@ 2014-12-06 19:33         ` Eli Zaretskii
  2014-12-06 19:45           ` Ivan Shmakov
  2014-12-06 23:13         ` Stefan Monnier
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2014-12-06 19:33 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> From: Ivan Shmakov <ivan@siamics.net>
> Date: Sat, 06 Dec 2014 19:17:16 +0000
> 
> --- a/etc/NEWS	2014-11-27 11:36:08 +0000
> +++ b/etc/NEWS	2014-12-06 19:03:35 +0000
> @@ -340,6 +340,9 @@
>  `tildify-ignored-environments-alist' variables (as well as a few
>  helper functions) obsolete.
>  
> +** tar-mode: new `tar-new-entry' command, allowing for new members to
> +be added to the archive.

How about adding the necessary bits to the Emacs manual?

> +(defun tar-header-serialize (header &optional update-checksum)
> +  "Return the serialization of a Tar HEADER as a string.
> +This function calls `tar-header-block-check-checksum' to ensure the
> +checksum is correct.
> +
> +When UPDATE-CHECKSUM is non-nil, update HEADER with the newly-computed

Not "when", "if".  "When" has an implicit timing reference, which is
not what you mean here.

Thanks.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 19:33         ` Eli Zaretskii
@ 2014-12-06 19:45           ` Ivan Shmakov
  2014-12-06 19:56             ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-06 19:45 UTC (permalink / raw)
  To: 19274

>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 19:17:16 +0000

[…]

 >> ** tar-mode: new `tar-new-entry' command, allowing for new members
 >> to be added to the archive.

 > How about adding the necessary bits to the Emacs manual?

	Sure; what’s the respective .texi file?  (Somehow, I failed to
	find one.)

[…]

 >> When UPDATE-CHECKSUM is non-nil, update HEADER with the
 >> newly-computed

 > Not "when", "if".  "When" has an implicit timing reference, which is
 > not what you mean here.

	ACK.

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 19:45           ` Ivan Shmakov
@ 2014-12-06 19:56             ` Eli Zaretskii
  2014-12-06 20:04               ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2014-12-06 19:56 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> From: Ivan Shmakov <ivan@siamics.net>
> Date: Sat, 06 Dec 2014 19:45:26 +0000
> 
> >>>>> Eli Zaretskii <eliz@gnu.org> writes:
> >>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 19:17:16 +0000
> 
> […]
> 
>  >> ** tar-mode: new `tar-new-entry' command, allowing for new members
>  >> to be added to the archive.
> 
>  > How about adding the necessary bits to the Emacs manual?
> 
> 	Sure; what’s the respective .texi file?  (Somehow, I failed to
> 	find one.)

"fgrep tar-mode doc/emacs/*.texi blames misc.texi.

Thanks.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 19:56             ` Eli Zaretskii
@ 2014-12-06 20:04               ` Ivan Shmakov
  2014-12-06 20:15                 ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-06 20:04 UTC (permalink / raw)
  To: 19274

>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 19:45:26 +0000
>>>>> Eli Zaretskii <eliz@gnu.org> writes:

[…]

 >>> How about adding the necessary bits to the Emacs manual?

 >> Sure; what’s the respective .texi file?  (Somehow, I failed to find
 >> one.)

 > "fgrep tar-mode doc/emacs/*.texi blames misc.texi.

	For me, it only finds ‘tar-mode’ in ‘wordstar-mode’:

$ grep -F -- tar-mode doc/emacs/*.texi 
doc/emacs/ack.texi:@file{tar-mode.el}, which provides simple viewing and editing commands
doc/emacs/misc.texi:@findex wordstar-mode
doc/emacs/misc.texi:@kbd{M-x wordstar-mode} provides a major mode with WordStar-like
$ 

	(And the same for -r --include=\*.texi over doc/ as a whole.)

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 20:04               ` Ivan Shmakov
@ 2014-12-06 20:15                 ` Eli Zaretskii
  2014-12-06 20:50                   ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2014-12-06 20:15 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> From: Ivan Shmakov <ivan@siamics.net>
> Date: Sat, 06 Dec 2014 20:04:46 +0000
> 
> >>>>> Eli Zaretskii <eliz@gnu.org> writes:
> >>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 19:45:26 +0000
> >>>>> Eli Zaretskii <eliz@gnu.org> writes:
> 
> […]
> 
>  >>> How about adding the necessary bits to the Emacs manual?
> 
>  >> Sure; what’s the respective .texi file?  (Somehow, I failed to find
>  >> one.)
> 
>  > "fgrep tar-mode doc/emacs/*.texi blames misc.texi.
> 
> 	For me, it only finds ‘tar-mode’ in ‘wordstar-mode’:

You are right, sorry.  Try this instead:

  fgrep -w Tar doc/emacs/*.texi





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 20:15                 ` Eli Zaretskii
@ 2014-12-06 20:50                   ` Ivan Shmakov
  2014-12-07 16:20                     ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-06 20:50 UTC (permalink / raw)
  To: 19274

[-- Attachment #1: Type: text/plain, Size: 648 bytes --]

>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 20:04:46 +0000
>>>>> Eli Zaretskii <eliz@gnu.org> writes:

[…]

 >>> "fgrep tar-mode doc/emacs/*.texi blames misc.texi.

 >> For me, it only finds ‘tar-mode’ in ‘wordstar-mode’:

 > You are right, sorry.  Try this instead:

 >   fgrep -w Tar doc/emacs/*.texi 

	Now, it makes me wonder if there should be an @findex tar-mode
	along with the @cindices?  (And @findex archive-mode, too.)

	Otherwise, does the patch MIMEd look sane?

	TIA.

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/diff, Size: 911 bytes --]

--- a/doc/emacs/files.texi	2014-06-08 07:41:27 +0000
+++ b/doc/emacs/files.texi	2014-12-06 20:44:44 +0000
@@ -1689,6 +1689,14 @@ likewise.  @kbd{v} extracts a file into a buffer in View mode
 another window, so you could edit the file and operate on the archive
 simultaneously.
 
+  The @kbd{I} key adds a new (regular) file to the archive.  The file
+is initially empty, but can readily be edited using the commands
+above.  The command inserts the new file on the line above the current
+one, so that using it on the topmost line of the Tar buffer makes the
+new file the first one in the archive, and using it on the last line
+(the one after the line describing the last file) makes it the last
+one.
+
   @kbd{d} marks a file for deletion when you later use @kbd{x}, and
 @kbd{u} unmarks a file, as in Dired.  @kbd{C} copies a file from the
 archive to disk and @kbd{R} renames a file within the archive.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 19:17       ` Ivan Shmakov
  2014-12-06 19:33         ` Eli Zaretskii
@ 2014-12-06 23:13         ` Stefan Monnier
  1 sibling, 0 replies; 17+ messages in thread
From: Stefan Monnier @ 2014-12-06 23:13 UTC (permalink / raw)
  To: 19274

> 	Please consider the revised patch MIMEd.

Looks good, thanks,


        Stefan





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-06 20:50                   ` Ivan Shmakov
@ 2014-12-07 16:20                     ` Eli Zaretskii
  2014-12-07 17:47                       ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2014-12-07 16:20 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> From: Ivan Shmakov <ivan@siamics.net>
> Date: Sat, 06 Dec 2014 20:50:36 +0000
> 
>  >   fgrep -w Tar doc/emacs/*.texi 
> 
> 	Now, it makes me wonder if there should be an @findex tar-mode
> 	along with the @cindices?  (And @findex archive-mode, too.)

What, just to help us search for it?  These functions are never
mentioned in that node.

But I don't mind adding the index entries.

(In general, the best way of doing this search is to take note of the
node you are reading in Info, and then search for the corresponding
@node line.)

> 	Otherwise, does the patch MIMEd look sane?

Yes, with one comment; see below.

> +  The @kbd{I} key adds a new (regular) file to the archive.  The file
> +is initially empty, but can readily be edited using the commands
> +above.  The command inserts the new file on the line above the current
> +one, so that using it on the topmost line of the Tar buffer makes the
> +new file the first one in the archive, and using it on the last line
> +(the one after the line describing the last file) makes it the last
> +one.

Instead of the complicated description of "the last line, which is one
line after the last file's line", I'd simply say "at the end of the
buffer".  This is simpler and much more clear, especially to
non-native speakers who might have problems with long and complex
sentences.

Otherwise, it's fine.  Thanks.  (Don't forget to mark the NEWS entry
with "+++" together with installing this change.)





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-07 16:20                     ` Eli Zaretskii
@ 2014-12-07 17:47                       ` Ivan Shmakov
  2014-12-07 17:58                         ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-07 17:47 UTC (permalink / raw)
  To: 19274

[-- Attachment #1: Type: text/plain, Size: 2284 bytes --]

>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>> From: Ivan Shmakov  Date: Sat, 06 Dec 2014 20:50:36 +0000

 >>> fgrep -w Tar doc/emacs/*.texi

 >> Now, it makes me wonder if there should be an @findex tar-mode along
 >> with the @cindices?  (And @findex archive-mode, too.)

 > What, just to help us search for it?  These functions are never
 > mentioned in that node.

 > But I don't mind adding the index entries.

	I guess my idea of a better Emacs manual includes documenting
	all the command names alongside their respective default
	bindings.  Looks like it warrants a separate bug report, though.

 > (In general, the best way of doing this search is to take note of the
 > node you are reading in Info, and then search for the corresponding
 > @node line.)

	In this particular case, I should have tried the command below.

$ grep -irE --include=\*.texi -- '\<tar\>' doc/ 

[…]

 >> The command inserts the new file on the line above the current one,
 >> so that using it on the topmost line of the Tar buffer makes the new
 >> file the first one in the archive, and using it on the last line
 >> (the one after the line describing the last file) makes it the last
 >> one.

 > Instead of the complicated description of "the last line, which is
 > one line after the last file's line", I'd simply say "at the end of
 > the buffer".  This is simpler and much more clear, especially to
 > non-native speakers who might have problems with long and complex
 > sentences.

	Indeed, that’s much better.  Does it make sense to also simplify
	the head of the sentence as follows?  (I believe that “lines”
	are rather just an implementation detail here.)

- The command inserts the new file on the line above the current one,
+ The command inserts the new file before the current one,

 > Otherwise, it's fine.  Thanks.  (Don't forget to mark the NEWS entry
 > with "+++" together with installing this change.)

	Meanwhile, I’ve also simplified tar-header-serialize a bit (at
	the cost of adding a couple of lines to tar--put-at) – and
	hopefully made it more readable at the same time.

	The (once again) revised patch is MIMEd.

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/diff, Size: 7081 bytes --]

--- a/etc/NEWS	2014-11-27 11:36:08 +0000
+++ b/etc/NEWS	2014-12-07 17:31:11 +0000
@@ -340,6 +340,10 @@
 `tildify-ignored-environments-alist' variables (as well as a few
 helper functions) obsolete.
 
++++
+** tar-mode: new `tar-new-entry' command, allowing for new members to
+be added to the archive.
+
 ** Obsolete packages
 
 ---
--- a/doc/emacs/files.texi	2014-06-08 07:41:27 +0000
+++ b/doc/emacs/files.texi	2014-12-07 17:35:34 +0000
@@ -1689,6 +1689,13 @@ @node File Archives
 another window, so you could edit the file and operate on the archive
 simultaneously.
 
+  The @kbd{I} key adds a new (regular) file to the archive.  The file
+is initially empty, but can readily be edited using the commands
+above.  The command inserts the new file on the line above the current
+one, so that using it on the topmost line of the Tar buffer makes the
+new file the first one in the archive, and using it at the end of the
+buffer makes it the last one.
+
   @kbd{d} marks a file for deletion when you later use @kbd{x}, and
 @kbd{u} unmarks a file, as in Dired.  @kbd{C} copies a file from the
 archive to disk and @kbd{R} renames a file within the archive.
--- a/lisp/tar-mode.el	2014-08-28 19:18:24 +0000
+++ b/lisp/tar-mode.el	2014-12-07 17:44:40 +0000
@@ -50,9 +50,6 @@
 ;;
 ;; o  chmod should understand "a+x,og-w".
 ;;
-;; o  It's not possible to add a NEW file to a tar archive; not that
-;;    important, but still...
-;;
 ;; o  The code is less efficient that it could be - in a lot of places, I
 ;;    pull a 512-character string out of the buffer and parse it, when I could
 ;;    be parsing it in place, not garbaging a string.  Should redo that.
@@ -369,6 +366,80 @@
 	string)
   (tar-parse-octal-integer string))
 
+(defun tar-new-regular-file-header (filename &optional size time)
+  "Return a Tar header for a regular file.
+The header will lack a proper checksum; use `tar-header-block-checksum'
+to compute one, or request `tar-header-serialize' to do that.
+
+Other tar-mode facilities may also require the data-start header
+field to be set to a valid value.
+
+If SIZE is not given or nil, it defaults to 0.
+If TIME is not given or nil, assume now."
+  (make-tar-header
+   nil
+   filename
+   #o644 0 0 (or size 0)
+   (or time (current-time))
+   nil				; checksum
+   nil nil
+   nil nil nil nil nil))
+
+(defun tar--pad-to (pos)
+  (make-string (+ pos (- (point)) (point-min)) 0))
+
+(defun tar--put-at (pos val &optional fmt mask)
+  (when val
+    (insert (tar--pad-to pos)
+	    (if fmt
+		(format fmt (if mask (logand mask val) val))
+	      val))))
+
+(defun tar-header-serialize (header &optional update-checksum)
+  "Return the serialization of a Tar HEADER as a string.
+This function calls `tar-header-block-check-checksum' to ensure the
+checksum is correct.
+
+If UPDATE-CHECKSUM is non-nil, update HEADER with the newly-computed
+checksum before doing the check."
+  (with-temp-buffer
+    (set-buffer-multibyte nil)
+    (let ((encoded-name
+	   (encode-coding-string (tar-header-name header)
+				 tar-file-name-coding-system)))
+      (unless (< (length encoded-name) 99)
+	;; FIXME: Implement it.
+	(error "Long file name support is not implemented"))
+      (insert encoded-name))
+    (tar--put-at tar-mode-offset (tar-header-mode header) "%6o\0 " #o777777)
+    (tar--put-at tar-uid-offset  (tar-header-uid  header) "%6o\0 " #o777777)
+    (tar--put-at tar-gid-offset  (tar-header-gid  header) "%6o\0 " #o777777)
+    (tar--put-at tar-size-offset (tar-header-size header) "%11o ")
+    (insert (tar--pad-to tar-time-offset)
+	    (tar-octal-time (tar-header-date header))
+	    " ")
+    ;; Omit tar-header-checksum (tar-chk-offset) for now.
+    (tar--put-at   tar-linkp-offset (tar-header-link-type header))
+    (tar--put-at   tar-link-offset  (tar-header-link-name header))
+    (when (tar-header-magic header)
+      (tar--put-at tar-magic-offset (tar-header-magic header))
+      (tar--put-at tar-uname-offset (tar-header-uname header))
+      (tar--put-at tar-gname-offset (tar-header-gname header))
+      (tar--put-at tar-dmaj-offset (tar-header-dmaj header) "%7o\0" #o7777777)
+      (tar--put-at tar-dmin-offset (tar-header-dmin header) "%7o\0" #o7777777))
+    (tar--put-at 512 "")
+    (let ((ck (tar-header-block-checksum (buffer-string))))
+      (goto-char (+ (point-min) tar-chk-offset))
+      (delete-char 8)
+      (insert (format "%6o\0 " ck))
+      (when update-checksum
+	(setf (tar-header-checksum header) ck))
+      (tar-header-block-check-checksum (buffer-string)
+				       (tar-header-checksum header)
+				       (tar-header-name header)))
+    ;; .
+    (buffer-string)))
+
 
 (defun tar-header-block-checksum (string)
   "Compute and return a tar-acceptable checksum for this block."
@@ -547,6 +618,7 @@ defvar tar-mode-map
     (define-key map "p" 'tar-previous-line)
     (define-key map "\^P" 'tar-previous-line)
     (define-key map [up] 'tar-previous-line)
+    (define-key map "I" 'tar-new-entry)
     (define-key map "R" 'tar-rename-entry)
     (define-key map "u" 'tar-unflag)
     (define-key map "v" 'tar-view)
@@ -731,10 +803,14 @@
   (interactive "p")
   (tar-next-line (- arg)))
 
+(defun tar-current-position ()
+  "Return the `tar-parse-info' index for the current line."
+  (count-lines (point-min) (line-beginning-position)))
+
 (defun tar-current-descriptor (&optional noerror)
   "Return the tar-descriptor of the current line, or signals an error."
   ;; I wish lines had plists, like in ZMACS...
-  (or (nth (count-lines (point-min) (line-beginning-position))
+  (or (nth (tar-current-position)
 	   tar-parse-info)
       (if noerror
 	  nil
@@ -948,6 +1024,37 @@
 	(write-region start end to-file nil nil nil t)))
     (message "Copied tar entry %s to %s" name to-file)))
 
+(defun tar-new-entry (filename &optional index)
+  "Insert a new empty regular file before point."
+  (interactive "*sFile name: ")
+  (let* ((buffer  (current-buffer))
+	 (index   (or index (tar-current-position)))
+	 (d-list  (and (not (zerop index))
+		       (nthcdr (+ -1 index) tar-parse-info)))
+	 (pos     (if d-list
+		      (tar-header-data-end (car d-list))
+		    (point-min)))
+	 (new-descriptor
+	  (tar-new-regular-file-header filename)))
+    ;; Update the data buffer; fill the missing descriptor fields.
+    (with-current-buffer tar-data-buffer
+      (goto-char pos)
+      (insert (tar-header-serialize new-descriptor t))
+      (setf  (tar-header-data-start new-descriptor)
+	     (copy-marker (point) nil)))
+    ;; Update tar-parse-info.
+    (if d-list
+	(setcdr d-list     (cons new-descriptor (cdr d-list)))
+      (setq tar-parse-info (cons new-descriptor tar-parse-info)))
+    ;; Update the listing buffer.
+    (save-excursion
+      (goto-char (point-min))
+      (forward-line index)
+      (let ((inhibit-read-only t))
+	(insert (tar-header-block-summarize new-descriptor) ?\n)))
+    ;; .
+    index))
+
 (defun tar-flag-deleted (p &optional unflag)
   "In Tar mode, mark this sub-file to be deleted from the tar file.
 With a prefix argument, mark that many files."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-07 17:47                       ` Ivan Shmakov
@ 2014-12-07 17:58                         ` Eli Zaretskii
  2014-12-07 18:07                           ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2014-12-07 17:58 UTC (permalink / raw)
  To: Ivan Shmakov; +Cc: 19274

> From: Ivan Shmakov <ivan@siamics.net>
> Date: Sun, 07 Dec 2014 17:47:30 +0000
> 
>  > (In general, the best way of doing this search is to take note of the
>  > node you are reading in Info, and then search for the corresponding
>  > @node line.)
> 
> 	In this particular case, I should have tried the command below.
> 
> $ grep -irE --include=\*.texi -- '\<tar\>' doc/ 

What I meant is this:

  fgrep "@node File Archives" doc/emacs/*.texi

>  > Instead of the complicated description of "the last line, which is
>  > one line after the last file's line", I'd simply say "at the end of
>  > the buffer".  This is simpler and much more clear, especially to
>  > non-native speakers who might have problems with long and complex
>  > sentences.
> 
> 	Indeed, that’s much better.  Does it make sense to also simplify
> 	the head of the sentence as follows?  (I believe that “lines”
> 	are rather just an implementation detail here.)
> 
> - The command inserts the new file on the line above the current one,
> + The command inserts the new file before the current one,

Yes, that's better.

Thanks.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-07 17:58                         ` Eli Zaretskii
@ 2014-12-07 18:07                           ` Ivan Shmakov
  2015-01-27 22:04                             ` Ivan Shmakov
  0 siblings, 1 reply; 17+ messages in thread
From: Ivan Shmakov @ 2014-12-07 18:07 UTC (permalink / raw)
  To: 19274

[-- Attachment #1: Type: text/plain, Size: 741 bytes --]

>>>>> Eli Zaretskii <eliz@gnu.org> writes:
>>>>> From: Ivan Shmakov  Date: Sun, 07 Dec 2014 17:47:30 +0000

[…]

 >> Does it make sense to also simplify the head of the sentence as
 >> follows?  (I believe that “lines” are rather just an implementation
 >> detail here.)

 >> - The command inserts the new file on the line above the current
 >>   one,
 >> + The command inserts the new file before the current one,

 > Yes, that's better.

	The revised patch for doc/emacs/files.texi is MIMEd.  (The rest
	remains the same [1].)

[1] news:871tobl5cd.fsf@violet.siamics.net
    http://permalink.gmane.org/gmane.emacs.bugs/96948

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/diff, Size: 815 bytes --]

--- a/doc/emacs/files.texi	2014-06-08 07:41:27 +0000
+++ b/doc/emacs/files.texi	2014-12-07 18:05:31 +0000
@@ -1689,6 +1689,13 @@ @node File Archives
 another window, so you could edit the file and operate on the archive
 simultaneously.
 
+  The @kbd{I} key adds a new (regular) file to the archive.  The file
+is initially empty, but can readily be edited using the commands
+above.  The command inserts the new file before the current one, so
+that using it on the topmost line of the Tar buffer makes the new file
+the first one in the archive, and using it at the end of the buffer
+makes it the last one.
+
   @kbd{d} marks a file for deletion when you later use @kbd{x}, and
 @kbd{u} unmarks a file, as in Dired.  @kbd{C} copies a file from the
 archive to disk and @kbd{R} renames a file within the archive.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#19274: tar-mode.el: allow for adding new archive members
  2014-12-07 18:07                           ` Ivan Shmakov
@ 2015-01-27 22:04                             ` Ivan Shmakov
  0 siblings, 0 replies; 17+ messages in thread
From: Ivan Shmakov @ 2015-01-27 22:04 UTC (permalink / raw)
  To: 19274-done

[-- Attachment #1: Type: text/plain, Size: 386 bytes --]

Version: 25.1

>>>>> Ivan Shmakov <ivan@siamics.net> writes:

[…]

 > The revised patch for doc/emacs/files.texi is MIMEd.  (The rest
 > remains the same [1].)

 > [1] news:871tobl5cd.fsf@violet.siamics.net
 >     http://permalink.gmane.org/gmane.emacs.bugs/96948

	Pushed; closing.

-- 
FSF associate member #7257  http://boycottsystemd.org/  … 3013 B6A0 230E 334A

[-- Attachment #2: Type: text/plain, Size: 586 bytes --]

commit a56eab8259568ea1389e972623e46359e73c0233

    Allow for adding new members to Tar archives.

    * lisp/tar-mode.el: Allow for adding new archive members.
    (tar-new-regular-file-header, tar--pad-to, tar--put-at)
    (tar-header-serialize): New functions.
    (tar-current-position): Split from tar-current-descriptor.
    (tar-current-descriptor): Use it.
    (tar-new-entry): New command.
    (tar-mode-map): Bind it.
    * doc/emacs/files.texi (File Archives): Document "I" for tar-new-entry.
    * etc/NEWS: Mention the new tar-new-entry command.

    Fixes: debbugs:19274

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-01-27 22:04 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-04 21:17 bug#19274: tar-mode.el: allow for adding new archive members Ivan Shmakov
2014-12-05  2:10 ` Stefan Monnier
2014-12-05 20:20   ` Ivan Shmakov
2014-12-06  5:09     ` Stefan Monnier
2014-12-06 19:17       ` Ivan Shmakov
2014-12-06 19:33         ` Eli Zaretskii
2014-12-06 19:45           ` Ivan Shmakov
2014-12-06 19:56             ` Eli Zaretskii
2014-12-06 20:04               ` Ivan Shmakov
2014-12-06 20:15                 ` Eli Zaretskii
2014-12-06 20:50                   ` Ivan Shmakov
2014-12-07 16:20                     ` Eli Zaretskii
2014-12-07 17:47                       ` Ivan Shmakov
2014-12-07 17:58                         ` Eli Zaretskii
2014-12-07 18:07                           ` Ivan Shmakov
2015-01-27 22:04                             ` Ivan Shmakov
2014-12-06 23:13         ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).