Vim: Writing function skeleton - formatting

When writing new functions with Vim I always seem to have to do a bit of "manual" work.
x = Cursor position
If I start typing a function and insert a couple of curly braces and the end
function Apples() {x}
Then hit Enter, it obviously looks like this
function Apples() {
x}
Which results in me having to ESC,O in order to shift the closing curlybrace down.
While this may seem like a trivial matter, doing this over the last 5 months is getting bothersome, and I know there are plenty like me out there who knows there should be an elegant solution to this. I am open to plugin-suggestions.

You can use a simple mapping like this one (there are dozens of variants floating around SO and the web):
inoremap {} {<CR>}<C-o>O
You can also search www.vim.org for a dedicated plugin.
But I strongly recommend you to try a snippet-expansion plugin like Snipmate or UltiSnips. Both plugins follow the same model but they have slightly different snippet syntaxes and features. It works like that:
you type a trigger:
fun
you hit <Tab> and you get the following with function_name in select mode:
function [function_name]() {
}
you type your desired name:
function Apples|() {
}
you hit <Tab> to place the cursor between the parentheses:
function Apples(|) {
}
you hit <Tab> again to place the cursor on the line below with the correct indentation:
function Apples() {
|
}

With lh-bracket (in C or C++ mode), when you hit enter whilst in between two brackets, the newlines you are expecting are inserted.
The idea is to test for: getline(".")[col(".")-2:col(".")-1]=="{}" and execute/insert "\<cr>\<esc>O" when the condition is true, or "\<cr>" otherwise.
Within lh-bracket, I have the following into a C-ftplugin:
call lh#brackets#enrich_imap('<cr>',
\ {'condition': 'getline(".")[col(".")-2:col(".")-1]=="{}"',
\ 'action': 'Cpp_Add2NewLinesBetweenBrackets()'},
\ 1,
\ '\<cr\>'
\ )
function! Cpp_Add2NewLinesBetweenBrackets()
return "\<cr>\<esc>O"
endfunction
I guess (code not tested) it would (*) translate into:
" put it into ftplugin/{yourfiltetype, javascript?}.vim
inoremap <buffer> <silent> <expr> <cr> s:SmartCR()
function s:SmartCR()
return getline(".")[col(".")-2:col(".")-1]=="{}"
\ ? "\<cr>\<esc>O"
\ : "\<cr>"
endfunction
(*) Actually, lh#brackets#enrich_imap does a few other things (the mapping is compatible with LaTeXSuite's IMAP.vim presence ; the mapping can be toggled on/off along with all the other mappings from lh-brackets)

Related

Maya MEL scripting how to read from an intField

