Re: [PATCH] Function for copying field values

2015-09-05 Thread Eric Abrahamsen
Eric Abrahamsen  writes:

> "Roland Winkler"  writes:
>
>> On Sat Sep 5 2015 Roland Winkler wrote:
>>> On Thu Sep 3 2015 Eric Abrahamsen wrote:
>>> > Basically it does what it says: if point is on a record name, the
>>> > whole record is copied, like before. If point is on a particular
>>> > field, the value (but not label) of that field is copied.
>>> 
>>> I am just trying to understand a typical usage pattern for the
>>> extended code.  I understand that it can make sense for a single
>>> record to grab the value of only one field.  Yet what would this be
>>> good for with multiple records?  It seems to me that with multiple
>>> records, this would make sense only if it included also the name of
>>> the record.
>>
>> One more thought: Why treat names special?  The only field, where it
>> appears to make sense to grab its value from multiple records
>> without including some "identifier", would be the name field.
>>
>> Then, treating all fields the same way might work best with a
>> separate command bbdb-copy-field-as-kill instead of extending the
>> functionality of bbdb-copy-records-as-kill.  The prefix arg could
>> then possibly be used in a different way: with prefix arg the
>> command could also grab the name field.  (Or: include the name field
>> whenever this command operates on more than one record?)
>
> Yup, I asked myself many of these same questions, and I'm not really
> sure why I settled on the current behavior. All I really need is a quick
> way to copy and share addresses, phone numbers, and mails from my
> contacts -- usually just one, and I don't need the name attached. Beyond
> that, I'm happy to work this however seems most useful.
>
> Your last suggestion seems as good as anything I could come up with: why
> don't we do a separate function that only copies fields. If the name was
> included automatically when copying multiple records, then the prefix
> arg could be saved for selecting members from a list value, like it does
> now. Mostly that's useful when people have a million different email
> addresses.

Okay, here's a new version of the patch that does that.

Eric

>From c54d8b7c24a98d5fb914683715467db2c2407364 Mon Sep 17 00:00:00 2001
From: Eric Abrahamsen 
Date: Sun, 6 Sep 2015 14:50:56 +0800
Subject: [PATCH] bbdb-com.el: New function for copying field values

* lisp/bbdb-com.el (bbdb-copy-fields-as-kill): New function copies value
   of field under point to the kill ring.
---
 lisp/bbdb-com.el | 72 
 1 file changed, 72 insertions(+)

