Jump to content
Sign in to follow this  
sbsmac

Squint - the sqf editor and error-checker

Recommended Posts

Thanks - I was wondering what to write next! Indentation - lex or parse ?

No problem, it was an interesting read and I learnt new stuff. Just don't forget to write stuff in .Net too :).

Oh and stop calling me MuzzleFlash dammit :D!!!!!!

Share this post


Link to post
Share on other sites

My apologies Mr Flash, it has now been corrected ;-)

Share this post


Link to post
Share on other sites

When you open a pbo, you'll notice that sqint shows you all the files inside that pbo and you can edit these as text. (This even works for binarised 'rap' files.).

If you modify an sqf file (for example) from the pbo and then save it, the sqf file will be written back into the pbo and then the pbo will be written back to disk - in other words you can edit files inside a pbo 'in place' without ever having to worry about manually extracting or repacking the pbo yourself.

There are a couple of areas where this needs a little tweaking...

1) If you use 'save as' to save a file from a pbo under a different name, you get the standard file dialog which makes it look like you are saving to disk. In fact you end up saving to pbo with a path that looks like a fully-qualified disk-path. Not good !

2) You can't yet save unbinarised rap files back to rap again after modifying them. I actually have this working on my debug build but there are a couple of corner cases where you could lose data so it's currently disabled for release builds.

When I rework the file-list I'll probably make it a lot easier to transfer files between domains - ie it will be possible to take all the files inside a pbo and drop them to disk as text files etc. Hope that explains it - feel free to follow up if you still have questions.

The main point though is that if you just stick to 'Save' or 'Save all' everything will work correctly and you can save yourself a lot of time by not having to muck around with pbo-extractors :)

---------- Post added at 04:30 PM ---------- Previous post was at 03:13 PM ----------

1.0.0.89 is now out...

*Bug #13197: Add option to disable line numbers

*Bug #13233: Add tabs-to-spaces conversion under Tools menu

*Bug #13234: Move auto-complete enable/disable to new settings/editor dialog

*Bug #13235: Implement basic auto-indent

*Task #13230: disallow format in sqf files

You can read about the auto-indent on this page. It's not terribly sophisticated but works well enough for basic editing and is pretty similar to how emacs works. It has a few little quirks - to TAB-indent a closing brace you need to put the cursor on the line below and you can probably find other cases where it is less-than-perfect (comments on the same line after an opening brace for example).