Forgive me for asking a basic question on stack overflow, but documentation and simple guides on the mel scripting language have proved to be very hard to find.
In any case, I'm trying to write a simple mel script that automatically creates a low-poly railroad, just as a learning excercise. The general idea is that a popup window will appear asking for how many segments you want
I've managed to get the window to appear, but now I have a few additional questions.
Firstly, how do I read in the value from the intField when I hit the button that runs the main procedure? I can't find any relevant guides.
Second, I've noticed a new problem in which the main script (which I'm currently running with a default value) seems to be running multiple times. What I think is happening is that when I click the button, I hold it down a bit too long, and Maya registers this as me clicking the button multiple times. How can I modify the button so that It only registers one click when I click on it?
Here is my code:
/***
Auto-Railroad Creator and Rigger
***/
// This script creates a low-poly, rigged railroad thingy that an artist can move and twist into position.
//relevant variables:
//the number of ties
int $numSegments = 0;
//the procedure that actually creates the railroad
//Heads up, this procedure is NOT finished. I'm just trying to get the window stuff working before I move on to completing this.
global proc makeRails(int $segments)
{
//If the given length is zero, do nothing.
if ( $segments == 0) return;
///the code proper
CreatePolygonCube;
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;
// Result: pCube1 polyCube1 //
return;
}
//The procedure that opens the popup window which asks for details:
global proc jh_makeRail()
{
//delete window if it already exists
if (`window -q -ex jh_makeRail`) deleteUI jh_makeRail;
//main window
window -topEdge 30 -title "Create a low-poly rail segment"
-mxb false -s true -rtf false -mb false -mbv false -w 300 -h 440 jh_makeRail;
//window content
columnLayout -adjustableColumn true;
separator -w 240 -h 20;
text -label "Utility to automatically create a low-poly rig for a simple railroad segment";
separator -w 240 -h 25;
text -label "Rail segment length (measured by the number of ties):";
intField -minValue 0;
//How do I use the value of this intField?
separator -w 240 -h 20;
//Since I haven't figured out how to read in the value of the intField, I'm using a default value of 30.
button -label "Make Rail" -c "makeRails 30";
window -e -w 300 -h 500 jh_makeRail;
showWindow jh_makeRail;
}
//This here is supposed to be the "entry point" of the mel script, where the code starts doing things.
jh_makeRail;
So, good news. A kind person on reddit helped me solve the problem.
First, regarding the secondary procedure running twice... turns out I was wrong about that. It was making two cubes because I told it to.
I had believed that "CreatePolygonCube;" and "polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;" were two parts of the same instruction, but they are actually two different ways to make a cube.
Next, regarding the primary question... Transfering the value from the intField to a global variable involves some sort of shuffling.
The code this person suggested is as follows:
{
//You need to declare existing global vars in like this, almost like you're importing them into the proc
global int $numSegments;
//Create field
string $myIntField = `intField -minValue 0`;
//build command string
string $cmd = "$numSegments = `intField -q -value " + $myIntField + "`";
//set change command
intField -edit -changeCommand $cmd $myIntField;
}
(This is a part of the window function, not the whole thing.)
The relevant thread is here:
https://www.reddit.com/r/Maya/comments/q1vz1i/i_need_help_with_mel_scripting/hfjpoh7/?context=3
global int $numSegments;
Yeah, don't do this :)
Use the optionVar MEL command instead!
// define some custom name for your global variable
string $myName = "railroad_num_segments";
// set your global var like so:
global void railroadSetNumSegments(int $num) {
optionVar -intVal "railroad_num_segments" $num;
}
// and query the value like so:
global int railroadGetNumSegments() {
// check to see if we have previously registered the optionVar
if(!`optionVar -exists "railroad_num_segments"`) {
// if the option doesn't exist, define a 'sensible' default here
railroadSetNumSegments(1);
}
// return the user preference
return `optionVar -q "railroad_num_segments"`;
}
The advantage of optionVar is that your user preference is now stored between Maya sessions.
Whenever you need the number of segments in your script, simply call railroadGetNumSegments().
You can also simplify the intField control to just:
intField -minValue 0 -value `railroadGetNumSegments` -changeCommand "railroadSetNumSegments #1";
Specifying #1 in the change command, will automatically query the controls value when it changes.
Also worth noting that there are actually 3 ways to create a polyCube in Maya. The entirely manual approach would be:
use createNode to create the polyCube node, and a mesh node.
use connectAttr to connect the outMesh attribute of the poly cube node, to the "inMesh" attribute on the mesh node.
use the sets command to add the mesh to the default shading group set.
use setAttr to set the polyCUbe node params to the desired values
That is in effect what the polyCube MEL command does internally.
The "CreatePolygonCube" command uses optionVar, to read all of the user preferences for the default widths/heights/num divisions etc; and then passes those parameters to the polyCube command.

Can gather be used to unroll Junctions?

