View unanswered posts | View active topics



Reply to topic  [ 7 posts ] 
Macros scripting: getting started, edition and example 
Author Message
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
Advanced macros can be developed for FlashDevelop - the sky is the limit as long as you can stay keep it in one class :)

Here is a very simple macro which "flattens" single line XML code in the current document.
Code:
// FlattenXML.cs
using System;
using PluginCore;

public class FlattenXML
{
   public static void Execute()
   {
      ScintillaNet.ScintillaControl sci = PluginBase.MainForm.CurrentDocument.SciControl;
      if (sci == null) return; // document not editable

      string src = sci.Text; // WARNING: reading/writing sci.Text property is slow
      sci.Text = src.Replace("><", ">\n<");
   }
}

Save the script:
We recommend your user FD directory (from FD main menu: Tools > User Config Files...) which corresponds to the '$(BaseDir)' variable, but it can really be anywhere.

:idea: For quick testing you can now simply select your CS file manually from FD main menu: Macros > Run Script....

Add a macro:
Now you can <Add> a new macro in the Macros dialog (Macros > Edit Macros...):
Image
The macro properties are pretty straightforward:
* AutoRun - optionally execute macro on FD startup
* Entries - list of basic macro commands (click <...> to edit)
* Image - you can build a nice icon for the menu item using "icomp", a tool included in FD program files (Tools\icomp)
* Label - text of the menu item
* Shortcut - obviously a shortcut to execute your macro

During development, use this action to make sure the script is reloaded/recompiled everytime:
Code:
ExecuteScript|Development;$(BaseDir)\FlattenXML.cs

When your script is completed, you want to make sure the script is only compiled once:
Code:
ExecuteScript|Internal;$(BaseDir)\FlattenXML.cs


Thu Dec 17, 2009 7:49 pm
Profile WWW
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
Code completion?

Writing C# code without an appropriate editor can be a pain. You could probably use Visual Studio (or the great and free C# Express) but there is a better solution...

The Snippet Compiler Live 2008 Ultimate Edition for Developers (yeah)!

It's not a joke, this is free, lightweight C# editor offering actually good code completion and compilation - precisely designed to quickly code and compile one class (typically to create a little command line application).

So download Snippet Compiler (SC) and run it. You'll be presented with a default C# class for a command line application.

The template class has 2 methods: RunSnippet and Main. This is a nice way to let you write your code in RunSnippet and to not worry about the usual try/catch and ReadKey when you test a command-line application.

For FD macro scripts:
- you'll want to compile your script using SC to trap compile errors (that's one thing you won't have to worry when testing),
- this means a public static void Main() method is required (SC compiles command line application only),
- you can keep the default class as-is (use RunSnippet() for your tests outside FD).

1. For most code completion needs you'll have to add a "reference" to FlashDevelop's PluginCore:
- in SC, select: Tools > References > File System
- click <...> to browse to FD program files and choose PluginCore.dll (double-click once to add it in the DLL list at the bottom of the dialog) then click <Ok>
(you may have to re-add the reference when you restart SC)

2. You will then simply add a public static void Execute() method with your FD script.

3. Code, compile with Ctrl+Shift+B to control your code is ok, then test in FlashDevelop.


Thu Dec 17, 2009 9:47 pm
Profile WWW
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
Basic scripts debugging (ie. tracing):

You won't have breakpoints and step debugging but you can trace to FD output panel from your plugin:
Code:
using PluginCore.Managers;
...
TraceManager.Add("show this in output");
TraceManager.Add("show this in RED", 3);

Color levels:
- 0: info (gray)
- 1: debug (black)
- 2: warning (orange)
- 3: error (red)
- 4: fatal (purple)


Fri Dec 18, 2009 11:45 am
Profile WWW
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
More complex example modifying the editor selection text

Scintilla is a complex editor component, and there are a number of gotchas:
- avoid reading/modifying sci.Text; it is highly inefficient,
- use direct methods like CurrentPos, GetCharAt, SetSel, ReplaceSel,... instead,
- be careful as all these text methods are byte-based: it isn't utf-8 aware and an accented characters will correspond to 2 bytes.