(And no, before you ask, I haven't yet made the insert-private-array work with it...)

Edited by sbsmac

Share this post


Link to post
Share on other sites

Awesome, just made a script in 10 minutes to remove dead bodies in 100 lines. It worked right out of squint no bug to solve. Normally there would be a pair of minor syntax errors at least. No bugs:

/*
Script to remove dead bodies.
Muzzleflash

!!! Should not be used with units in which you want to keep the group !!!

** Initialize **

[TYPE, PARAMS] "run" BR_Initialize.sqf;
Probably best run separate!
Type can be:
"INTERVAL" - Bodies will be removed at PARAMS seconds intervals
"DELAYED" - Bodies will be removed a PARAMS seconds after death

** Exposed functions **
grp call BR_AddGroup
obj call BR_AddObject
arr call BR_AddArray
*/

#define __Push(arr,var) arr set [count arr, var];

//Only server. "killed" event handler local etc..
if (!isServer) exitWith {};

BR_Type = toUpper (_this select 0); //Type of body remover
BR_Params = _this select 1; //Parameters

if (BR_Type == "DELAYED") then {
   BR_Delay = BR_Params;
};
if (BR_Type == "INTERVAL") then {
   BR_Interval = BR_Params;
};

//The actual list of items to be removed
BR_ToBeRemoved = [];

/********"Exposed" functions ********/
BR_AddObject = {
  _this call BR_AddDeadEvent;
};

BR_AddGroup = {
   {_x call BR_AddObject} forEach (units _this);    
};

BR_AddArray = {
   {_x call BR_AddObject} forEach _this;
};
/*************************************/

//Add killed event 
BR_AddDeadEvent = {
   _this addEventHandler ["killed", {(_this select 0) call BR_AddToBeRemoved}];
};

//Adds object to be removed
BR_AddToBeRemoved = {
   private ["_val"];
   if (BR_Type == "INTERVAL") then {
       __Push(BR_ToBeRemoved, _this)       
   };
   if (BR_Type == "DELAYED") then {
       _val = [_this, time+BR_Delay];
       __Push(BR_ToBeRemoved, _val)
   };
};

//Removes body
BR_RemoveBody = {
  private ["_body","_grp"];
  _body = _this;
  _grp = group _this;
  //Delete body
  if (isNull _body || alive _body) exitWith {};
  deleteVehicle _body;
  sleep 0.13;
  if (count units _grp <= 0) then {
      deleteGroup _grp;
  }; 
};

BR_IntervalRemover = {
   while {sleep BR_Interval; true} do {
       //Remove body
       {_x call BR_RemoveBody} forEach BR_ToBeRemoved;
       sleep 0.43;
       //Remove null references
       BR_ToBeRemoved = BR_ToBeRemoved - [objNull];
   };
};

BR_DelayedRemover = {
   private ["_idx","_obj"];
   while {sleep 5.3; true} do {
       //Count number of indices to remove
       _idx = 0;
       while {time >= ((BR_ToBeRemoved select _idx) select 1)} do {
           _idx = _idx + 1;
           sleep 0.06;
       };
       //Remove those indices
       for "_i" from 0 to (_idx -1) do {
           _obj = (BR_ToBeRemoved select _i) select 0;
           _obj call BR_RemoveBody;
           BR_ToBeRemoved set [_i, objNull]; //Flag it as null
           sleep 0.12;
       };
       sleep 0.28;
       //Remove those bad references
       BR_ToBeRemoved = BR_ToBeRemoved - [objNull];      
   };
};

//Spawn the handler
if (BR_Type == "INTERVAL") then {
   [] spawn BR_IntervalRemover;
};
if (BR_Type == "DELAYED") then {
   [] spawn BR_DelayedRemover;
};

BR_HasInitialized = true;

squint complained when I put the right hand side of _val into the macro:

_val = [_this, time+BR_Delay];
__Push(BR_ToBeRemoved, _val)

Where __Push is:

#define __Push(arr,var) arr set [count arr, var];

Is it that really true. Can the preprocessor not comprehend this? squint said something like wrong number of arguments. Haven't worked with C for years and that was very basic, I did not do much work with the preprocess there.

Share this post


Link to post
Share on other sites

I think you mean squint complained when you wrote

__Push(BR_ToBeRemoved,_[_this, time+BR_Delay])

IIRC the C proprocessor has no problem with this but the OFP/A2 preprocessor is a bit simpler and doesn't 'see' the square brackets inside the macro argument list. So it tries to execute the following (colours used to indicate separate arguments)

__Push( BR_ToBeRemoved , [_this , time+BR_Delay] )

Ie, it sees 3 arguments rather than 2 ! This has actually caught me out a couple of times in the past. :(

Squint (naturally) does its best to emulate the quirks of the Arma preprocessor rather than implementing a C preprocessor. There are a few more 'interesting' characteristics - for example try

#define A(FOO) FOO BAR

#define B(BAR) A(BAR)

B(argument)

then look at the preprocessed output if you want a surprise. Believe it or not this really is the way the ArmA PP works !

Sickboy was very helpful in pointing out all the ways in which early versions failed to produce 'matching' output when thrown at ACE (which makes very extensive use of macros so I'm very confident that I have a near-exact emulation.

The one area where squint is actually stricter that it needs to be is that it is possible in Arma to write

#define A(X,Y) something

A(1)

and get away with it. Since I can't see that this would ever be done except by mistake, squint flags this as an error - "incorrect number of arguments".

Edited by sbsmac

Share this post


Link to post
Share on other sites

Ahh thought it might be something to do with the comma. Thanks for explaining.

Just noticed copying from squint into keynote kept the syntax highlighting, a thing some other editors do not. Very nice :bounce3:

_mag = sqrt (random 1.00) * _a;

Careful - this may not evaluate as you expect - use brackets

My english terminology is far from perfect, but isn't it parantheses?

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

Yep . technically 'parentheses' is more specific than 'brackets'. But 'brackets' tends to be used colloquially - one very rarely hears 'parentheses' in normal speech, even amongst programmers :)

British usage tends to be (IME) ...

() - "brackets"

{} - "braces" or "curly brackets"

[] - "square brackets"

<> - "angle brackets"

Wikipedia claims that in the US things are a bit more as you say...

BTW - don't know if you noticed the last update post since it came out as you were posting but I added auto-indent for you ;-)

Edited by sbsmac

Share this post


Link to post
Share on other sites

I did notice an update when I started squint again to check something, however was already finished with script. Just fired up squint and wrote an if statement:

OMG OMG OMG OMG :yay: :bounce3: awesome. "Sorry SQF plugin for N++. It's just that I've met someone else. Someone who really get's me." :D.

I only program as a hobby at the moment, though I will soon be studying software engineering, so don't really know what stuff it is called amongst programmers yet. Now I know what part of this stuff is called :).

---------- Post added at 18:47 ---------- Previous post was at 18:40 ----------

I can see on dev-heaven that you are working on tabs-to-spaces and that the options is already in. Tab is currently broken however,, functions more like home at the moment, and pressing tab on a completely empty file gives an IndexOutOfRangeException.

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

Tabs-to-spaces is already in and should be working. Not tested but it's only a one-line function so what could possible go wrong (famous last words) ?.....

Tab is behaving as expected (apart from the exception you see). See this bit of the manual to understand the way it works. :)

Share this post


Link to post
Share on other sites

You're right it was me being stupid. I was trying to indent a line improperly and squint of course corrected me. I then started thinking it was the program's fault, like any user would do ;)

