emacs define-generic-mode why cannot use regexp-opt? - emacs

I am trying to make simple major mode for syntax highlighting using define-generic-mode. I found that
(define-generic-mode 'mytest-mode
'("//") nil
'(
((regexp-opt '("int" "string" "bool")) . 'font-lock-type-face)
)
nil nil "mytest mode"
)
is not working. But if I replace regexp-opt call with its manually calculated result, then all works as expected:
(define-generic-mode 'mytest-mode
'("//") nil
'(
("\\(?:bool\\|int\\|string\\)" . 'font-lock-type-face)
)
nil nil "mytest mode"
)
So, why I cannot just put regexp-opt call in the mode definition?
EDIT
Hint about forced evaluation of items in quoted list from Lindidancer's answer:
(define-generic-mode 'mytest-mode
'("//") nil
'(
(,(regexp-opt '("int" "string" "bool")) 'font-lock-type-face)
)
nil nil "mytest mode"
)
doesn't help: no errors on mode activation but no highlighting also
Second hint about use list function to form lists:
(define-generic-mode 'mytest-mode
'("//") nil
(list
((regexp-opt '("int" "string" "bool")) 'font-lock-type-face)
)
nil nil "mytest mode"
)
gives error on activating mode: (invalid-function (regexp-opt (quote ("int" "string" "bool"))))
same error when trying evaluate:
(list
((regexp-opt '("int" "string" "bool")) 'font-lock-type-face)
)
in scratch buffer.
EDIT 1
(list (list (regexp-opt '("int" "string" "bool")) 'font-lock-type-face))
doesn't help also - no errors, no highlighting.
EDIT 2
Steps, what I exactly do, are:
Execute define-generic-mode call in the *Scratch* buffer
Switch to buffer with some keywords under test
M-x mytest-mode

It's because the call to regexp-opt is inside a quoted list, so it isn't seen as a function call.
You can either create the list using functions like list or use backquotes, where a , means that the next form should be evaluated.
`(
(,(regexp-opt '("int" "string" "integer" "bool" "boolean" "float")) . 'font-lock-type-face)
)

(define-generic-mode 'mytest-mode
'("//") nil
`(
(,(regexp-opt '("int" "string" "bool")) . 'font-lock-type-face)
)
nil nil "mytest mode"
)

Related

Can Org-Babel code be converted to Elisp?

I have an org-babel source, which accesses a server via tramp and runs a shell script there. Is it possible to convert this source block into an Elisp function?
#+BEGIN_SRC sh :dir "/pscp:putty-connection-xy:/dir-yz"
expect -c '
spawn bash -c "scp file-to-copy user#server:/home1/dir-xy"
expect {
"(yes/no)?" {
send "yes\r"
expect "*?assword:*"
send "secretPassWord\r"
}
"*?assword:*" {
send "secretPassWord\r"
}
}
expect eof
'
#+END_SRC
Use Tramp's multi-hop (untested):
(copy-file "/plink:putty-connection-xy:/dir-yz/file-to-copy"
"/plink:putty-connection-xy|ssh:user#server:/home1/dir-xy/")
This uses plink and ssh, 'tho. If you can connect user#server directly from your local machine, you could shorten this, using pscp:
(copy-file "/pscp:putty-connection-xy:/dir-yz/file-to-copy"
"/pscp:user#server:/home1/dir-xy/")
The solution is simple. I call the block and give it over
'sh', the code and the parameters of the block. It works
(org-babel-execute-src-block nil
'("sh"
"cd /home1/
expect -c '
spawn bash -c \"scp file-to-copy user#server:/home1/dir-xy .\"
expect {
\"*?assword:*\" {
send \"secretPassWord\\r\" } }
expect eof'
"
((:colname-names) (:rowname-names)
(:result-params "raw" "replace")
(:result-type . value) (:results . "silent")
(:exports . "code")
(:tangle . "no") (:hlines . "no") (:noweb . "no")
(:cache . "no") (:session . "none")) "" nil nil ))

Append the nested case statement content with outer case statement's content using perl

In this situation we have to deal with nested case statements, which you can observe by seeing the input file and output.
INPUT FILE
case name in
ABSI) one="1"
two="2"
;;
DEV)
one="11"
two="22"
case nest in
kmr) three="3"
;;
sug) four="4"
five="5"
case next_level in
CAC)six="6"
;;
esac
;;
esac
;;
DUL) seven="7"
nine="9"
case again in
NOV) six="66"
ten="10"
;;
esac
;;
esac
**OUTPUT SHOULD BE **
ABSI:one="1"
ABSI:two="2"
DEV:one="11"
DEV:two="22"
DEV:kmr:three="3"
DEV:sug:four="4"
DEV:sug:five="5"
DEV:sug:CAC:six="6"
DUL:seven="7"
DUL:nine="9"
DUL:NOV:six="66"
DUL:NOV:ten="10"
I got the output for one level nested case statement. first I saved the content between first "case" and last "esac" (same as "end") in a temp file and run the below given script
open (data,"<input.txt");
while (<data>) {
$para1; $para2;
unless (/case/../esac/){
if(/(.*)\)(.*)$/) {
$para1=$1;
$var=$2;
}
else { $var=$_; }
print $para1.$var."\n";
}
if (/case/../esac/) {
if(/(.*)\)(.*)$/) {
$para2=$1;
$var=$2;
}
else { $var=$_; }
print $para1.$para2.$var."\n";
} }
close data;
I need your help and suggestion to get output for multiple nested case statement.
Thank you.
Keep an array containing the current levels. Push another level onto it whenever you see a xxx) line and pop the latest one off when you see a ;; line. Then you just need to look for the assignment statements.
This seems to work for your test data.
#!/usr/bin/perl
use strict;
use warnings;
# We use modern Perl here - specifically say()
use 5.010;
my #levels;
while (<DATA>) {
if (/(\w+)\)/) {
push #levels, $1;
}
if (/(\w+="\w+")/) {
say join(':', #levels), ":$1";
}
if (/;;/) {
pop #levels;
}
}
__DATA__
case name in
ABSI) one="1"
two="2"
;;
DEV)
one="11"
two="22"
case nest in
kmr) three="3"
;;
sug) four="4"
five="5"
case next_level in
CAC)six="6"
;;
esac
;;
esac
;;
DUL) seven="7"
nine="9"
case again in
NOV) six="66"
ten="10"
;;
esac
;;
esac
The output is:
ABSI:one="1"
ABSI:two="2"
DEV:one="11"
DEV:two="22"
DEV:kmr:three="3"
DEV:sug:four="4"
DEV:sug:five="5"
DEV:sug:CAC:six="6"
DUL:seven="7"
DUL:nine="9"
DUL:NOV:six="66"
DUL:NOV:ten="10"

