macro for deleting selected rows from org table - emacs

I have some org table with 5 columns and 100 rows.
I would like to delete all those rows with field $3="away".
Below is the function that should do the following. Unfortunately I do not know how to convert org table that is created with (org-table-to-lisp), back to text table into my buffer.
(defun org-table-tests ()
"acts on balance table itself"
(interactive)
(save-excursion
(unless (org-table-p)
(error
"You are not in an org-table."))
(goto-char (org-table-begin))
(let (out-tbl
(tbl-list (org-table-to-lisp)))
(while
(let ((row-list (car tbl-list)))
(cond ((and
(listp row-list)
;; do not copy "away" (3rd column) lines containing folliwng:
(string-match "away" (nth 2 row-list)))
;; just skip copying to new table
)
(t (setq out-tbl (cons row-list out-tbl))))
(setq tbl-list (cdr tbl-list))))
;;(orgtbl-to-generic out-tbl) <---------- QUESTION: which function to use to convert back to table in text format.
)))
... or maybe there is a better way for doing such tasks with orgtbl mode?

Since your main question was answered, here's now a solution that doesn't rely on converting to lisp and back :
(defun org-table-tests ()
(interactive)
(save-excursion
(unless (org-table-p)
(error "You are not in an org-table."))
(goto-char (org-table-begin))
(while (org-table-p)
(if (string-match "away" (save-excursion (org-table-get-field 3)))
(delete-region (point) (progn (forward-line) (point)))
(forward-line)))))

Have a look at org-listtable-to-string. It's the reverse of org-table-to-lisp.
Also have a look at this screencast to see how
I've found the solution in under a minute (just grepped for "to table" in org's code base, basically).

If you just want to remove row where $3=="away", following commands are useful. But I don't know why it works.
ESC M-<
M-x flush-lines
RET
^[|][^|]*[|][^|
]*[|] away [|]
RET
Input:
| 1 | 2 | 3 | 4 | 5 |
|------+------+------+------+------|
| away | 12 | 13 | 14 | away |
| 21 | 22 | away | 24 | 25 |
| 31 | away | 33 | away | 35 |
Output:
| 1 | 2 | 3 | 4 | 5 |
|------+------+------+------+------|
| away | 12 | 13 | 14 | away |
| 31 | away | 33 | away | 35 |

Related

orgmode region to table

