draw a polygon over closed polylines - lisp

i try to describe this problem well with my humble English skills :
i have closed blocks on my dwg file, these blocks are consist of many Polylines which are joined together but they are not uni-body (integrated), all i want is a lisp to draw a polygon over this block and create a uni-body block. is there any way around ?
thnx

Assuming that:
when you say "joined" you mean their ends are touching,
when you say "uni-body" you actually mean "joined" in the AutoCAD sense,
then try the following:
(defun convert_block_to_polyline (block / old_entlast new_entlast curr polylines_set)
(setq old_entlast (entlast))
(command "explode" block)
(setq new_entlast (entlast))
(setq
curr (entnext old_entlast)
polylines_set (ssadd)
)
(while (entnext curr)
(ssadd curr polylines_set)
(setq curr (entnext curr))
)
(command "join" (entlast) polylines_set "")
(princ)
)
This function assumes:
You don't want to retain the original block, if you do then its a simple question of creating a copy before you explode it, and pasting it in the same place afterwards.
The block is made solely of objects which can be included in the join command (lines, polylines etc..)

Related

How to get org mode file "Title" and other file-level properties from an arbitrary file?

I have files with this format
#+TITLE: Magit Cheatsheet
:PROPERTIES:
:Status: Open
:Tags: tools, emacs, org, magit
:Creation: [2021-03-03 Wed]
:END:
I'd like to be able to read the title and these properties for a given file name (not the currently open file) with elisp. I found this but it isn't working for me and seems too complex for something as simple as this.
I cannot answer the question about the properties until you fix the file (how you fix it will affect the proposed solution).
For the title however, the following code works (Q: what is the shortest lie in computing? A: It works!):
#+begin_src elisp :results drawer
(defun ndk/get-keyword-key-value (kwd)
(let ((data (cadr kwd)))
(list (plist-get data :key)
(plist-get data :value))))
(defun ndk/org-current-buffer-get-title ()
(nth 1
(assoc "TITLE"
(org-element-map (org-element-parse-buffer 'greater-element)
'(keyword)
#'ndk/get-keyword-key-value))))
(defun ndk/org-file-get-title (file)
(with-current-buffer (find-file-noselect file)
(ndk/org-current-buffer-get-title)))
(ndk/org-file-get-title "/tmp/foo86.org")
#+end_src
The main function is the last one ndk/org-file-get-title which takes care of opening the file and running the ndk/org-current-buffer-get-title function on the resulting buffer. The latter functions uses the almighty org-element-map function on a subset of the data that the parser returns (that's for efficiency only): we map the ndk/get-keyword-key-value function on all the keyword elements. This function returns a (key value) list for each of the keywords that it gets called on, and the mapper accumulates those pairs into a list. We then select the pair that contains the string "TITLE" as the key, and the (nth 1 ...) call gets the value part of the pair (the key part would be (nth 0 ...)).
A minor variation of this would also work for dealing with #+PROPERTY keywords, but dealing with property drawers under a headline would be more complicated (I think - I haven't tried it out).

Displaying info panel at top of buffer

I'd like to display a few lines at the top of the buffer, but not as part of the actual buffer text, just for display.
Specifically, I'd like to display a Git timeline (not yet released, sorry), like this automatically when I open a file, so I can easily see any recent activity:
P DP D D
T=F=S=S=M=T=W=T=F=S=S=M=T=W=T=F=S=S=M==T==W==T==F==S==S==M==T==W==T==F==S==S==M=
11 18 25 2 9
(Single chars are first initials of people with commits on those days. There will be a legend below as well)
It sounds like I want something like the header line, but for the buffer. Is there anything like that?
One idea I had was to use an overlay at the start of the buffer and put my text there, but I'm not at all sure this is "the right thing" or a completely inappropriate / unsuitable use of this.
I tried, and got it working, using an overlay of the char at (point-min), with the text-property of 'before-string and the string literal above (with newlines and a trailing newline). Here's a proof of concept:
(defun test/add-overlay ()
(interactive)
(setq test/timeline-overlay (make-overlay (point-min) (+ (point-min) 1)))
(overlay-put test/timeline-overlay 'timeline-panel t)
(overlay-put test/timeline-overlay 'before-string
(propertize " P DP D D \nT=F=S=S=M=T=W=T=F=S=S=M=T=W=T=F=S=S=M==T==W==T==F==S==S==M==T==W==T==F==S==S==M=\n 11 18 25 2 9
" 'face 'font-lock-comment-face))
)
(defun test/remove-overlay ()
(interactive)
(remove-overlays (point-min) (point-max) 'timeline-panel t)
)
This does seem to work quite fine, but I'm not sure if it might conflict with something else.
Is this the way to go, or are the more suitable user interface constructs in Emacs to do what I want?
If you can reduce it to a single line, then use header-line-format -- it's local in every buffer. Just set the variable for the buffer you want. See the Emacs sources for examples, e.g., ruler-mode.el.
You seem to have dismissed using a header line, saying that you want something "for the buffer". I don't understand why you think header-line-format does not give you what you want (except that it is one line only).
Yes, if you want display-only text placed at a particular location in the buffer, then an overlay with some after-string or before-string is the way to go.

How to exchange words in emacs(by replace them with each other one) [duplicate]

This question already has answers here:
How can I swap or replace multiple strings in code at the same time?
(5 answers)
Closed 8 years ago.
Say I have some text like:
First one is good, so I used first one.Second one is bad, so I drop it.
I want to switch the 'first' and 'second',and like replace-string,leave the capital to the same case as original word.
Is there any built-in functions to handle this situations?
Edit:
Let me explain the problem further.If I use usual replace-string twice,will some times cause unwanted results.In the example above, If using replace-string first RET second RET, then replace-string second RET first RET,it will out put: First one is good. so I used first one.First one is bad, so I drop it. It also a problem in some case like "clientFolder=>serverFolder and server=> client"
#huaiyuan answered the same question here:
How can I swap or replace multiple strings in code at the same time?
His code allows you to enter arbitrary list of pairs to do parallel replacement.
Incidently, if you want to read some cool lisp code, click on #huaiyuan and read his answers.
Here's a great trick courtesy of Mickey's Mastering Emacs blog (see http://www.masteringemacs.org/articles/2013/01/25/evaluating-lisp-forms-regular-expressions/ under the heading "Swapping Elements")
C-M-% \(first\)\|second RET \,(if \1 "second" "first") RET
Edit: and here's an elisp version of that:
(defun my-swap-text (a b)
"Swap two pieces of text wherever they appear, using `query-replace-regexp'."
(interactive "sSwap: \nswith: ")
(let ((use-region (and transient-mark-mode mark-active)))
(query-replace-regexp
(rx (or (group (eval a)) (eval b)))
(quote (replace-eval-replacement replace-quote (if (match-string 1) b a)))
nil
(when use-region (region-beginning))
(when use-region (region-end)))))
did you google search this at all?
http://kb.iu.edu/data/abdp.html

Watch a sexpr for edits

I'd like to tell Emacs to 'watch' a particular form (identified by its car) within a buffer and evaluate it whenever I edit it.
One approach I can think of is to add a function to post-self-insert-hook, which would find and parse the targeted form and compare it with its previously stored state.
It doesn't sound too inefficient, especially if a 'calls per second' maximum is enforced (e.g. using current-time).
Is there is a higher level / more idiomatic way to accomplish this? It sounds like the sort of problem that has been solved already.
I think the most natural way is to create an overlay that would span from the beginning to the end of the form.
Overlays have a modification-hooks property, and you can add a watcher function to it.
The overlay will contract or expand appropriately if you modify buffer contents strictly inside it, but you'll need to decide what to do when buffer is edited at the edges of the form. See insert-in-front-hooks, insert-behind-hooks and the last two arguments to make-overlay. I'd probably just re-create the overlay in most of these cases, just to be sure about the new bounds.
About the "calls per second" thing, you can use run-with-idle-timer.
Part of what #Dmitry mentioned can be turn into simple prototype. Mark (message "text") and run M-xeval-on-modify-add
(defun eval-on-modify-add ()
(interactive)
(let ((ov (make-overlay (region-beginning) (region-end))))
(overlay-put ov 'modification-hooks '(eval-on-modify-execute))))
(defun eval-on-modify-execute (ov &optional flag &rest rv)
(if flag
(eval-region (overlay-start ov) (overlay-end ov))))
(message "test")

folding multi-line-comments in emacs automatically

in my .emacs configuration, i have the following :
(defun fold-long-comment-lines ()
"This functions allows us to fold long comment lines
automatically in programming modes. Quite handy."
(auto-fill-mode 1)
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(not (eq (get-text-property (point) 'face)
'font-lock-comment-face)))))
the above gets invoked as part of "c-mode-common-hook" and correctly provides folding long comment lines automatically.
however, the above thing works indiscriminately, whether i am using a single line comment e.g. describing struct fields, or multi-line comments describing some complicated piece of code.
so, the basic question is, how can i get automatic folding of long comment lines only if it is a multi-line comment ?
thanks
anupam
edit-1: multi-line-comment explanation
when i say "multi-line-comment", it basically means comments like this:
/*
* this following piece of code does something totally funky with client
* state, but it is ok.
*/
code follows
a correspondingly, a single line comment would be something like this
struct foo {
char buf_state : 3; // client protocol state
char buf_value : 5; // some value
}
the above elisp code, dutifully folds both these comment lines. i would like to fold only the former, not the latter.
If you only want it to affect auto-fill-mode and not general filling (e.g. not when you hit M-q), then your code can be replaced by setting comment-auto-fill-only-comments. As for having it apply only to "multi-line comments", I think you're first going to have to explain what is the difference between. Are you saying that you only want to auto-fill when the comment already spans more than one line, or is there some other characteristic of a comment that can let Emacs figure out that a comment that currently only spans a single line can be spread over multiple lines.
You could try something like:
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(let ((ppss (syntax-ppss)))
(or (null (nth 4 ppss)) ;; Not inside a comment.
(save-excursion
(goto-char (nth 8 ppss))
(skip-chars-backward " \t")
(not (bolp))))))) ;; Comment doesn't start at indentation.