What does `error: expected open delimiter` when calling rust macro mean?

I have such a macro:
macro_rules! expect_token (
([$($token:matchers, $result:expr)|+] <= $tokens:ident, $parsed_tokens:ident, $error:expr) => (
match $tokens.pop() {
$(
Some($token) => {
$parsed_tokens.push($token);
$result
},
)+
None => {
$parsed_tokens.reverse();
$tokens.extend($parsed_tokens.into_iter());
return NotComplete;
},
_ => return error(expr)
}
);
)
when I call it with expect_token!([Ident(name), name] <= tokens, parsed_tokens, "expected function name in prototype"); I get the error "error: expected open delimiter".
What does this error mean and what I am doing wrong?
P.S. If you are wondering what is the definition of identifiers like NotComplete, you can look at https://github.com/jauhien/iron-kaleidoscope/blob/master/src/parser.rs, but it is not relevant for this question as far as I understand, as the problem is not with the macro body, but with its invocation.
Ok, I have found the response: matchers in macros invocation should be enclosed in parenthesis. The problem was in my misunderstanding of matchers as left hand side of match rules, while they are lhs of the => in macro rules, which is clearly stated in documentation.
P.S. What about the whole macros I gave as example it is wrong anyway. )

Sed : Add a line at the starting of each TCL proc

I have a TCL proc like this, & want to add a line after the start of the proc, the puts "puts " entered myproc" " line
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
Can you help?
& it should also work for
proc myproc2 { N val } {
puts " entered myproc"
# comment line
set ret {} for { set i 0 } { $i < $N } { incr i } { lappend ret $val }
return $ret
}
If all you want to do is get an execution trace of your code, such as a call stack dump etc, then you don't need to modify your source code at all. You can use tcl itself to do it for you.
Tcl has no reserved keywords, none at all. Not even proc is reserved. You can therefore redefine it:
rename proc _proc
# Now proc no longer exists but we have _proc instead.
# Use it to redefine "proc":
_proc proc {name arguments body} {
set body "puts \"entered $name\";$body"
_proc $name $arguments $body
}
Just do that before running any of your own code and you'll find that every proc prints out when it's being entered on each call.
This is how a lot of tcl debuggers and profilers work - using tcl to redifine itself.
From your comments it looks like you're trying to also print how deep the stack is with each call. To do that you need to add more code to each proc definition. The most straightforward way is of course something like this:
_proc proc {name arguments body} {
set preamble"set dist2top \[info level\];puts \"\$dist2top entered $name\""
set body "$preamble;$body"
_proc $name $arguments $body
}
But as you can see, writing code inside strings can quickly become unmanagable. There are several tricks you can use to make it more manageable. One of the more common is to split $body by line and use list commands to manipulate code. It should reduce at least one level of quoting hell. My favorite is to use a templating technique similar to how you'd write html templates in MVC frameworks. I usually use string map for this:
_proc proc {name arguments body} {
_proc $name $arguments [string map [list %NAME% $name %BODY% $body] {
set dist2top [info level]
puts "$dist2top entered: %NAME%"
%BODY%
}]
}
The last argument in the _proc definition is just a string but it looks like a code block which makes it easier to read. No nasty quoting hell with this technique.
Using awk you can do:
awk '/^ *proc/ {$0 = $0 "\nputs \" entered myproc\""} 1' RS= proc-file.tcl
Gives this file:
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"

Command line string Variable comparison

I've been trying to compare my computername to some pre-set string. From reading around on google, namely http://commandwindows.com/batchfiles-branching.htm, I've attempted the following and many variants of the same line with /I, "%ComputerName", A513242 etc
IF (%ComputerName% == "A513242") (
EXIT) ELSE (
ECHO "else taken")
where "A513242" is the result of calling ECHO %ComputerName%
this seems to always take the "else taken" branch.
Any help as to why the (EXIT) case is not being taken/ what syntactical mistake I am making would be appreciated.
Try this:
if "%ComputerName%"=="A513242" (exit) else (echo "else taken")