How to create an emacs macro for text templates - c++

I am new to lisp and I am having trouble figuring out how to create a macro in emacs with the following functionality: Say I am tired of writing out the pattern in c++ for a for loop:
for (int i = 0; i < N; i++) {
}
Call this macro "forloop" then I would like to do the following: when I type "M-x forloop" the macro prints out
for (int
in the buffer and waits for an input. Then I type "i" and hit return after which the macro continues and prints
for (int i = 0; i <
And again waits for input. Finally after I type "N" and hit return the macro finishes by printing the rest:
for (int i = 0; i < N; i++) {
}
After some extensive reading and testing, I was able to write simple lisp functions, create my own macros, save them and call them and so on... but I still can't quite figure out how to make a macro that does something like I have described above. Any thoughts would be much appreciated! Thanks in advance!
Macros like this could be really nice for speeding up coding in any language. I would prefer the macro to be dynamic in the way described so that you don't have to remember how many arguments it needs and in which order they go when calling it.

I use yasnippet (http://www.emacswiki.org/emacs/Yasnippet) for this, but there are a lot of other solution.
In yasnippet you type a keyword for you snippet (say for) then the yasnippet key shortcut, then you have field to fill, using tab to go from one field to the next.
Every snippet is define in is own file in some easy to learn DSL.

I don't know anything better than yasnippet for this problem.
Here's the relevant snippet:
# -*- mode: snippet -*-
#name : for (...; ...; ...) { ... }
# --
for (unsigned int ${1:i}=0; $1<${2:N}; ++$1)$0
Note that there are two arguments (zero is the exit point),
both have default values, but you can change them by just typing.
key binding for yasnippet
I highly recommend to bind yas/expand to C-o, so it
doesn't conflict with auto-complete-mode.
The default binding for this shortcut is near-useless, but it's in
a great position:
(global-set-key "\C-o" 'aya-open-line)
(defun aya-open-line ()
(interactive)
(cond ((expand-abbrev))
((yas/snippets-at-point)
(yas/next-field-or-maybe-expand-1))
(((yas/expand)))))
This way, the shortcut for expanding and moving to the next field
is the same, which makes you very quick.
Also note that expand-abbrev takes precedence: you can fill
an abbrev table for c++-mode for the stuff that you use.
Abbrevs don't take an argument, but they all live in one table,
instead of each yasnippet living in its own file, so it's
very easy to edit abbrevs.
special function to insert curly braces
I wouldn't recommend putting the braces in yasnippet,
since sometimes you need them and sometimes you don't.
I use this function instead:
(defun ins-c++-curly ()
"Insert {}."
(interactive)
(if (looking-back "\\()\\|try\\|else\\|const\\|:\\)$")
(progn
(insert " {\n\n}")
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
(insert "{}")
(backward-char))

You can see similar macros in sgml-mode.el, for example html-href-anchor, which inserts an HREF anchor (obviously :-).
You will get more specific answers if you tag this as [elisp].

If you are reading this and wondering exactly how to do what I requested with yasnippit, here is my yasnippit file:
# name: fori ... { ... }
# key: fori
# --
for (int ${1:intname} = 0; ${1:$(yas-substr text "[^: ]*")} < ${2:max}; ${1:$(yas-substr text "[^: ]*")}++) {
$0
}
Note that yasnippit already has a function for "for" in c++ mode, but I did not like the way it behaved.
Conclusion, yasnippit is awesome and super easy! Thanks for the suggestion!

Related

Standard ML multiple condition statement

I am about finished with a script I am writing but I have one last condition statement to add to my function.
fun whileloop (x:real,a:int,b:real) =
if (a<1)
then (x,a,b)
else whileloop(x+1.0,a-1,b-1.0)
This is my current loop I have created. It is basically accomplishing everything I need under one exception. I want it to exit its loop once the b variable hits zero[if this happens before a reaches zero). I believe Standard ML will not let me do a condition statement for a real variable...such as b<1.0. just to give you an idea of what I am trying to accomplish...I want the following code to work below:
fun whileloop (x:real,a:int,b:real) =
if (a<1 or b<1.0)
then (x,a,b)
else whileloop(x+1.0,a-1,b-1.0)
of course this code does not work due to the syntax and a condition statement being checked against a real number...but how could I accomplish this task while keeping my skeleton somewhat intact. I simply want to add another if condition statement to the existing skeleton. In C++ this was a fairly simple task.
Here is the answer. Thanks to John Coleman.
fun whileloop (x:real,a:int,b:real) =
if (a<1 orelse b<1.0)
then (x,a,b)
else whileloop(x+1.0,a-1,b-1.0)

How to get clang-format to align chained method calls

I've joined an existing project and I'm the first team member to use clang-format. The existing style mostly matches except for a couple of annoying differences. Here's one (the other one being here):
folly::dynamic makeRequest(const string &response) {
return folly::dynamic::object()
("log_type", "FOO")
("src_id", "42")
("dst_id", "666")
("success", true);
}
clang-format insists on formatting it like this:
folly::dynamic makeRequest(const string &token_response) {
// using longer variable names to highlight using up the whole line lenght
return folly::dynamic::object()("log_type", "FOO")(
"src_id", somethingId)("dst_id", whateverId)("success",
sucess);
}
In the former style I don't feel strongly for how continuation lines are indented, as long as we get one method invocation per line. Is that possible?
Not the best possible solution, but you can force line breaks by putting "//" after each line:
return folly::dynamic::object() //
("log_type", "FOO") //
("src_id", "42") //
("dst_id", "666") //
("success", true);
Another approach that I have used myself is to turn off clang-format for the specific block of code.
// clang-format off
return folly::dynamic::object()
("log_type", "FOO")
("src_id", "42")
("dst_id", "666")
("success", true)
;
// clang-format on
This might not be optimal if you have more complicated logic inside the chained method params (since you will want that logic to be formatted), but if you just have a tuple like this it can be cleaner than adding empty comments.
Both ways you are bypassing clang-format, but this way is cleaner (imo) and signifies your intentions more clearly to future developers.

SLOC in cppcheck

I want to write checker that can be added to other checkers in CppCheck. This checker must check SLOC of all member function, for example the function should contain no more than 200 significant lines of code. But in CppCheck I only found method that checks the existence of a body hasBody(), but not a count of lines.
I am a cppcheck developer. I am no expert in this topic. I think it depends on exactly what you want to count. how many lines is this:
void f() { int x=3; int y=x+2; dostuff(x+y+4); }
I would guess that you want to go through the tokens and count semicolons or something:
for (tok = functionScope->classStart; tok != functionScope->classEnd; tok = tok->next()) {
if (tok->str() == ";")
++lines;
}
I think this checker you suggest is interesting but it does not fit well in the core cppcheck tool. I would suggest that you write an addon. I will be happy to add it in our addons folder and show it in the GUI etc.
By the way.. I have thought that it would be nice to integrate (execute and read results) ohcount, cccc, or whatever in the GUI so extended statistics can be shown.

Visual Studio Breakpoint Macro to modify a value?

I'm debugging an application (C++), and I've found a point in the code where I want to change a value (via the debugger). So right now, I've got a breakpoint set, whereupon I do:
Debugger reaches breakpoint
I modify the variable I want to change
I hit F5 to continue running
lather, rinse, repeat
It's hitting this breakpoint a lot, so I would like to automate this. I would like to set the Breakpoint to run a macro, and continue execution.
However, I have no experience writing VisualStudio macros, so I don't know the commands for modifying a variable of the executing program. I've looked around, but haven't found anything helpful online so far.
I found how to do this with a macro. Initially, I tried using Ctrl-Shift-R to record a macro of keystrokes, but it stopped recording when I did Ctrl-Alt-Q. But I was able to edit the macro to get it to work. So here's what I did, in case anyone else wants to do something similar.
Tools -> Macros -> Macro Explorer
Right Click -> New macro
Public Module RecordingModule
Sub setvalue()
DTE.Debugger.ExecuteStatement("variable_name=0")
End Sub
End Module
This macro will execute the assignment statement, setting my variable (in this case, making it a NULL pointer).
Right Click on a BreakPoint -> When Hit...
Check "Run a macro"
Select Macros.MyMacros.RecordingModule.setvalue
Check "Continue execution"
Click OK
Then, I was able to run my program, automatically adjusting a pointer to NULL as it went. This was very useful for testing, and did not require recompiling.
Looking for similar today and found that you can also use the 'Print a message:' option instead of a macro. Values from code can be printed by placing them inside {}. The key is that VS will also evaluate the content as an expression - so {variable_name=0} should achieve the same as the macro example.
If you are think of a macro in the same way as Microsoft excel, then you're out of luck. It doesn't quite work that way.
In C++, a macro refers to a small inline function created with #define. It is a preprocessor, so a macro is like using a replace on all its references with its body.
For example:
#define add(a,b) ((a)+(b))
int main() {
int a=3, b=4, c=5, d=6, e, f;
d = add(a,b);
e = add(c,d);
}
Would like to the c++ compiler as:
int main() {
int a=3, b=4, c=5, ...;
d = ((a)+(b));
e = ((c)+(d));
}
Now, back to your question. If the variable is within scope at this breakpoint, just set it from within your code:
myVar = myValue;
If it is not, but it is guaranteed to exist, you may need a little hack. Say that this variable is an int, make a global int pointer. If this variable is static, make sure to set it to its address, and back to NULL inside it's scope. If it is dynamic, you may need some extra work. Here is an example:
int* globalIntPointer;
void func() {
*globalIntPointer = 3;
//...
}
int main() {
int a = 5;
globalIntPointer = &a;
func();
//...
globalIntPointer = NULL; // for safety sake
return 0;
}
You can execute a VS macro when a breakpoint is hit (open the breakpoints window, right click on the breakpoint in question, and select "When Hit..." off the popup menu). I'm less certain about writing a macro that modifies a variable of the program under debug though -- I've never done that, and a quick try with attempting to record a macro to do it doesn't seem to work (all it records is activating the right window, not changing the value).
Select "Condition..." and write an assignment for the variable in question in the "Condition:" textbox. This will naturally resolve to "true" with it not being an actual conditional test. Therefore, the breakpoint is never hit, and your variable has been set accordingly.

Is there any way to make Visual Studio stop indenting namespaces?

Visual Studio keeps trying to indent the code inside namespaces.
For example:
namespace Foo
{
void Bar();
void Bar()
{
}
}
Now, if I un-indent it manually then it stays that way. But unfortunately if I add something right before void Bar(); - such as a comment - VS will keep trying to indent it.
This is so annoying that basically because of this only reason I almost never use namespaces in C++. I can't understand why it tries to indent them (what's the point in indenting 1 or even 5 tabs the whole file?), or how to make it stop.
Is there a way to stop this behavior? A config option, an add-in, a registry setting, hell even a hack that modifies devenv.exe directly.
As KindDragon points out, Visual Studio 2013 Update 2 has an option to stop indenting.
You can uncheck TOOLS -> Options -> Text Editor -> C/C++ -> Formatting -> Indentation -> Indent namespace contents.
Just don't insert anything before the first line of code. You could try the following approach to insert a null line of code (it seems to work in VS2005):
namespace foo
{; // !<---
void Test();
}
This seems to suppress the indentation, but compilers may issue warnings and code reviewers/maintainers may be surprised! (And quite rightly, in the usual case!)
Probably not what you wanted to hear, but a lot of people work around this by using macros:
#define BEGIN_NAMESPACE(x) namespace x {
#define END_NAMESPACE }
Sounds dumb, but you'd be surprised how many system headers use this. (glibc's stl implentation, for instance, has _GLIBCXX_BEGIN_NAMESPACE() for this.)
I actually prefer this way, because I always tend to cringe when I see un-indented lines following a {. That's just me though.
Here is a macro that could help you. It will remove indentation if it detects that you are currently creating a namespace. It is not perfect but seems to work so far.
Public Sub aftekeypress(ByVal key As String, ByVal sel As TextSelection, ByVal completion As Boolean) _
Handles TextDocumentKeyPressEvents.AfterKeyPress
If (Not completion And key = vbCr) Then
'Only perform this if we are using smart indent
If DTE.Properties("TextEditor", "C/C++").Item("IndentStyle").Value = 2 Then
Dim textDocument As TextDocument = DTE.ActiveDocument.Object("TextDocument")
Dim startPoint As EditPoint = sel.ActivePoint.CreateEditPoint()
Dim matchPoint As EditPoint = sel.ActivePoint.CreateEditPoint()
Dim findOptions As Integer = vsFindOptions.vsFindOptionsMatchCase + vsFindOptions.vsFindOptionsMatchWholeWord + vsFindOptions.vsFindOptionsBackwards
If startPoint.FindPattern("namespace", findOptions, matchPoint) Then
Dim lines = matchPoint.GetLines(matchPoint.Line, sel.ActivePoint.Line)
' Make sure we are still in the namespace {} but nothing has been typed
If System.Text.RegularExpressions.Regex.IsMatch(lines, "^[\s]*(namespace[\s\w]+)?[\s\{]+$") Then
sel.Unindent()
End If
End If
End If
End If
End Sub
Since it is running all the time, you need to make sure you are installing the macro inside in your EnvironmentEvents project item inside MyMacros. You can only access this module in the Macro Explorer (Tools->Macros->Macro Explorer).
One note, it does not currently support "packed" namespaces such as
namespace A { namespace B {
...
}
}
EDIT
To support "packed" namespaces such as the example above and/or support comments after the namespace, such as namespace A { /* Example */, you can try to use the following line instead:
If System.Text.RegularExpressions.Regex.IsMatch(lines, "^[\s]*(namespace.+)?[\s\{]+$") Then
I haven't had the chance to test it a lot yet, but it seems to be working.
You could also forward declare your types (or whatever) inside the namespace then implement outside like this:
namespace test {
class MyClass;
}
class test::MyClass {
//...
};
Visual Studio 2017+
You can get to this "Indent namespace contents" setting under Tools->Options then Text Editor->C/C++->Formatting->Indention. It's deep in the menus but extremely helpful once found.
I understand the problem when there are nested namespaces. I used to pack all the namespaces in a single line to avoid the multiple indentation. It will leave one level, but that's not as bad as many levels. It's been so long since I have used VS that I hardly remember those days.
namespace outer { namespace middle { namespace inner {
void Test();
.....
}}}