Desired function algorithm
|------------------|
| old buffer - 70% |
| |
| |
| |
|------------------|
| |
| eshell - 30% |
|------------------|
If there is only 1 window in the buffer
1.1 Split buffer into 2 parts: top - 70% of the height, bottom - 30% of the height.
1.2. Put cursor to the bottom buffer.
1.3. Open eshell.
Code
(defun new-eshell ()
(interactive)
(when (one-window-on-screen-p)
(let ((new-window (split-window-vertically 30)))
(select-window new-window)
(eshell "eshell"))))
(defun one-window-on-screen-p ()
(= (length (window-list)) 1))
(global-set-key "\M-e" 'new-eshell)
Problem
When I click Alt-e for the first time, the function works correctly. But if I hide eshell buffer, and click Alt-e for the second time, the window is split in proportions 50/50 and "*eshell<2>*" buffer is opened at the top instead of bottom.
I think that the problem is that the parameter of split-lines-vertically refers to a number of lines, not to a proportion. This code worked for me:
(defun new-eshell ()
(interactive)
(when (one-window-on-screen-p)
(let* ((lines (window-body-height))
(new-window (split-window-vertically (floor (* 0.7 lines)))))
(select-window new-window)
(eshell "eshell"))))
(btw, I obtained strange results if I passed a floating point number to split-lines-vertically, so I had to use floor)
Related
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.
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 |
I use blame-mercurial using the monky.el package.
In a split window, when activating blame the results come up in the other window with info about the line changed (author/changeset/date:).
I would like to have a command that searches the first line of the "result" buffer, get to where the mark ":" is and shift the border of the original buffer up till that point.
Basically, if the borders of both windows are:
| ...... | ...... |
Before executing the command:
|author 4543 11-27-2013: int x; | int x; |
After executing the command:
|author 4543 11-27-2013:| int x; |
The reason for this is I would like to keep the coloring of data types/functions...etc while seeing who last changed these source file lines.
In the blame resulted file, when the lines are proceeded with author changeset date. they loose their coloring.
So I want to use the info for each line from the blame buffer "side by side" with the original fontified file.
I also can't use a fixed window border shift value, because depending on the author(s) name length for each file the position of ":" will change accordingly.
I have modified the last version at
"Mirroring location in file in two opened buffers side by side"
such that the following code makes sense. If you run the code below and then switch on sync-window-mode for the mercury-blame buffer then isearch will have the desired effect.
(defun mercury-blame-resize ()
"Resize mercury blame window to blame string at point only."
(interactive) ;; for debugging
(window-resize (selected-window)
(- (save-excursion
(beginning-of-line)
(skip-chars-forward "^:\n"))
(window-width) -1)
'horizontal 'ignore-fixed-size))
(add-hook 'sync-window-master-hook 'mercury-blame-resize)
(add-hook 'sync-window-mode-hook '(lambda ()
(setq-local isearch-update-post-hook #'(lambda () (set-window-hscroll (selected-window) 0)))))
Version for emacs 23:
(defvar mercury-blame-resize-min 5)
(defun mercury-blame-resize ()
"Resize mercury blame window to blame string at point only."
(interactive) ;; for debugging
(save-excursion
(beginning-of-line)
(let ((n (skip-chars-forward "^:\n")))
(when (looking-at ":")
(condition-case err
(enlarge-window (- (max mercury-blame-resize-min n)
(window-width) -1)
'horizontal)
(error))))))
(add-hook 'sync-window-master-hook 'mercury-blame-resize)
(add-hook 'sync-window-mode-hook '(lambda ()
(set (make-local-variable 'isearch-update-post-hook) #'(lambda () (set-window-hscroll (selected-window) 0)))))
Helper for testing (without mercury):
(loop for i from 1 upto 100 do
(loop for j from 0 upto (random 20) do
(insert (+ 32 (random 20))))
(insert ":\n"))
EDIT: In version for emacs 23: Only re-size mercurity blame buffer when there is a ":" on the current line.
I am converting a region to a table by using C-c |.
Is there a way to reverse the process, say after converting do some editing and go back to original format (tab separated values will do)?
I know that I can do it via org-table-export but that is too cumbersome.
Try orgtbl-to-tsv for tab-separated values.
There is also orgtbl-to-csv for comma-separated values.
Combining the table with a short code block to do the conversion is convenient. For example:
* Some heading
#+name: foo
| a | b | c |
|---+---+---|
| 1 | 2 | 3 |
| 4 | 5 | 6 |
#+name: foo-csv
#+BEGIN_SRC elisp :var x=foo :wrap example
(orgtbl-to-csv x nil)
#+END_SRC
#+RESULTS: foo-csv
#+begin_example
1,2,3
4,5,6
#+end_example
C-c C-c on the code block will produce the results shown. Adding :colnames no as a header argument to the code block will also preserve the header line:
#+name: foo-csv
#+BEGIN_SRC elisp :var x=foo :wrap example :results raw :colnames no
(orgtbl-to-csv x nil)
#+END_SRC
#+RESULTS: foo-csv
#+begin_example
a,b,c
1,2,3
4,5,6
#+end_example
I needed this too and just wrote the following based on org-table-export:
(defun org-table-transform-in-place ()
"Just like `ORG-TABLE-EXPORT', but instead of exporting to a
file, replace table with data formatted according to user's
choice, where the format choices are the same as
org-table-export."
(interactive)
(unless (org-at-table-p) (user-error "No table at point"))
(org-table-align)
(let* ((format
(completing-read "Transform table function: "
'("orgtbl-to-tsv" "orgtbl-to-csv" "orgtbl-to-latex"
"orgtbl-to-html" "orgtbl-to-generic"
"orgtbl-to-texinfo" "orgtbl-to-orgtbl"
"orgtbl-to-unicode")))
(curr-point (point)))
(if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format)
(let ((transform (intern (match-string 1 format)))
(params (and (match-end 2)
(read (concat "(" (match-string 2 format) ")"))))
(table (org-table-to-lisp
(buffer-substring-no-properties
(org-table-begin) (org-table-end)))))
(unless (fboundp transform)
(user-error "No such transformation function %s" transform))
(save-restriction
(with-output-to-string
(delete-region (org-table-begin) (org-table-end))
(insert (funcall transform table params) "\n")))
(goto-char curr-point)
(beginning-of-line)
(message "Tranformation done."))
(user-error "Table export format invalid"))))
(define-key org-mode-map (kbd "\C-x |") 'org-table-transform-in-place)
It'd be great if this got added to org-mode proper as I think many would use it.
Mark the region.
M-x replace-string
|
C-q TAB RET
If you want to tweak it, use replace-regex.
Here are the steps to use export the table as tab or comma separated values:
Use the command org-table-export. M-x org-table-export
Enter the filename to save to (or hit enter for the same file).
Select the format (this is where you can set the orgtbl-to-tsv or any other formats).
These are some of the formats that can be used:
orgtbl-to-csv
orgtbl-to-generic
orgtbl-to-html
orgtbl-to-latex
orgtbl-to-orgtbl
orgtbl-to-texinfo
orgtbl-to-tsv
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)