I have a region:
Items Quantity Amount
"Item A" 423 63
"Item B and C" 27 169
"Item D " 6 199
I would like to create org-table of the above region:
|Items | Quantity| Amount|
----------------|------------------
|"Item A" | 423 | 63 |
|"Item A and C" | 27 | 169 |
|"Item D" | 6 | 199 |
The current suggestion is to select the region and use C-c | to create the table but this creates a table based on spaces between the elements. It is not able to group the items column. Is there a way I can group
You can write your own Emacs Lisp function which will convert all the white-chars (not only spaces) between the two sexp and replace them with , in the currently active region.
(defun my/convert-region ()
(interactive)
(save-window-excursion
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(forward-sexp)
(while (< (point) (buffer-end 1))
(let ((beg (point)))
(if (= (point) (line-end-position))
(forward-char)
(progn
(forward-sexp)
(backward-word)
(delete-region beg (point)))
(insert ",")))
(forward-sexp))
(goto-char (point-min))
(widen)))
I checked this on such active region:
Items Quantity Amount
"Item A" 423 63
"Item B and C" 27 169
"Item D " 6 199
After running M-x my/convert-region it was changed to:
Items,Quantity,Amount
"Item A",423,63
"Item B and C",27,169
"Item D ",6,199
You can add this function to your config file and bind it to some keys.
If you want this function to convert this region to the org-table in the same function just add org-table-convert-region call.
(defun my/convert-region-to-org-table ()
(interactive)
(save-window-excursion
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(forward-sexp)
(while (< (point) (buffer-end 1))
(let ((beg (point)))
(if (= (point) (line-end-position))
(forward-char)
(progn
(forward-sexp)
(backward-word)
(delete-region beg (point)))
(insert ",")))
(forward-sexp))
(org-table-convert-region (point-min) (point-max) '(4))
(goto-char (point-min))
(widen)))
For the same input:
Items Quantity Amount
"Item A" 423 63
"Item B and C" 27 169
"Item D " 6 199
I got the following result:
| Items | Quantity | Amount |
| Item A | 423 | 63 |
| Item B and C | 27 | 169 |
| Item D | 6 | 199 |
Unfortunately the quotation marks are being removed by org-mode during the conversion.
(defun my/convert-region-to-org-table-with-header ()
(interactive)
(save-window-excursion
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(forward-sexp)
(while (< (point) (buffer-end 1))
(let ((beg (point)))
(if (= (point) (line-end-position))
(forward-char)
(progn
(forward-sexp)
(backward-word)
(delete-region beg (point)))
(insert ",")))
(forward-sexp))
(org-table-convert-region (point-min) (point-max) '(4))
(goto-char (point-min))
(org-ctrl-c-minus)
(widen)))
Then the output will look like this:
| Items | Quantity | Amount |
|--------------+----------+--------|
| Item A | 423 | 63 |
| Item B and C | 27 | 169 |
| Item D | 6 | 199 |
I can explain how the code works if anyone is interested. This answer is already pretty long so I am not going to do that now when not sure if it will be useful for anyone.
Hope that helps.
In these cases i normally create an emacs macro:
position the cursor on the second line (As your first line does not contain the quotes, it will not work there) of your table.
Press f3 and then:
C-a
Then press the pipe: "|"
press "delete" to remove the first double quote
search for the next double quote C-s "
remove the double quote and add another pipe sign
move one word further with C-right
add another pipe
C-e
add another pipe
move one line down with the cursor
press f4 to close the marco
When you now press f4 it should execute the same again.
If everything went fine, then you can execute the command easily hundreds of times through C- any number you want and "f4".
After that is done, you can simply also add pipes in the first line once.
Now pressing "tab" inside the org-table will align everything.
Hope that helps.

Showing thousand separator in org-mode spreadsheets

Is there a way to configure org-mode spreadsheets to show thousand separators? I would like 1000 to be shown as 1,000.
Here is a solution. First define the function group-number:
(defun group-number (num &optional size char)
"Format NUM as string grouped to SIZE with CHAR."
;; Based on code for `math-group-float' in calc-ext.el
(let* ((size (or size 3))
(char (or char ","))
(str (if (stringp num)
num
(number-to-string num)))
;; omitting any trailing non-digit chars
;; NOTE: Calc supports BASE up to 36 (26 letters and 10 digits ;)
(pt (or (string-match "[^0-9a-zA-Z]" str) (length str))))
(while (> pt size)
(setq str (concat (substring str 0 (- pt size))
char
(substring str (- pt size)))
pt (- pt size)))
str))
from: Emacs Cookbook - put commas in numbers
Next, use it in your formula:
| | | |
|-----------+-------+-------------|
| 2000 | 3100 | 5,100 |
| 11 | 22 | 33 |
| 111221212 | 29996 | 111,251,208 |
| | | 0 |
#+TBLFM: $3='(group-number (+ $1 $2));N
Here we are using the group-number function to format the result of an emacs lisp form - rather than using the calc formula syntax.

Emacs: how to find that at least one windows was vertically split

I don't know, how to write a function like this in elisp:
if(any window was split vertically)
return t;
else
return nil;
true:
|----------| |----------|----------|
| | | | |
| | | | |
|----------| |----------|----------|
false:
|--------| |--------|-------|
| | | | |
| | | | |
|--------| | |-------|
| | | | |
| | | | |
|--------| |--------|-------|
I found, that there is window-list function, that returns a list of all the windows. So, the algorithm should be like this:
(setq windows (window-list))
dolist(windows)
{
if($_->is_vertically_split())
{
return nil;
}
}
return t;
How can I determine, that this window is vertically split? It's height shouldn't be 100%.
Update
Using #lawlist answer I wrote the following, but it doesn't work (always returns nil):
(defun no-window-is-vertically-split ()
(let (windows (window-list)
(result nil))
(dolist (w windows)
(when (or
(window-in-direction 'above w)
(window-in-direction 'below w))
(setq result t)))
result))
(no-window-is-vertically-split)
Is it possible to break the dolist loop and just return the value, when 1-st split window is found?
You can use any of these to test whether there is a window above, below, left or right:
(window-in-direction 'above)
or
(window-in-direction 'below)
or
(window-in-direction 'left)
or
(window-in-direction 'right)
And here is an example using conditions -- just replace [... do something] with your preferred action:
(cond
((window-in-direction 'above)
[... do something])
((window-in-direction 'below)
[... do something])
((window-in-direction 'left)
[... do something])
((window-in-direction 'right)
[... do something]))
To test whether there is only one window, the following is useful:
(one-window-p t)
Here is a test similar to the call of the question, which is based upon the the test being performed from the selected window:
(if
(or
(window-in-direction 'above)
(window-in-direction 'below))
(message "There is either a window above or below the selected window.")
(message "There is are no windows above or below the selected window."))
EDIT (August 1, 2014):  Based on the updated question of the original poster, the following is an example of how to break the dolist loop and throw the result:
(defun no-window-is-vertically-split ()
(catch 'done
(let* (
result
(windows (window-list)))
(dolist (w windows)
(when (or
(window-in-direction 'above w)
(window-in-direction 'below w))
(setq result t)
(throw 'done result))))))
These two functions will detect horizontal and vertical splits:
(defun any-vertical-splits-p ()
"Return t if any windows have been split vertically."
(when (member nil (mapcar #'window-full-height-p (window-list))) t))
(defun any-horizontal-splits-p ()
"Return t if any windows have been split horizontally."
(when (member nil (mapcar #'window-full-width-p (window-list))) t))
I wasn't quite sure I knew what you meant in your diagram. Vertical and horizontal are used here as Emacs uses them with split-window-vertically and split-window-horizontally.

Org Table Formatting with Dollar Sign Columns

I'm using this method of creating a column:
http://orgmode.org/worg/org-tutorials/org-spreadsheet-lisp-formulas.html
I have a spreadsheet with 9 columns and column 8 contains filenames which have dollar signs in them, such as:
product_name $500.00.jpg
So I want column 9 to state whether or not the file actually exists, so my org TBLFM is as follows:
#+TBLFM: $9='(file-exists-p (concat "/import/" $8))
So the issue is, whether or not I use the ;L flag at the end of the TBLFM, when applying the formula I immediately get "Invalid Field Specifier: "$500"" because there is no column numbered 500.
Any thoughts as to how I can get this working? I've tried $8 in quotes and not in quotes, with and without the literal flag, and I've tried escaping the dollar sign in the actual columns all with no luck.
Edit: It's important to note that changing my column values to something like: product_name $\ 500.00.jpg does in fact work, however the file-exists-p value returned is obviously incorrect.
Edit: An example org-mode table triggering the error:
| foo | bar | /some/file with $500 in it.jpg | | baz |
| | | | | |
#+TBLFM: $4='(or (file-exists-p $3) "f")
This is the bit of Org code, which handles this case of the formula:
;; Insert the references to fields in same row
(while (string-match "\\$\\(\\([-+]\\)?[0-9]+\\)" form)
(setq n (+ (string-to-number (match-string 1 form))
(if (match-end 2) n0 0))
x (nth (1- (if (= n 0) n0 (max n 1))) fields))
(unless x (error "Invalid field specifier \"%s\""
(match-string 0 form)))
(setq form (replace-match
(save-match-data
(org-table-make-reference x nil numbers lispp))
t t form)))
As you see, there's no way for you to sidestep this bit, however, you could've patched the org-table-eval-formula near that place to allow you some kind of escape sequence to insert the literal sigil, I could get it this far:
;; Insert the references to fields in same row
(while (string-match "\\(^\\|[^\\$]\\)\\$\\(\\([-+]\\)?[0-9]+\\)" form)
(setq n (+ (string-to-number (match-string 2 form))
(if (match-end 3) n0 0))
x (nth (1- (if (= n 0) n0 (max n 1))) fields))
(unless x (error "Invalid field specifier \"%s\""
(match-string 0 form)))
(setq form (replace-match
(save-match-data
(org-table-make-reference x nil numbers lispp))
t t form)))
This will skip $$, unfortunately, this function calls itself recursively until all $ are replaced (I didn't know that). What you could do later: in eLisp code replace double sigils with singles... This worked in my case:
| foo | bar | /some/file with $$500 in it.jpg | f | /some/file with $500 in it.jpg |
| | | | t | |
#+TBLFM: $4='(or (file-exists-p $3) "f")::$5='(format "%s" (replace-regexp-in-string "\\$\\$" "$" $3))
Try escaping the $8 with a dollar char, that is as $$8.

specify window layout in emacs on commandline

I would like to be able to specify the window layout of the Emacs when starting it from commandline.
More specifically, I invoke "emacs file1 file2 file3 file4" and would, for example, like see
+---------+ +--------+
| file1 | | buff |
| | | list |
+---------+ instead of the default +--------+ that I see currently
| | | |
| file3 | | file4 |
+---------+ +--------+
My emacs is GNU Emacs 24.0.91.1, and I do not use emacsclient.
Note, I do not want to make the change permanent. That is why I ask for command-line solution.
Put the following in layout.el
(setq inhibit-startup-screen t)
(defun ordered-window-list-aux (tree)
(if (windowp tree)
(list tree)
(append (ordered-window-list-aux (nth 2 tree))
(ordered-window-list-aux (nth 3 tree)))))
(defun ordered-window-list ()
"Lists windows from top to bottom, left to right."
(ordered-window-list-aux
(car (window-tree))))
(require 'cl)
(defun fill-windows ()
"Make window list display recent buffer."
(mapcar*
(lambda (win buf)
(set-window-buffer win buf))
(nreverse (ordered-window-list))
(buffer-list)))
(delete-other-windows)
;; your window configuration
(split-window-horizontally)
(split-window-vertically)
;; Make window list display recent buffer
(fill-windows)
Then
emacs blah foo bar --load layout.el
The only thing you have to do is customizing the layout the way you want using a combination of the following functions:
(split-window-horizontally)
(split-window-vertically)
(other-windows 1)