In this program:
use v6;
my $j = +any "33", "42", "2.1";
gather for $j -> $e {
say $e;
} # prints 33␤42␤2.1␤
for $j -> $e {
say $e; # prints any(33, 42, 2.1)
}
How does gather in front of forchange the behavior of the Junction, allowing to create a loop over it? The documentation does not seem to reflect that behavior. Is that spec?
Fixed by jnthn in code and test commits.
Issue filed.
Golfed:
do put .^name for any 1 ; # Int
put .^name for any 1 ; # Mu
Any of ten of the thirteen statement prefixes listed in the doc can be used instead of do or gather with the same result. (supply unsurprisingly produces no output and hyper and race are red herrings because they try and fail to apply methods to the junction values.)
Any type of junction produces the same results.
Any number of elements of the junction produces the same result for the for loop without a statement prefix, namely a single Mu. With a statement prefix the for loop repeats the primary statement (the put ...) the appropriate number of times.
I've searched both rt and gh issues and failed to find a related bug report.

TCL, How to name a variable that includes another variable

In TCL, I'm writing a procedure that returns the depth of a clock.
But since I have several clocks I want to name the var: depth_$clk
proc find_depth {} {
foreach clk $clocks {
…
set depth_$clk $max_depth
echo $depth_$clk
}
}
But I get:
Error: can't read "depth_": no such variable
Use error_info for more info. (CMD-013)
Your problem is this line:
echo $depth_$clk
The issue is that the syntax for $ only parses a limited set of characters afterwards for being part of the variable name; the $ is not part of that. Instead, you can use the set command with one argument; $ is effectively syntactic sugar for that, but the command lets you use complex substitutions.
echo [set depth_$clk]
HOWEVER!
The real correct thing to do here is to switch to using an associative array. It's a bit larger change to your code, but lets you do more as you've got proper access to substitutions in array element names:
proc find_depth {} {
foreach clk $clocks {
…
set depth($clk) $max_depth
echo $depth($clk)
}
}
echo ${depth}_$cell
This can help too.
Thanks !

perl6 Is there a way to do editable prompt input?

