Author Topic: Macro for surrounding a selection with a single keystroke.  (Read 4313 times)

EdgeVel

  • Community Member
  • Posts: 6
  • Hero Points: 0
Macro for surrounding a selection with a single keystroke.
« on: October 15, 2013, 06:04:44 PM »
Hi all,

I have been working on a macro that allows the user to select a word, sentence .. etc, and when the user types bracket, for example, then the selected text will be surrounded by brackets. If they type quotes, it will be surrounded by quotes, and so on. This is a functionality I saw on textmate a while ago and considered it pretty handy. The code I have implemented for this macro so far, I have pasted here:

Code: [Select]
#include "slick.sh"

_command void type_single_quote() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   if (!select_active()) {
      keyin("'");
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("'");
      _end_select();
      cursor_right();
      _insert_text("'");
      deselect();
   }
}

_command type_double_quote() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   if (!select_active()) {
      keyin("\"");
   }
   else {
      lock_selection();
      _begin_select();
      keyin("\"");
      _end_select();
      cursor_right();
      keyin("\"");
      deselect();
   }
}


_command type_parenthesis() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   if (!select_active()) {
      keyin("(");
      return (0);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("(");
      _end_select();
      cursor_right();
      _insert_text(")");
      deselect();
   }
}


_command type_bracket() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   _str l_event = last_event();
   if (!select_active()) {
      keyin(l_event);
      return (0);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("{");
      _end_select();
      cursor_right();
      _insert_text("}");
      deselect();
   }
}

_command type_square_bracket() name_info(','EDITORCTL_ARG2|MARK_ARG2|VSARG2_LASTKEY)
{
   _str l_event = last_event();
   if (!select_active()) {
      keyin(l_event);
   }
   else {
//    lock_selection();
      _begin_select();
      _insert_text("[");
      _end_select();
      cursor_right();
      _insert_text("]");
      deselect();
   }
}

defeventtab default_keys;
def "'" = type_single_quote;
def '"' = type_double_quote;
def '(' = type_parenthesis;
def '{' = type_bracket;
def '[' = type_square_bracket;

I would also like to simplify the code a little bit, but i don't know how to  do it. Notice that the functions {type_square_bracket, type_bracket, type_parenthesis, ... etc } are all the same, and they only differ in the symbol being used. If you know how to reduce it to one function, please let me know.

Also, please let me know of other improvements I can make on it.

Thanks,
Ed


chrisant

  • Senior Community Member
  • Posts: 1410
  • Hero Points: 131
Re: Macro for surrounding a selection with a single keystroke.
« Reply #1 on: October 16, 2013, 05:34:15 AM »
It's a factoring problem:

You want commands that don't take an argument.
So first, make a helper function that accepts a string argument indicating which character to use.
Then make one command per character, and make each command call the helper function, passing it the appropriate character.

EdgeVel

  • Community Member
  • Posts: 6
  • Hero Points: 0
Re: Macro for surrounding a selection with a single keystroke.
« Reply #2 on: October 16, 2013, 04:32:15 PM »
Is that because a command cannot have any arguments? or can it?

EdgeVel

  • Community Member
  • Posts: 6
  • Hero Points: 0
Re: Macro for surrounding a selection with a single keystroke.
« Reply #3 on: October 16, 2013, 05:08:10 PM »
Thanks, I have improved my code a little bit with the function helper idea.
Code: [Select]
#include "slick.sh"

void wrap_in_char(s)
{
   if (!select_active()) {
      keyin(s);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text(s);
      _end_select();
      cursor_right();
      _insert_text(s);
      deselect();
   }
}

_command type_single_quote() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   wrap_in_char("'");
}

_command type_double_quote() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   wrap_in_char('"');
}


_command type_parenthesis() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   if (!select_active()) {
      keyin("(");
      return (0);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("(");
      _end_select();
      cursor_right();
      _insert_text(")");
      deselect();
   }
}


_command type_bracket() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   _str l_event = last_event();
   if (!select_active()) {
      keyin(l_event);
      return (0);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("{");
      _end_select();
      cursor_right();
      _insert_text("}");
      deselect();
   }
}

_command type_square_bracket() name_info(','EDITORCTL_ARG2|MARK_ARG2|VSARG2_LASTKEY)
{
   _str l_event = last_event();
   if (!select_active()) {
      keyin(l_event);
   }
   else {
      lock_selection();
      _begin_select();
      _insert_text("[");
      _end_select();
      cursor_right();
      _insert_text("]");
      deselect();
   }
}

defeventtab default_keys;
def "'" = type_single_quote;
def '"' = type_double_quote;
def '(' = type_parenthesis;
def '{' = type_bracket;
def '[' = type_square_bracket;

1. For some reason, this code has a lot of conflicts with the auto close, especially when using plain text languages.Is there is a way to disable auto-close programmatically and re enable it after executing the command?

2. I want to be able to wrap each line in a block selection, as another smart behavior. You might understand what I'm trying to do better if you read my TODO comment in the code below:
Code: [Select]
_command type_parenthesis() name_info(','EDITORCTL_ARG2|MARK_ARG2)
{
   if (!select_active()) {
      keyin("(");
      return (0);
   }
   else {
      if (_select_type() == "BLOCK") {
         // TODO: do what I'm doing in the else statement for each line.
         }
      else{
         lock_selection();
         _begin_select();
         _insert_text("(");
         _end_select();
         cursor_right();
         _insert_text(")");
         deselect();
      }
   }
}

Any help appreciated,

Ed
« Last Edit: October 16, 2013, 05:09:49 PM by EdgeVel »