Natural language processing / commands (prolog) - command

I want to create a predicate, which recognizes a word (in this case: "save") and starts saving the next words, until the sign/word "end" comes.
It should work like this:
?- save.
one
two
end
true.
The predicate for saving:
save(X) :- assert(listitem(X)).
and then I started like this:
save :- read(save).
read:- X -> save(X).
end --> 'end'.
The problem is, that I can add as much words as I want, but if I want to stop the command with "end", the program fails and actually the words have not been saved.
What part of the predicate is wrong? I'd be very happy for some help.
Thank you in advance!

This is some extremely confused code. Here's what you wanted:
:- dynamic listitem/1.
readline(Line) :-
% this is an SWI extension, but it's very handy
read_line_to_codes(user, Codes),
atom_codes(Line, Codes).
save :-
readline(X),
(X \= end -> (assertz(listitem(X)), save)
; true).
Odds are good, somewhere in the code you didn't bring, all you were missing was the effect of the ; true there: that when you find end, you're finished, but not that you failed. But you have a lot of problems here.
save/0 calls read/1, which is a system predicate. All this is going to do is read a word from the user (ending with a period!) and notice that it isn't the word "save". Unfortunately, reading a whole line without periods at the end is a somewhat non-trivial task in Prolog, hence the pile of code in my solution.
read/0 is not called by anything.
The syntax X -> save(X) is almost certainly not what you want. This is the first occurrence of X in the predicate, and so it probably isn't doing you much good to test it conditionally before it has a value.
end --> 'end'. is a DCG rule, but you aren't using phrase/2 anywhere to invoke it (nor are you using end/2 directly with a difference list).
assert/1 is a really bad habit to get into. The ISO predicates asserta/1 and assertz/1 are not only portable, they also give the reader a better idea what the effect on the fact database will be.
Similarly, you have no dynamic declaration for listitem/1, which would raise portability and improve readability.

I would use a 'state machine' approach: it's so simple!
:- dynamic listitem/1.
loop(Mode) :- read(W), loop(Mode, W).
loop(_, stop).
loop(skip, save) :- loop(save).
loop(skip, _) :- loop(skip).
loop(save, W) :- assertz(listitem(W)), loop(save).
test:
1 ?- loop(skip).
|: asd.
|: save.
|: ok.
|: ok1.
|: stop.
true
.
2 ?- listing(listitem).
:- dynamic stackoverflow:listitem/1.
stackoverflow:listitem(ok).
stackoverflow:listitem(ok1).
true.

Related

vim/neovim fold: Avoid cascaded fold when fold all

When reviewing some code, I always enjoy the folding feature of vim/nvim. I set foldmethod=intend, and that works pretty well except the following case:
When it comes to "close all folds", which is triggered by zM, there will be meaningless cascaded folds under the lines which have a high indentation while the surrounding indentation is low. For example,
def a_very_long_function(arg1
arg2
arg3
):
pass
Then when I press zM, I will need to press za many times to unfold the args. I thought foldexp might solve this problem, but I have no idea how to write a suitable function. Cause I use nvim, I also tried the pretty-fold plugin but it doesn't seem to have a concern of my issue. I also notice the intendexp option, but I don't know if it's the best practice. Is there anything else could solve the problem or there's a existing feature which could avoid this?
What I want is When I unfold after close all folds, there isn't any meaningless cascaded folds which needs to be unfold many times.

How can I detect the end of the buffer when iterating over lines or headings in elisp?