diff --git a/lisp/bbdb-com.el b/lisp/bbdb-com.el
index 6074bab..13dae6a 100644
--- a/lisp/bbdb-com.el
+++ b/lisp/bbdb-com.el
@@ -2563,6 +2563,78 @@ Interactively, use BBDB prefix \
"[ \t\n]*\\'" "\n"
(mapconcat 'identity (nreverse drec) "")
 
+;;;###autoload
+(defun bbdb-copy-fields-as-kill (records &optional which)
+  "Copy field values from displayed RECORDS to kill ring.
+
+Interactively, use BBDB prefix \
+[bbdb-do-all-records], see
+`bbdb-do-all-records'.  The value of the field under point will
+be copied for all records, and prefixed with the name of the
+contact.  If point is on a field with a label, only field values
+with the same label will be copied.
+
+If a numeric prefix is given, and the field being copied has a
+list value, copy the list item at the index of the prefix
+argument."
+  (interactive (list (bbdb-do-records t)
+		 (and current-prefix-arg
+  (prefix-numeric-value current-prefix-arg
+  (let* ((field (bbdb-current-field))
+	 (field-name (car-safe field))
+	 (field-type (when field-name
+		   (cond
+			((eq 'xfields field-name)
+			 (caadr field))
+			((memq field-name '(phone address))
+			 (cons field-name (aref (cadr field) 0)))
+			(t field-name
+	 (single (= 1 (length records)))
+	 drec)
+(dolist (record (bbdb-record-list records t))
+  (let ((val (bbdb-record-field
+		  (car record)
+		  (cond ((symbolp field-type)
+			 field-type)
+			((consp field-type)
+			 (car field-type))
+	(when (memq field-name '(phone address))
+	  (dolist (v val)
+	;; Only take phones and addresses with the proper label.
+	(when (equal (aref v 0) (cdr field-type))
+	  (setq val v)))
+	  ;; Format phones and addresses properly.
+	  (when val
+	(setq val
+		  (if (eq field-name 'phone)
+		  (bbdb-phone-string val)
+		(bbdb-format-address-default val)
+	;; Prefix arg `which' asks for a specific element from a
+	;; list value
+	(when (and val
+		   (listp val))
+	  (setq val
+		(if which
+		(nth which val)
+		  (mapconcat
+		   (lambda (v)
+		 (concat
+		  v (nth 1 (or (cdr (assq field bbdb-separator-alist))
+	bbdb-default-separator
+		   val "\n"
+	(unless single
+	  (setq val (cons (bbdb-record-name (car record)) val)))
+	(when val
+	  (push val drec
+(kill-new (replace-regexp-in-string
+   "[ \t\n]*\\'" "\n"
+   (map

Re: [PATCH] Function for copying field values

2015-09-05 Thread Eric Abrahamsen
"Roland Winkler"  writes:

> On Sat Sep 5 2015 Roland Winkler wrote:
>> On Thu Sep 3 2015 Eric Abrahamsen wrote:
>> > Basically it does what it says: if point is on a record name, the
>> > whole record is copied, like before. If point is on a particular
>> > field, the value (but not label) of that field is copied.
>> 
>> I am just trying to understand a typical usage pattern for the
>> extended code.  I understand that it can make sense for a single
>> record to grab the value of only one field.  Yet what would this be
>> good for with multiple records?  It seems to me that with multiple
>> records, this would make sense only if it included also the name of
>> the record.
>
> One more thought: Why treat names special?  The only field, where it
> appears to make sense to grab its value from multiple records
> without including some "identifier", would be the name field.
>
> Then, treating all fields the same way might work best with a
> separate command bbdb-copy-field-as-kill instead of extending the
> functionality of bbdb-copy-records-as-kill.  The prefix arg could
> then possibly be used in a different way: with prefix arg the
> command could also grab the name field.  (Or: include the name field
> whenever this command operates on more than one record?)

Yup, I asked myself many of these same questions, and I'm not really
sure why I settled on the current behavior. All I really need is a quick
way to copy and share addresses, phone numbers, and mails from my
contacts -- usually just one, and I don't need the name attached. Beyond
that, I'm happy to work this however seems most useful.

Your last suggestion seems as good as anything I could come up with: why
don't we do a separate function that only copies fields. If the name was
included automatically when copying multiple records, then the prefix
arg could be saved for selecting members from a list value, like it does
now. Mostly that's useful when people have a million different email
addresses.

E


--
___
bbdb-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bbdb-info
BBDB Home Page: http://bbdb.sourceforge.net/


Re: [PATCH] Function for copying field values

2015-09-05 Thread Roland Winkler
On Sat Sep 5 2015 Roland Winkler wrote:
> On Thu Sep 3 2015 Eric Abrahamsen wrote:
> > Basically it does what it says: if point is on a record name, the
> > whole record is copied, like before. If point is on a particular
> > field, the value (but not label) of that field is copied.
> 
> I am just trying to understand a typical usage pattern for the
> extended code.  I understand that it can make sense for a single
> record to grab the value of only one field.  Yet what would this be
> good for with multiple records?  It seems to me that with multiple
> records, this would make sense only if it included also the name of
> the record.

One more thought: Why treat names special?  The only field, where it
appears to make sense to grab its value from multiple records
without including some "identifier", would be the name field.

Then, treating all fields the same way might work best with a
separate command bbdb-copy-field-as-kill instead of extending the
functionality of bbdb-copy-records-as-kill.  The prefix arg could
then possibly be used in a different way: with prefix arg the
command could also grab the name field.  (Or: include the name field
whenever this command operates on more than one record?)

Roland

--
___
bbdb-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bbdb-info
BBDB Home Page: http://bbdb.sourceforge.net/


Re: [PATCH] Function for copying field values

2015-09-05 Thread Roland Winkler
On Thu Sep 3 2015 Eric Abrahamsen wrote:
> Basically it does what it says: if point is on a record name, the
> whole record is copied, like before. If point is on a particular
> field, the value (but not label) of that field is copied.

I am just trying to understand a typical usage pattern for the
extended code.  I understand that it can make sense for a single
record to grab the value of only one field.  Yet what would this be
good for with multiple records?  It seems to me that with multiple
records, this would make sense only if it included also the name of
the record.

Roland

--
___
bbdb-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bbdb-info
BBDB Home Page: http://bbdb.sourceforge.net/


[PATCH] Function for copying field values

2015-09-02 Thread Eric Abrahamsen
I've always wanted a function for easily copying the values of record
fields.

The attached patch replaces the `bbdb-copy-records-as-kill' function
with a new function, `bbdb-copy-records-or-fields-as-kill'.

Basically it does what it says: if point is on a record name, the whole
record is copied, like before. If point is on a particular field, the
value (but not label) of that field is copied.

If the "*" prefix is given, the field value is copied from all records.
If point is on a field that has a label (ie phones or addresses), only
phones/addresses with the same label are copied from other records.

Lastly, a numeric prefix argument will select the corresponding item
from a field with a list value. If the field under point isn't a list,
the argument is ignored.

The implementation, while it seems to work just fine, is pretty ugly,
particularly working around the various types and labels. I would love
to know if this could be cleared up somehow.

Also I just realized I didn't make a ChangeLog note -- if this patch is
acceptable, I can send another version with the note included.

Thanks,
Eric



>From 195e25433ecc4c092f25b1f71c59d2749a954045 Mon Sep 17 00:00:00 2001
From: Eric Abrahamsen 
Date: Thu, 3 Sep 2015 14:25:30 +0800
Subject: [PATCH] New function for copying value of record fields

* lisp/bbdb-com.el (bbdb-copy-records-or-fields-as-kill): Replace old
  function `bbdb-copy-records-as-kill' with new function
  `bbdb-copy-records-or-fields-as-kill'.

* lisp/bbdb.el (bbdb-mode-map): Add new function to `bbdb-mode-map'.
---
 lisp/bbdb-com.el | 79 +---
 lisp/bbdb.el |  2 +-
 2 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/lisp/bbdb-com.el b/lisp/bbdb-com.el
index 6074bab..8137f22 100644
--- a/lisp/bbdb-com.el
+++ b/lisp/bbdb-com.el
@@ -2548,20 +2548,81 @@ Default is the first URL."
 ;;; Copy to kill ring
 
 ;;;###autoload
-(defun bbdb-copy-records-as-kill (records)
+(defun bbdb-copy-records-or-fields-as-kill (records &optional which)
   "Copy displayed RECORDS to kill ring.
+
+If point is on the record name, copy the whole record.  If point
+is on a particular field, copy only the value of that field.
+
 Interactively, use BBDB prefix \
-[bbdb-do-all-records], see `bbdb-do-all-records'."
-  (interactive (list (bbdb-do-records t)))
-  (let (drec marker)
+[bbdb-do-all-records], see
+`bbdb-do-all-records'.  If point is on a record name, all records
+will be copied.  If point is on a record field, the value of this
+field for all records will be copied.  If point is on a field
+with a label, only field values with the same label will be
+copied.
+
+If a numeric prefix is given, and the field being copied has a
+list value, copy the list item at the index of the prefix
+argument."
+  (interactive (list (bbdb-do-records t)
+		 (and current-prefix-arg
+  (prefix-numeric-value current-prefix-arg
+  (let* ((field (bbdb-current-field))
+	 (field-name (car-safe field))
+	 (field-type (when field-name
+		   (cond
+			((eq 'xfields field-name)
+			 (caadr field))
+			((memq field-name '(phone address))
+			 (cons field-name (aref (cadr field) 0)))
+			(t field-name
+	 drec)
 (dolist (record (bbdb-record-list records t))
-  (push (buffer-substring (nth 2 record)
-  (or (nth 2 (car (cdr (memq record bbdb-records
-  (point-max)))
-drec))
+  (if (or (eq field-name 'name)
+	  (not field-name))
+	  ;; Copy the whole record.
+	  (push (buffer-substring (nth 2 record)
+  (or (nth 2 (car (cdr (memq record bbdb-records
+  (point-max)))
+		drec)
+	;; Or just the one field.
+	(let ((val (bbdb-record-field
+		(car record)
+		(cond ((symbolp field-type)
+			   field-type)
+			  ((consp field-type)
+			   (car field-type))
+	  (when (memq field-name '(phone address))
+	(dolist (v val)
+	  ;; Only take phones and addresses with the proper label.
+	  (setq val
+		(when (equal (aref v 0) (cdr field-type))
+		  v)))
+	;; Format phones and addresses properly.
+	(when val
+	  (setq val
+		(if (eq field-name 'phone)
+			(bbdb-phone-string val)
+		  (bbdb-format-address-default val)
+	  ;; Prefix arg `which' asks for a specific element from a
+	  ;; list value
+	  (when (and which
+		 (listp val))
+	(setq val (nth which val)))
+	  (when val
+	(push val drec)
 (kill-new (replace-regexp-in-string
"[ \t\n]*\\'" "\n"
-   (mapconcat 'identity (nreverse drec) "")
+   (mapconcat (lambda (v)
+			(if (stringp v)
+v
+			  (mapconcat #'identity
+	 v
+	 (nth 1 (or (cdr (assq field bbdb-separator-alist))
+		bbdb-default-separator)
+			  (nreverse drec) "\n")))
+(message "Copied to kill ring")))
 
 ;;; Help and documentation
 
diff --git a/lisp/bbdb.el b/lisp/bbdb.el
index