print only text discarding text properties - emacs

I have the following function to print the line where point is to the *scratch* buffer,
(defun print-line ()
(print (thing-at-point 'line) (get-buffer "*scratch*")))
but it prints even the fontified info like this
#(" OFFICE
" 0 2 (fontified t org ...
How to discard the printing of the fontified info.

To expand on Daimrod's mention of buffer-substring-no-properties...
M-x apropos RET no-properties RET
buffer-substring-no-properties
Function: Return the characters of part of the buffer, without the
text properties.
field-string-no-properties
Function: Return the contents of the field around POS, without text
properties.
insert-buffer-substring-no-properties
Function: Insert before point a substring of BUFFER, without text
properties.
match-string-no-properties
Function: Return string of text matched by last search, without text
properties.
minibuffer-contents-no-properties
Function: Return the user input in a minibuffer as a string, without
text-properties.
substring-no-properties
Function: Return a substring of STRING, without text properties.
You can read about text properties in the manual:
M-: (info "(elisp) Text Properties") RET

I needed something similar for eredis when manipulating strings from an org-table. You can use `set-text-properties' to get rid of them when displaying the string.
(defun strip-text-properties(txt)
(set-text-properties 0 (length txt) nil txt)
txt)
(defun print-line ()
(print (strip-text-properties
(thing-at-point 'line))
(get-buffer "*scratch*")))

I've tried some things but it's weird, I don't really understand how text properties work.
For example:
(type-of (thing-at-point 'line)) => string
As you've said if one tries to print it, the properties are printed as well, but if one tries to insert it:
(insert (format "%s" (thing-at-point 'line)))
Only the string is printed, not the properties.
So it seems to me that those properties are just bound to the string but you can manipulate the string as usual:
(lenght (thing-at-point 'line))
(substring (thing-at-point 'line) 0 2)
However, if all you want is the line, and the line only you can use buffer-substring-no-properties:
(defun print-line ()
(print (buffer-substring-no-properties (point-at-bol) (point-at-eol))))

Related

Emacs24 and python-mode: indention in docstrings

I have the following code/text:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
In Emacs23 (23.4.1) I was able to press TAB in the last line ("second note line"; nomatter how this line was indented) and it was aligned correctly like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e., it uses the previous line and indents the following line in the same way.
Now in Emacs24 (24.3.1) this does not work anymore and it is aligned like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e. it aligns the multi-line string block, but does not depend on the previous line.
It affects only docstrings; code is indented as I want. I am using python-mode. How can I change this, so that pressing TAB aligns the block correctly?
Python mode has changed quite a bit between Emacs 23 and 24. There is no configuration that would allow you to do what you want.
But, Emacs is quite flexible and you can advise the (python-indent-context) function to make it return a different result that will lead to the behavior you want. The function (python-indent-context) returns a character at which the indentation is measured and used for indenting the current line. By default, when inside a string, it returns the point where the beginning of the string resides. Thus, your line will be indented to the indentation of the start of the string. We can easily modify it to return a point in the previous non-empty line instead, for instance like this:
(defun python-fake-indent-context (orig-fun &rest args)
(let ((res (apply orig-fun args))) ; Get the original result
(pcase res
(`(:inside-string . ,start) ; When inside a string
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point))))
(_ res)))) ; Otherwise, return the result as is
;; Add the advice
(advice-add 'python-indent-context :around #'python-fake-indent-context)
The same effect can be achieved using the old defadvice for older Emacs:
(defadvice python-indent-context (after python-fake-indent-context)
(pcase ad-return-value
(`(:inside-string . ,start) ; When inside a string
(setq ad-return-value ; Set return value
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point)))))))
(ad-activate 'python-indent-context)
What about editing the section de-stringified in a separate buffer? That would allow python-mode with all its facilities.
Here a first draft - original string will be stored in kill-ring:
(defun temp-edit-docstring ()
"Edit docstring in python-mode. "
(interactive "*")
(let ((orig (point))
(pps (parse-partial-sexp (point-min) (point))))
(when (nth 3 pps)
(let* (;; relative position in string
(relpos (- orig (+ 2 (nth 8 pps))))
(beg (progn (goto-char (nth 8 pps))
(skip-chars-forward (char-to-string (char-after)))(push-mark)(point)))
(end (progn (goto-char (nth 8 pps))
(forward-sexp)
(skip-chars-backward (char-to-string (char-before)))
(point)))
(docstring (buffer-substring beg end)))
(kill-region beg end)
(set-buffer (get-buffer-create "Edit docstring"))
(erase-buffer)
(switch-to-buffer (current-buffer))
(insert docstring)
(python-mode)
(goto-char relpos)))))
When ready, copy the contents back into original buffer.
Which remains to be implemented still.

Repeated calls to format ignore the ~t option

I have this:
(defun promptread (prompt)
(format *query-io* "~10t~a:" prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun prompt-cd ()
(make-cd
(promptread "Artist")
(promptread "Album")
(promptread "Rating")
(promptread "Like [y/n]")))
It works, however the format ~10t only affects the first call to promptread inside make-cd; the others are left-aligned without this padding.
Why would this be?
REPL:
CL-USER> (addcds)
Artist:Dixie
Album:Funny
Rating:22
The first promptread is indented because of the format with ~10t but not the others, which use the same exact format call.
The problem is that after force-output and readline, the cursor is not known to formatto be at position 0. Thus absolute tabulation will fail. If you start the format string with ~&, you will see this as an additional newline will be outputted anyway.
To solve the problem use the # modifier to get relative tabulation:
(format *query-io* "~10#t~a:" prompt)

How to finish this job in emacs?

The original string is like this:
# chrom,name,strand,txStart
And the result should looks like this:
# $1: chrom
# $2: name
# $3: strand
# $4: txStart
Does anyone have idea of a quick way to do that?
Lots of ways.
You could use a search and replace making use of the \# counter in the replacement. That's zero-based, so you'd either need to add a dummy replacement at the front to use up the zero, or else use the elisp replacement expression \,(1+ \#) instead.
You could use a keyboard macro, and insert a counter with C-xC-kTAB or <f3>. You can seed that counter by supplying a prefix argument when you start recording.
On Emacs 24 you can number the lines of a marked region using a custom format string with C-uC-xrN, so your format string could be # $%1d:
Evaluate following code and execute foo function on input line.
(require 'cl)
(defun foo ()
(interactive)
(let* ((str (buffer-substring-no-properties
(line-beginning-position) (line-end-position)))
(words-str (and (string-match "# \\(.+\\)$" str)
(match-string 1 str)))
(buf (get-buffer-create "*tmp*")))
(unless words-str
(error "Line should be '# word1,word2,...'"))
(with-current-buffer buf
(erase-buffer)
(loop with index = 1
for word in (split-string words-str ",")
do
(progn
(insert (format "# $%d: %s\n" index word))
(incf index)))
(pop-to-buffer buf))))

Emacs auto compelete paren, indent and new line - how to?

In C - I want that when I type a { and then } emacs will insert a new line between them and then set the cursor in between them. For example:
int main() {
now I type } and the following happens:
int main()
{
//cursor is here
}
Edit: forgot to mention - I want emacs to know that when defining a function that it should do what was described above but when doing a for loop, or if statement for example I want it to do the following:
if (bla bla) {
type } and... :
if (bla bla) {
//cursor here
}
If you don't mind that the behaviour will be only almost, but not exactly the way you described it, there is a built-in way to do that. It's the auto-newline feature, that can be activated with the key combination C-c C-a or this line your .emacs:
(c-toggle-auto-newline 1)
The difference is that it will do the reformatting right after entering the opening brace {. When you finally enter the closing brace, it will indent it the right way, too.
You also need to set the right CC Mode style. The style "cc-mode" seems to define things the way you described it. You can activate it with the key combination C-c . and then choosing cc-mode, or the .emacs line
(c-set-style "cc-mode")
The c-mode functions are autoloaded and will therefore usually not be available while loading the .emacs file. Therefore you should wrap them in a hook for c-mode, like this
(add-hook 'c-mode-hook
(lambda ()
(c-toggle-auto-newline 1)
(c-set-style "cc-mode")))
As for the { stuff:
(define-minor-mode c-helpers-minor-mode
"This mode contains little helpers for C developement"
nil
""
'(((kbd "{") . insert-c-block-parentheses))
)
(defun insert-c-block-parentheses ()
(interactive)
(insert "{")
(newline)
(newline)
(insert "}")
(indent-for-tab-command)
(previous-line)
(indent-for-tab-command)
)
Paste the above into your .emacs. You can activate it with c-helpers-minor-mode.
Edit: The above inserts everything by just pressing {. The script below should do it if you type {}:
(defun insert-latex-brackets (opening closing) ; prototype function for all enclosing things
(interactive)
(insert opening)
(insert " ")
(insert closing)
(backward-char (+ 1 (length closing )))
)
(defun check-char-and-insert (char opening closing)
(interactive)
(if (equal char (char-to-string (char-before (point))))
(progn (delete-backward-char 1)
(insert-latex-brackets opening closing))
(insert char)
)
)
(local-set-key (kbd "}") 'check-char-and-insert)
One last note: You could try using yasnippet, which can be a real time saver used properly.

Why might the Emacs "downcase" function refuse to do downcasing?

I'm trying to write simple Emacs function to convert ids between C style ones and camelCase ones (i.e. c_style <-> cStyle). But for some reason, Emacs built in downcase function leaves the word intact. M-x downcase-word works fine so I completely lost. Any ideas are welcome.
(defun toggle-id-style ()
"Toggle between C-style ids and camel Case ones (i.e. c_style_id -> cStyleId and back)."
(interactive)
(save-excursion
(progn
(re-search-forward "[^A-Za-z0-9_]" nil t)
(let ((end (point))
(case-fold-search nil))
(progn
(re-search-backward "[^A-Za-z0-9_]" nil t)
(let* ((cstyle (if (string-match "_" (buffer-substring-no-properties (point) end)) t nil))
(regexp (if cstyle "_\\(\\w+\\)" "\\([A-Z][a-z0-9]+\\)") )
(func (if cstyle 'capitalize (lambda (s) (concat "_" (downcase s) ) ))))
(progn
(while (re-search-forward regexp end t)
(replace-match (funcall func (match-string 1)) nil nil)))))))))
;;M-x replace-regexp _\(\w+\) -> \,(capitalize \1) ;; c_style -> cStyle
;;M-x replace-regexp \([A-Z][a-z0-9]+\) -> _\,(downcase \1) ;;cStyle -> c_style
It works fine if I convert c_style but when I'm trying to convert cStyle I got c_Style as result. Yes, I've checked that this is due to downcase behaviour.
Your problem is the second argument to replace-match. From the documentation:
If second arg fixedcase is non-nil, do not alter case of replacement text.
Otherwise maybe capitalize the whole text, or maybe just word initials,
based on the replaced text.
If the replaced text has only capital letters
and has at least one multiletter word, convert newtext to all caps.
Otherwise if all words are capitalized in the replaced text,
capitalize each word in newtext.
You're passing nil for the fixedcase argument, which causes replace-match to capitalize the replacement when the text being replaced is capitalized. Pass t instead and this bit of the code will work.
I have two general comments about your code.
All of your uses of progn are unnecessary. The body of save-excursion is an implicit progn and so are the bodies of let and let*.
You search forwards and then backwards to try to find the bounds of the symbol underneath point. Emacs already has a thingatpt library to find things at or near the point. In your case you can just call (bounds-of-thing-at-point 'symbol) which returns a cons cell (START . END) giving the start and end positions of the symbol that was found.
I think you need the second arg of replace-match to be t instead of nil.