Re: [O] limitations of hard-coded field separator removed

2012-03-27 Thread Bastien
Hi Andreas,

Andreas Röhler andreas.roeh...@easy-emacs.de writes:

 attached a org-table-import.patch

Thanks for this patch.

I test it against latest master and got this error:

,
| Debugger entered--Lisp error: (wrong-type-argument stringp nil)
|   re-search-forward(nil #marker at 57 in tst.org t)
|   (while (re-search-forward separator end t) (replace-match  |  t t))
|   (let* ((beg (min beg0 end0)) (end (copy-marker (max beg0 end0))) (separator 
(cond ((and separator (stringp separator)) separator) ((eq 4 
(prefix-numeric-value separator)) (read-from-minibuffer Separator char: ) 
(goto-char beg) (unless separator (setq separator (org-guess-separator))) 
(goto-char beg) (while (re-search-forward separator end t) (replace-match  |  
t t)) (goto-char beg) (org-table-align))
|   org-table-convert-region(14 57 nil)
|   call-interactively(org-table-convert-region t nil)
|   execute-extended-command(nil)
|   call-interactively(execute-extended-command nil nil)
`

Beside this problem...

 removes limitations of hard-coded separator char(s).
 `org-guess-separator' accepts and detects all chars as field separators.
 It works based on the assumption, that char looked for appears in equal
 number at each row.

This looks clever, but is it safe?  E.g. if cells of the table are
surrounded by double-quotes, you'll have the same number of quotes in
each row, but the double-quote char by itself is _not_ the separator.

So I'm not sure about this heuristics -- want to ear/test more.

 Also a default value
 `org-table-import-default-separator' should make
 guessing faster in some cases.

That an easier way and I would favor it: keep the current behavior, 
but add an option for a list of separators that the user can set.  
Org would then test this list sequentially.  

What do you think?

-- 
 Bastien



[O] limitations of hard-coded field separator removed

2012-02-23 Thread Andreas Röhler

Hi,

attached a
org-table-import.patch

removes limitations of hard-coded separator char(s).
`org-guess-separator' accepts and detects all chars as field separators.
It works based on the assumption, that char looked for appears in equal 
number at each row.


Also a default value
`org-table-import-default-separator' should make
guessing faster in some cases.

Best regards,

Andreas

--
http://launchpad.net/python-mode
http://launchpad.net/s-x-emacs-werkstatt/

diff --git a/lisp/org-table.el b/lisp/org-table.el
index 39cddab..6ad572b 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -334,6 +334,11 @@ available parameters.
   :group 'org-table-import-export
   :type 'string)
 
+(defcustom org-table-import-default-separator \t
+  `org-table-import' may specify that value, avoid guessing.
+  :group 'org-table-import-export
+  :type 'string)
+
 (defconst org-table-auto-recalculate-regexp ^[ \t]*| *# *\\(|\\|$\\)
   Detects a table line marked for automatic recalculation.)
 (defconst org-table-recalculate-regexp ^[ \t]*| *[#*] *\\(|\\|$\\)
@@ -474,71 +479,72 @@ SIZE is a string Columns x Rows like for example \3x2\.
 	  (goto-char pos)))
 (org-table-align)))
 
+(defun org-guess-separator ()
+  Guess the separator char of a given table.
+
+Works based on the assumption, that char looked for appears in equal numbers at each row. 
+  (interactive)
+  (save-excursion
+(let ((orig (point))
+  char erg matches done pos first second)
+  (beginning-of-line)
+  ;; look first for `org-table-import-default-separator'
+  (when (re-search-forward org-table-import-default-separator nil t 1)
+(setq erg (org-guess-separator-intern)))
+  (unless erg
+(goto-char orig)
+(when (re-search-forward [[:punct:][:blank:]] nil t 1)
+  (setq erg (org-guess-separator-intern
+  ;; maybe neither default nor of character-class punct
+  (unless erg
+(goto-char orig)
+
+(setq erg (org-guess-separator-intern)))
+  (when (interactive-p) (if (string= \t erg)
+(message %s \\t)
+  (message %s erg)))
+  erg)))
+
+(defun org-guess-separator-intern ()
+  (let (erg)
+(while (and (not (eolp)) (not done))
+  (setq pos (point))
+  (setq char (progn (or (looking-back .)(looking-at .)) (match-string-no-properties 0)))
+  (setq matches (count-matches char (line-beginning-position) (line-end-position)))
+  (forward-line 1)
+  (if (eq matches (count-matches char (line-beginning-position) (line-end-position)))
+  (progn
+(setq done t)
+(setq erg char))
+(goto-char pos)
+(forward-char 1)))
+erg))
+
 (defun org-table-convert-region (beg0 end0 optional separator)
   Convert region to a table.
-The region goes from BEG0 to END0, but these borders will be moved
-slightly, to make sure a beginning of line in the first line is included.
-
-SEPARATOR specifies the field separator in the lines.  It can have the
-following values:
-
-'(4) Use the comma as a field separator
-'(16)Use a TAB as field separator
-integer  When a number, use that many spaces as field separator
-nil  When nil, the command tries to be smart and figure out the
- separator in the following way:
- - when each line contains a TAB, assume TAB-separated material
- - when each line contains a comma, assume CSV material
- - else, assume one or more SPACE characters as separator.
-  (interactive rP)
+
+Optional arg SEPARATOR prompts user to specify the separator char. 
+  (interactive r\nP)
   (let* ((beg (min beg0 end0))
-	 (end (max beg0 end0))
-	 re)
+	 (end (copy-marker (max beg0 end0)))
+	 (separator (cond ((and separator (stringp separator))
+			   separator)
+			  ((eq 4 (prefix-numeric-value separator))
+			   (read-from-minibuffer Separator char: )
 (goto-char beg)
-(beginning-of-line 1)
-(setq beg (move-marker (make-marker) (point)))
-(goto-char end)
-(if (bolp) (backward-char 1) (end-of-line 1))
-(setq end (move-marker (make-marker) (point)))
-;; Get the right field separator
-(unless separator
-  (goto-char beg)
-  (setq separator
-	(cond
-	 ((not (re-search-forward ^[^\n\t]+$ end t)) '(16))
-	 ((not (re-search-forward ^[^\n,]+$ end t)) '(4))
-	 (t 1
+(unless separator (setq separator (org-guess-separator)))
 (goto-char beg)
-(if (equal separator '(4))
-	(while ( (point) end)
-	  ;; parse the csv stuff
-	  (cond
-	   ((looking-at ^) (insert | ))
-	   ((looking-at [ \t]*$) (replace-match  |) (beginning-of-line 2))
-	   ((looking-at [ \t]*\\\([^\\n]*\\)\)
-	(replace-match \\1)
-	(if (looking-at \) (insert \)))
-	   ((looking-at [^,\n]+) (goto-char (match-end 0)))
-	   ((looking-at [ \t]*,) (replace-match  | ))
-	   (t (beginning-of-line 2
-  (setq re (cond
-		((equal separator '(4)) ^\\|\?[ \t]*,[ \t]*\?)
-		((equal