The TLDR is the code:
(while (?????)
(org-next-visible-heading 1)
(org-todo 'todo)
)
What should I put in the condition ????? in order to stop at the end of the file, or after the last visible heading?
The longer context:
I'm using trying to use elisp to modify org-mode files for emacs. I'm new to elisp and finding it hard to find the relevant documentation for some basic things.
I want to iterate over the headings in an org-mode buffer and modify the status (i.e. todo) keyword. I've seen it suggested that if I want to modify the buffer, it is better not to use org-element-map but instead to use something like org-next-visible-heading or org-forward-same-level, and at each point use org-todo to modify the heading.
I know how to write a while loop, but I don't know how to write the condition as I haven't been able to find out how to detect if I'm at the end of the buffer, even though this seems to be a trivial thing to want to do.
I'm happy to be told there is a better approach to my problem but I would still like to know how to detect the end of a buffer in general.
Rather than looping, you can use org-map-entries. Here is an example, pretty much from the doc, that marks each headline as a TODO item:
(org-map-entries '(org-todo "TODO") t 'file 'archive 'comment)
It specifies a function to apply to each headline: (org-todo "TODO"); no tag or property matching; file scope; and skips archive and comment headlines.
Read the linked doc and also do C-h f org-map-entries, but don't get too scared by the doc string of the function: org-map-entries is very powerful, but it will take some time to understand how to do things with it and harness its power.

How can I modify emacs' Search and Replace to perform a more complicated task?

total Emacs noob here. So right now I'm working on a fairly big LaTeX project in Emacs in which there are couple of places where I need to index some words, using the makeidx package. Because I also wanted indexed words to be bold, I created my own command \ind{} which would make the argument go bold and indexed. But right now I'm dissatisifed with this command so I'd like to change every instance of \ind{whatever} in my text by \textbf{whatever}\index{whatever by default}.
The thing is I know exactly what I want :
Go through the text, look for any instance of \ind{ and replace by \textbf{ using search-and-replace
Save the argument of \ind ("whatever" in this case) in memory
Ask me the user what should the argument of \index be. By default (by striking enter), it should be the first argument, but I can also change my mind and enter something different ("whatever by default" in this case). If there's no input (only a space " " for example) stop the program.
Write down \index{, the new argument and }.
Go to next occurance in the text.
But, alas!, I know not how to achieve this, so I need someone's help. If it should take too much time to explain how to do such a thing, would you please send me some tutorial about writing my own functions?
I hope I'm being clear, and thanks for your patience!
This approach seems vaguely unorthodox to me, but it works and seems sufficient for a one-off job...
In the replacement text for replace-regexp and query-replace-regexp (C-M-%), one newer escape sequence is \,(...), where ... can be any Lisp expression. There's a Lisp function read-from-minibuffer which reads arbitrary text typed by the user, with an optional default. Therefore:
C-M-%: Start query-replace-regexp.
\\ind{\([^}]+?\)}: The pattern to search for.
\\textbf{\1}\\index{\,(read-from-minibuffer "index content? " \1)}: The replacement text. The user will be prompted for the text to put in the braces following the \index{} element, using the original text between the braces following the \ind{} element as a default.
Note that when using query-replace-regexp, you'll have to confirm each choice by typing y after each. Use M-x replace-regexp if you want to avoid this step.
Vlad give you the LaTeX answer to your problem. An Emacs solution is the key-macro: start with
C-x (
to define a new macro, then do one step of your change, say:
C-s \ind{
<left>ex
Then copy and paste the argument in the \textbf macro... You have to be careful to move in a way that will be repeatable. Once the standard modification is done, you let the cursor after the whatever by default and end the definition by
C-x )
now C-x e will call the macro you just define, letting your cursor at the correct place to change the part you want to change You can also repeat the e to call the macro several time at once.
Why not just redefine the \ind so that it can get an optional argument?
For example:
\newcommand{\ind}[2][]{%
\def\first{#1}%
\ifx\first\empty
\textbf{#2}\index{#2}%
\else
\textbf{#2}\index{#1}%
\fi
}
This way you can use \ind{whatever} or \ind[whatever-else]{whatever}.

emacs + vimpulse-visual-mode + "linewise" text selection

Is it possible to make visual-line-mode (one after pressing V from normal mode) conduct as if first mark was in the beginning of the first line of selection and second mark - end of the last line?
For an example, currently after V, j and M-x comment-dwim:
here<cursor>is a
simple example
becomes
here;; is a
;; simp
le example
whereas desired result is often:
;; here is a
;; simple example
Of course, one can write a wrapper for comment-dwim, but I suspect/hope that there is a more correct solution.
Thank you in advance.
Doesn't V (vimpulse-visual-toggle-line) already do that?
Linewise selection will select whole lines. (I use this all the time)
The behaviour you're talking about will occur if you're using v (vimpulse-visual-toggle-char).
comment-dwim calls comment-or-uncomment-region to perform the actual commenting on the marked region. There is no option to extend the region to beginning of the first line and/or end of the last line. You will have to write a wrapper or advice comment-or-uncomment-region to achieve the effect you want.

Is there a way to display a macro list similar to displaying your mappings in Vim?

I know there is a way to list mappings via :map (or :imap, :cmap, etc.), but I can't find a way to list macros I have stored in my vimrc file (as in let #a = 'blahblah').
Is there a way to do this without having to manually looking inside it (via :split [myvimrcfile] or whatever way)?
Also, if it is possible, is there a way to attach some sort of documentation that would display with the macro to explain what it is for? I have a handful that I use quite a bit, but about 6 weeks apart. It would be nice to just quickly list them along with a comment that tells me what the macro does (or even just a name so I make sure I use the right one).
Thanks
In vim, the macros are just stored in registers. You can recall the content of any register and execute it as a macro (which is what the # does). To see a list of what is in your registers, use :reg.
You can see the contents of all the registers using the
:reg
command. Or an argument string like this
:reg ahx
will show you the contents of registers a, h, and x.
That way you can at least see what sequence of commands will be run and hopefully that will be clear enough for you to tell one from another.
The registers simply contain text. You can paste the command sequence in as text or you can copy text into a register and then run it as a command, depending on how you access the register.
I have not found any direct way to edit the contents of a register, but you can paste it into the file, edit it, and then save it back to the same register.
IHTH.
As /u/jheddings wrote the macros are stored as registers and what counts is the assignment of the code to the register (usually done in the vimrc files with let #a=blahblah
To ease the way to display the macros you defined in your vimrc file (in my case it is in the ~/.vimrc path) you can use this vim function:
function! ShowMacros()
10new
exe 'r!' . 'grep -B 1 -E "^\s*let #" ~/.vimrc'
call cursor(1,1)
endfunction
What it does:
10new - open a new vim window with ten lines size
exe ... - execute a command and put in the window
call ... - go to the first line first column
You can execute this function by tipping in the normal mode
:call ShowMacros
You could additionally create a key mapping or a command to fasten the way to call the function:
:cnoremap sm call ShowMacros()<CR>
command! sm call ShowMacros()`
This is the original post where I wrote the function similar to the above.
The OP asked, "is there a way to attach some sort of documentation that would display with the macro to explain what it is for?"
I have found VI / VIM macros extremely obtuse to understand even a week after I've written them, so I heartily support the idea of documentation. I have a suggestion for that, in two parts.
First is the process of documenting the macro in your .vimrc. I've developed the following .vimrc comment format that helps me understand, a week or a year or more later, what a macro is supposed to be doing. E.g.:
"
"= GENERIC CLIPBOARD YANK <F2>y (Y for Yank)
"= Yank the entire contents of the file into the clipboard; quit without saving.
"
"define F2 followed by y to be:
"| Go to line 1.
"| | From there, into the * buffer (system clipboard),
"| | | yank to the end of the file.
"| | | | Go to sleep for 1 second (to allow the clipboard to be updated).
"| | | | | Quit without saving the file.
"| | | | | |
map #2y 1G"*yG1gs:q!<CR>
"-------"-"-"-"--"------
Second, I am imagining that Jakub's ShowMacros() function above could be modified to grep a specific set of Help lines for each macro that would be in the file along with the definition, much the way the above command-line breakdown is attached to the definition, that would provide the needed User Help.
I've flagged two lines above with "= at the beginning of each, so that they can become the User Help. Then Jakub's grep command would search for "^\"= ". Here's the command I used. I'm not sure if the -E for Extended Regular Expressions is needed and the -B 1 is a nice touch to include one line previous to a matching sequence, so here I have an explicitly empty comment line.
In my vimrc, I only needed one backslash, for the initial parsing of the definitions. Here's the line, replacing the one in Jakub's function definition above:
exe 'r!' . 'grep -B 1 -E "^\"= " ~/.vimrc'
Thanks to Jakub's hint, I now can generate help from my .vimrc in pretty much exactly the way the OP is asking for. I've been using vi since 1983, so I'm pretty stoked.
Thanks Jakub!
IHTH,
August