In bash shell, if you hit up or down arrows, the shell will show you your previous or next command that you entered, and you can edit those commands to be new shell commands.
In perl6, if you do
my $name = prompt("Enter name: ");
it will print "Enter name: " and then ask for input; is there a way to have perl6 give you a default value and then you just edit the default to be the new value. E.g.:
my $name = prompt("Your name:", "John Doe");
and it prints
Your name: John Doe
where the John Doe part is editable, and when you hit enter, the edited string is the value of $name.
https://docs.raku.org/routine/prompt does not show how to do it.
This is useful if you have to enter many long strings each of which is just a few chars different from others.
Thanks.
To get the editing part going, you could use the Linenoise module:
zef install Linenoise
(https://github.com/hoelzro/p6-linenoise)
Then, in your code, do:
use Linenoise;
sub prompt($p) {
my $l = linenoise $p;
linenoiseHistoryAdd($l);
$l
}
Then you can do your loop with prompt. Remember, basically all Perl 6 builtin functions can be overridden lexically. Now, how to fill in the original string, that I haven't figure out just yet. Perhaps the libreadline docs can help you with that.
Well by default, programs are completely unaware of their terminals.
You need your program to communicate with the terminal to do things like pre-fill an input line, and it's unreasonable to expect Perl 6 to handle something like this as part of the core language.
That said, your exact case is handled by the Readline library as long as you have a compatible terminal.
It doesn't look like the perl 6 Readline has pre-input hooks setup so you need to handle the callback and read loop yourself, unfortunately. Here's my rough attempt that does exactly what you want:
use v6;
use Readline;
sub prompt-prefill($question, $suggestion) {
my $rl = Readline.new;
my $answer;
my sub line-handler( Str $line ) {
rl_callback_handler_remove();
$answer = $line;
}
rl_callback_handler_install( "$question ", &line-handler );
$rl.insert-text($suggestion);
$rl.redisplay;
while (!$answer) {
$rl.callback-read-char();
}
return $answer;
}
my $name = prompt-prefill("What's your name?", "Bob");
say "Hi $name. Go away.";
If you are still set on using Linenoise, you might find the 'hints' feature good enough for your needs (it's used extensively by the redis-cli application if you want a demo). See the hint callback used with linenoiseSetHintsCallback in the linenoise example.c file. If that's not good enough you'll have to start digging into the guts of linenoise.
Another solution :
Use io-prompt
With that you can set a default value and even a default type:
my $a = ask( "Life, the universe and everything?", 42, type => Num );
Life, the universe and everything? [42]
Int $a = 42
You can install it with:
zef install IO::Prompt
However, if just a default value is not enough. Then it is better you use the approach Liz has suggested.

Xcode evaluating expressions while debugging

I am working on an iPhone app. I am a full-time Java developer and I am used to using Eclipse where I can put a breakpoint in and stop the process. Then, I can type in any expression that I want and Eclipse will evaluate it using the values from that point in the process.
Is there a way to do that in Xcode? I want to be able to stop at a breakpoint and then enter some code to evaluate it. The gdb console will let me do po (print-object), but it is really limited. Any help?
In XCode 4.0 this is sort of hidden in the GUI. When you're at a breakpoint you can probably see the Variables View inside the Debug Area; it's the pane which shows local variables and such. Right-click on the Variables View and select "Add Expression..."
I realize this is an old thread but it's still a top Google hit so I thought it worth answering.
My practice:
po [NSUserDefaults standardUserDefaults]
displays: <NSUserDefaults: 0x6143040>
po [[NSUserDefaults standardUserDefaults] stringForKey:#"Currency"]
displays: "CHF"
Use the "expression" command in the debugger. Using it is relatively simple. Just type the command expression and press enter. You will then be prompted enter an expression. Here is an example
(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
2+2
(int) $2 = 4
I also attached the help info for the expression command below. Hope this helps.
Evaluate a C/ObjC/C++ expression in the current program context, using user
defined variables and variables currently in scope. This command takes
'raw' input (no need to quote stuff).
Syntax: expression --
Command Options Usage:
expression [-f ] [-G ] [-a ] [-d ] [-t ] [-u ] --
expression [-o] [-a ] [-d ] [-t ] [-u ] --
expression
-G <gdb-format> ( --gdb-format <gdb-format> )
Specify a format using a GDB format specifier string.
-a <boolean> ( --all-threads <boolean> )
Should we run all threads if the execution doesn't complete on one
thread.
-d <boolean> ( --dynamic-value <boolean> )
Upcast the value resulting from the expression to its dynamic type
if available.
-f <format> ( --format <format> )
Specify a format to be used for display.
-o ( --object-description )
Print the object description of the value resulting from the
expression.
-t <unsigned-integer> ( --timeout <unsigned-integer> )
Timeout value for running the expression.
-u <boolean> ( --unwind-on-error <boolean> )
Clean up program state if the expression causes a crash, breakpoint
hit or signal.
Timeouts:
If the expression can be evaluated statically (without runnning code) then it will be.
Otherwise, by default the expression will run on the current thread with a short timeout:
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted
and resumed with all threads running. You can use the -a option to disable retrying on all
threads. You can use the -t option to set a shorter timeout.
User defined variables:
You can define your own variables for convenience or to be used in subsequent expressions.
You define them the same way you would define variables in C. If the first character of
your user defined variable is a $, then the variable's value will be available in future
expressions, otherwise it will just be available in the current expression.
Examples:
expr my_struct->a = my_array[3]
expr -f bin -- (index * 8) + 5
expr unsigned int $foo = 5
expr char c[] = "foo"; c[0]
IMPORTANT NOTE: Because this command takes 'raw' input, if you use any
command options you must use ' -- ' between the end of the command options
and the beginning of the raw input.
Not answering question about Xcode, but JetBrains' AppCode does this in the standard IDE way most of us know from other platforms.