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

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.

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.

How do I get the list of all environment variables available in a Lisp process?

I want to enumerate the list of all environment variables available in my Lisp process. I want the same list that is returned by the C variable environ.
Neither SBCL nor Clozure CL seem to provide it out of the box. Can I do it using CFFI?
Interfacing with the OS and common lisp is still quite dependent on your lisp distribution. So more or less is not easy to find a good library that works in all CL distributions.
I recommend you to work with UIOP, which comes with ASDF 3 and above and it is the best library for working with the OS inside common lisp nowadays. However it doesn't have a function to list the environment variables, furthermother if we take a look at how it works with environment varables we can see that for every lisp distribution we have a different version of accessing the variables only for example:
(defun getenv (x)
"Query the environment, as in C getenv.
Beware: may return empty string if a variable is present but empty;
use getenvp to return NIL in such a case."
(declare (ignorable x))
#+(or abcl clasp clisp ecl xcl) (ext:getenv x)
#+allegro (sys:getenv x)
#+clozure (ccl:getenv x)
#+cmucl (unix:unix-getenv x)
#+scl (cdr (assoc x ext:*environment-list* :test #'string=))
#+cormanlisp
(let* ((buffer (ct:malloc 1))
(cname (ct:lisp-string-to-c-string x))
(needed-size (win:getenvironmentvariable cname buffer 0))
(buffer1 (ct:malloc (1+ needed-size))))
(prog1 (if (zerop (win:getenvironmentvariable cname buffer1 needed-size))
nil
(ct:c-string-to-lisp-string buffer1))
(ct:free buffer)
(ct:free buffer1)))
#+gcl (system:getenv x)
#+genera nil
#+lispworks (lispworks:environment-variable x)
#+mcl (ccl:with-cstrs ((name x))
(let ((value (_getenv name)))
(unless (ccl:%null-ptr-p value)
(ccl:%get-cstring value))))
#+mkcl (#.(or (find-symbol* 'getenv :si nil) (find-symbol* 'getenv :mk-ext nil)) x)
#+sbcl (sb-ext:posix-getenv x)
#-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl genera lispworks mcl mkcl sbcl scl xcl)
(not-implemented-error 'getenv))
(defsetf getenv (x) (val)
"Set an environment variable."
(declare (ignorable x val))
#+allegro `(setf (sys:getenv ,x) ,val)
#+clisp `(system::setenv ,x ,val)
#+clozure `(ccl:setenv ,x ,val)
#+cmucl `(unix:unix-setenv ,x ,val 1)
#+ecl `(ext:setenv ,x ,val)
#+lispworks `(hcl:setenv ,x ,val)
#+mkcl `(mkcl:setenv ,x ,val)
#+sbcl `(progn (require :sb-posix) (symbol-call :sb-posix :setenv ,x ,val 1))
#-(or allegro clisp clozure cmucl ecl lispworks mkcl sbcl)
'(not-implemented-error '(setf getenv))
so for getting one variable:
CL-USER> (uiop:getenv "GEM_PATH")
"/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global"
as pointed in a comment if you are usign SBCL you can get this with it:
SB-EXT:POSIX-ENVIRON
example in c:
extern char **environ;
//...
int i = 0;
while(environ[i]) {
printf("%s\n", environ[i++]); // prints in form of "variable=value"
}
| GEM_HOME=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev |
| SHELL=/bin/bash |
| TERM=dumb |
| TMPDIR=/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/ |
| Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.e0K30SfWTc/Render |
| USER=toni |
| SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners |
| __CF_USER_TEXT_ENCODING=0x1F5:0x0:0x8 |
| PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin |
| PWD=/Users/toni/learn/lisp/cl-l/stackoverflow/scripts |
| LANG=es_ES.UTF-8 |
| XPC_FLAGS=0x0 |
| XPC_SERVICE_NAME=org.gnu.Emacs.13016 |
| SHLVL=1 |
| HOME=/Users/toni |
| BUNDLE_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev |
| LOGNAME=toni |
| GEM_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global |
| DISPLAY=/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0 |
| _=/tmp/babel-6131RLH/C-bin-6131T_s |
example in SBCL
(sb-ext:posix-environ)
("TERM=dumb" "TERMCAP=" "COLUMNS=139" "INSIDE_EMACS=25.2.1,comint"
"BUNDLE_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev"
"GEM_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global"
"GEM_HOME=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev" "LANG=es_ES.UTF-8"
"XPC_FLAGS=0x0" "USER=toni" "XPC_SERVICE_NAME=org.gnu.Emacs.13016"
"DISPLAY=/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0"
"LOGNAME=toni"
"PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin"
"SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners"
"Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.e0K30SfWTc/Render"
"SHELL=/bin/bash" "HOME=/Users/toni" "__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x8"
"TMPDIR=/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/"
"SBCL_HOME=/Users/toni/.roswell/impls/x86-64/darwin/sbcl/1.3.16/lib/sbcl"
"ROS_OPTS=((\"program\"\"(:eval\\\"(ros:quicklisp)\\\")\")(\"lispdir\"\"/usr/local/Cellar/roswell/17.4.8.76/etc/roswell/\")(\"verbose\"\"0\")(\"homedir\"\"/Users/toni/.roswell/\")(\"wargv0\"\"/usr/local/bin/ros\")(\"argv0\"\"/usr/local/bin/ros\")(\"quicklisp\"\"/Users/toni/.roswell/lisp/quicklisp/\")(\"impl\"\"sbcl/1.3.16\")(\"dynamic-space-size\"\"3gb\")(\"sbcl.version\"\"1.3.16\")(\"allegro.version\"\"100express\")(\"ccl-bin.version\"\"1.11\")(\"ecl.version\"\"16.1.3\")(\"slime.version\"\"2017.02.27\")(\"sbcl-bin.version\"\"1.2.11\")(\"default.lisp\"\"sbcl\"))")
So for other implementations you mut investigate how to,
Finally exist a good library called OSICAT that:
OSICAT is a lightweight operating system interface for Common Lisp on
Unix-platforms. It is not a POSIX-style API, but rather a simple lispy
accompaniment to the standard ANSI facilities.
so in your case you must use:
(osicat:environment)
(("TERM" . "dumb") ("TERMCAP" . "") ("COLUMNS" . "139") ("INSIDE_EMACS" . "25.2.1,comint") ("BUNDLE_PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev") ("GEM_PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global") ("GEM_HOME" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev") ("LANG" . "es_ES.UTF-8") ("XPC_FLAGS" . "0x0") ("USER" . "toni") ("XPC_SERVICE_NAME" . "org.gnu.Emacs.13016") ("DISPLAY" . "/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0") ("LOGNAME" . "toni") ("PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin") ("SSH_AUTH_SOCK" . "/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners") ("Apple_PubSub_Socket_Render" . "/private/tmp/com.apple.launchd.e0K30SfWTc/Render") ("SHELL" . "/bin/bash") ("HOME" . "/Users/toni") ("__CF_USER_TEXT_ENCODING" . "0x1F5:0x0:0x8") ("TMPDIR" . "/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/") ("ROS_OPTS" . "((\"program\"\"(:eval\\\"(ros:quicklisp)\\\")\")(\"lispdir\"\"/usr/local/Cellar/roswell/17.4.8.76/etc/roswell/\")(\"verbose\"\"0\")(\"homedir\"\"/Users/toni/.roswell/\")(\"wargv0\"\"/usr/local/bin/ros\")(\"argv0\"\"/usr/local/bin/ros\")(\"quicklisp\"\"/Users/toni/.roswell/lisp/quicklisp/\")(\"impl\"\"ccl-bin/1.11\")(\"dynamic-space-size\"\"3gb\")(\"sbcl.version\"\"1.3.16\")(\"allegro.version\"\"100express\")(\"ccl-bin.version\"\"1.11\")(\"ecl.version\"\"16.1.3\")(\"slime.version\"\"2017.02.27\")(\"sbcl-bin.version\"\"1.2.11\")(\"default.lisp\"\"ccl-bin\"))"))
SO I hope that this should work

Replacing word in inactive buffer

If I have two buffers open (side-by-side) and I move from one window to another, can I replace previously selected word in the first (now inactive) window with the one that is under cursor in active window?
_ is cursor
_______________
| foo | _bar |
| | |
| | |
| | |
|_______|_______|
is there an internal command that can quickly let me replace foo with bar?
No internal commands, but this is Emacs:
(defun replace-word-other-window ()
(interactive)
(let ((sym (thing-at-point 'symbol))
bnd)
(other-window 1)
(if (setq bnd (bounds-of-thing-at-point 'symbol))
(progn
(delete-region (car bnd) (cdr bnd))
(insert sym))
(message "no symbol at point in other window"))
(other-window -1)))
update: advanced version
(defun region-or-symbol-bounds ()
(if (region-active-p)
(cons (region-beginning)
(region-end))
(bounds-of-thing-at-point 'symbol)))
(defun replace-word-other-window ()
(interactive)
(let* ((bnd-1 (region-or-symbol-bounds))
(str-1 (buffer-substring-no-properties
(car bnd-1)
(cdr bnd-1)))
(bnd-2 (progn
(other-window 1)
(region-or-symbol-bounds))))
(if bnd-2
(progn
(delete-region (car bnd-2) (cdr bnd-2))
(insert str-1))
(message "no region or symbol at point in other window"))
(other-window -1)))

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)

Org-Mode table to s-expressions

I would like to export from Org-Mode tables to s-expressions.
| first | second | thrid |
|--------+--------+--------|
| value1 | value2 | value3 |
| value4 | value5 | value6 |
Would turn into:
((:FIRST "value1" :SECOND "value2" :THIRD "value3")
(:FIRST "value4" :SECOND "value5" :THIRD "value6"))
I plan on writing such a setup if it doesn't exist yet but figured I'd tap into the stackoverflow before I start reinventing the wheel.
This does the trick. It has minimal error checking.
The interface to use is either the programmatic interface:
(org-table-to-sexp <location-of-beginning-of-table> <location-of-end-of-table>)
In which case it'll return the sexp you requested.
If you wanted an interactive usage, you can call the following command to operate on the table in the region. So, set the mark at the beginning of the table, move to the end, and type:
M-x insert-org-table-to-sexp
That will insert the desired sexp immediately after the table in the current buffer.
Here is the code:
(defun org-table-to-sexp-parse-line ()
"Helper, returns the current line as a list of strings"
(save-excursion
(save-match-data
(let ((result nil)
(end-of-line (save-excursion (end-of-line) (point))))
(beginning-of-line)
(while (re-search-forward "\\([^|]*\\)|" end-of-line t)
(let ((match (mapconcat 'identity (split-string (match-string-no-properties 1)) " ")))
(if (< 0 (length match))
;; really want to strip spaces from front and back
(push match result))))
(reverse result)))))
(require 'cl)
(defun org-table-to-sexp (b e)
"Parse an org-mode table to sexp"
(save-excursion
(save-match-data
(goto-char b)
(let ((headers (mapcar
(lambda (str)
(make-symbol (concat ":" (upcase str))))
(org-table-to-sexp-parse-line)))
(sexp nil))
(forward-line 1) ;skip |--+--+--| line
(while (< (point) e)
(forward-line 1)
(let ((line-result nil))
(mapcar* (lambda (h e)
(push h line-result)
(push e line-result))
headers
(org-table-to-sexp-parse-line))
(if line-result
(push (reverse line-result)
sexp))))
sexp))))
(defun insert-org-table-to-sexp (b e)
"Convert the table specified by the region and insert the sexp after the table"
(interactive "r")
(goto-char (max b e))
(print (org-table-to-sexp b e) (current-buffer)))