Code:
using System;
using System.Text;
using PluginCore;

///
/// Select some text (even multiline) in the editor and call this macro to escape it to be used as a String value
///
public class EscapeText
{
   private static string[] CS_EscapeSequences = new string[] { "\aa", "\bb", "\ff", "\nn", "\rr", "\tt", "\vv", "\"\"", "\\\\", "??", "\00" };
   private static char[] CS_EscapeTable;
   private static bool EscapeCSInited = false;
   
   private static string EscapeString(string str)
   {   
      if (EscapeCSInited == false) {
         EscapeCSInited = true;
         CS_EscapeTable = new char[256];
         foreach (string escape in CS_EscapeSequences) {
            CS_EscapeTable[escape[0]] = escape[1];
         }
      }
      if (str == null) return "null";
      
      StringBuilder sb = new StringBuilder(str.Length + 2);
      for (int rp = 0; rp < str.Length; rp++) {
         char c = str[rp];
         // if it is an escape char
         if (c <= 255 && CS_EscapeTable[c] != '\0') {
            // ASCII escaped character
            sb.Append('\\').Append(CS_EscapeTable[c]);
         } else {
            // ASCII printable character
            sb.Append(c);
         }
      }
      return sb.ToString();
   }
   
   public static void Execute()
   {
      ScintillaNet.ScintillaControl sci = PluginBase.MainForm.CurrentDocument.SciControl;
      if (sci == null) return; // document not editable
      
      string selection = sci.SelText;
      if (string.IsNullOrEmpty(selection)) return; // no selection
      
      sci.ReplaceSel(EscapeString(selection));
   }
}


Sat Feb 28, 2015 2:22 pm
Profile WWW
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
Another simple example: trace current variable

Picks the current selection, if not empty, or the word at the cursor position, then adds a new line of text with a trace statement.

Code:
// Trace.cs
using System;
using PluginCore;
using ScintillaNet;

public class Trace
{
    public static void Execute()
    {
        ScintillaControl sci = PluginBase.MainForm.CurrentDocument.SciControl;
        if (sci == null) return; // document not editable

        String trace = sci.SelTextSize > 0
            ? sci.SelText // current selection
            : sci.GetWordFromPosition(sci.CurrentPos); // current word

        sci.LineEnd();
        sci.NewLine();
        sci.InsertText(sci.CurrentPos, String.Format("trace(\"{0} = \" + {0});", trace));
        sci.LineEnd();
    }
}


Thu Aug 06, 2015 9:29 am
Profile WWW
Admin

Joined: Wed Aug 31, 2005 7:27 am
Posts: 12172
Location: London
Reply with quote
Another simple example: XML Pretty Print

Reformats the entire (well formed) XML document or only the selection.
(note: FlashDevelop 5+ because it used .NET 3.5 features)

Code:
// XmlPrettyPrint.cs
using System;
using System.Xml.Linq;
using PluginCore;
using ScintillaNet;

class XmlPrettyPrint
{
   public static void Execute()
   {
      ScintillaControl sci = PluginBase.MainForm.CurrentDocument.SciControl;
      if (sci == null) return; // document not editable

      string src = sci.SelTextSize == 0 ? sci.Text : sci.SelText; // selection or full text

      XDocument doc = XDocument.Parse(src); // use Linq to parse and format the XML

      if (sci.SelTextSize == 0) sci.Text = doc.ToString();
      else sci.ReplaceSel(doc.ToString());
   }
}


Fri Aug 07, 2015 10:05 am
Profile WWW
Member

Joined: Fri Jul 23, 2010 10:26 am
Posts: 146
Reply with quote
Can one macro do more than one thing? I.e. can an argument be passed to a macro?
For example, is it possible to enhance Trace macro to output a single variable, or do a "for..in" (and assign two different shortcuts to those), or should the source file be copy&pasted, with only one line difference between the two macros?


Sat Aug 08, 2015 8:37 am
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 7 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.