Share this post


Link to post
Share on other sites

Minor bug?

//ACRE checker
if (isClass (configFile >> "cfgWeapons" >> "ACRE_PRC148")) then {
   G_ACRE = true;
} else {
   G_ACRE = false;
};

When auto-indented:

//ACRE checker
if (isClass (configFile >> "cfgWeapons" >> "ACRE_PRC148")) then {
   G_ACRE = true;
   } else {
       G_ACRE = false;
           };

Share this post


Link to post
Share on other sites

I hate to say it but that's about as good as the indent is likely to get for a while. Getting it to indent in the style you want would required the indenter to rewind through the tokens on the previous line and realise there was a closing brace at the start of the line. Actually I'll look at adding this special case but you're starting to see the limits of lexical indentation ;-)

In the meantime, 1.0.0.90 is released

*Bug #13238: Pressing TAB in an empty file gave an exception

*Bug #13247: Add BIS and ACE functions to dictionary

The main feature here is that I have addded BIS and ACE functions to the dictionary of global variables. This has a couple of benefits...

1) You should no longer get 'unknown variable' errors when calling these functions.

2) The auto-complete will offer them as candidates and potentially save you a lot of typing.

Share this post


Link to post
Share on other sites

I totally understand I just wanted to let you know the issue if you didn't already.

How do you plan on going around handling unrecognised global variables? Perhaps a box where you can write whitespace-separated globals?

Or an option to ignore warning?

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

At this stage I think the only unrecognised globals you should see would be from addons that declare additional function libraries. There are a few approaches to this...

1) Teach squint how to read CfgFunctions sections in addons (actually quite straightforward)

2) Allow the import of textual lists of functions which the user (or addon maker) can create.

3) Have a project/global dictionary to which the user can add exceptions when they run across unknown variables.

Share this post


Link to post
Share on other sites

There are a few times where you might have a valid reason to create a variable the dynamic way using call compile format for example, so I don't think number 1 is going to do it alone.

Nevermind, but don't think number 1 is going to solve it alone.

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

A couple of minor tweaks to auto-complete...

1.0.0.91..

* Feature #13251: Add common control constructs to auto-complete

*Feature #13250: Improve auto-indent so that it only offers function names after call or spawn

What the first one means is you can type

f..o..r..DOWN..DOWN..ENTER to get the template

for [{},{},{}] do {};

for example.

Share this post


Link to post
Share on other sites

Squint freezes on me and I end up having to ctrl alt delete to get out of it, does anyone else have these issues. It doesnt happen every time I get into it either.

Share this post


Link to post
Share on other sites

Actually I think I may have seen the same although I had put it down to developing on a very flaky laptop.

In my case I think this occurs when squint is just left unattended with no input for some period of time (which is odd because it's not actually running very much code at that point!) but I haven't really nailed it down. If you have a reliable 'recipe' for reproducing this it would be very helpful to hear it.

*Edit* It seems that squint on my laptop is very susceptible to problems with power-management. If I close the laptop lid and reopen it, squint is guaranteed to hang, even if doesn't even have any files or projects open. I'll see if I can reproduce this in the debugger.

*Edit again* Nope-it works fine under the debugger. Power-management on my laptop is really extremely bad (screen keeps repainting itself for about a minute after opening the lid) but other apps seem to cope ok.

Cobra - it would be very useful to know if you are using a laptop or PC, whether you have configured iit to drop down into low-power modes, and whether you think this might be at all related to the hangs that you see (I may be chasing a red-herring here).

Edited by sbsmac

Share this post


Link to post
Share on other sites

Tested: If I leave squint idle after a certain amount of time it will stop working.

Share this post


Link to post
Share on other sites

Seems we simul-posted :) Could you take a look at my edited previous post and comment on whether you think power-management might be a factor ?

Thx.

Also, just to be clear, could you confirm the symptoms of the 'hang' that you see? In my case the squint window just goes completely dead and won't repaint itself after another window has been dragged in front although sometimes I do get the actualy title-bar coming back. This argues quite strongly for some mechanism where the windows message-pump has gone awol...

Edited by sbsmac

Share this post


Link to post
Share on other sites

Im using a PC/vista and my power management is set to the highest setting.

It just freezes on screen and I have no way to close the window, currently I dropped it down and now I cannot bring it back up or shut it down.

Also if I minimize the window then it is guaranteed to freeze if I leave it for more than a minute or so.

Edited by cobra4v320

Share this post


Link to post
Share on other sites

Hmm - haven't yet managed to reproduce it by leaving the window minimized but I may be missing a step ...

Do you still get the problem if you don't load any files or type anything in the **Scatch** window ? Do there need to be errors showing in the error-list for this to occur ?

Thx-any ideas you have to narrow this down would be most helpful. In the meantime I'll take a look at why it's crashing under power-management. Hopefully it's the same cause.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×