Author Topic: Centre text on open  (Read 1062 times)

bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Centre text on open
« on: March 08, 2021, 08:47:08 pm »
i'd like to know if it is possible to configure a filetype to centre all its text when a file matching the filetype is opened. let's take a txt filetype for example, is there any way to configure SlickEdit to centre all the text in a .txt file on opening ? such a feature would work like the "shift left" or "shift right" commands. in this case, the entire block of text will be moved, without modification, to the centre of the editor when a file is opened.

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #1 on: March 08, 2021, 09:59:59 pm »
I don't understand what you mean by center text - can you give a diagram or something.

It's possible to run a macro when a new buffer is opened  - any function whose name starts with "_buffer_add_" gets automatically called when a new file is opened.  Add the following code to vusrmac.e in your configuration folder, load it with the "load module" command in the macro menu to try it.  The "say" command outputs text to a debug window.


Code: [Select]
void _buffer_add_center_text(_str old_buffer_name, _str options="")
{
  if ( get_extension(p_buf_name) == "txt" ) {
     say("i'm a text file" :+ p_buf_name);
  }

  if ( p_LangId == "fundamental" ) {
     say("i'm fundamental" :+ p_buf_name);
  }
}


bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Re: Centre text on open
« Reply #2 on: March 09, 2021, 08:39:04 pm »
nice one, again SlickEdit surprises me with its flexibility.

what i mean by centering the text can best be seen when you select all the text in an opened file and use the "Shift Selection Right" command. the entire block of text is shifted right. some screenshots:

Normal:



Centred:



so what i'd like to see accomplished is a specific filetype being centred on open as seen in the second screenshot.

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #3 on: March 10, 2021, 08:55:13 am »
I had some spare time so I wrote a macro you can play with.  You might not need anything this complex though.  It tries to find the number of visible columns on the screen using the end_window() function  - this seems to get too big a number sometimes and a spurious horizontal scroll occurs  - so if this happens you get prompted to enter the number of columns you want to shift right (or left). 

After the shift is done, the macro enters a loop (an "event loop") which allows you to adjust the centered column using left-arrow or right-arrow   - or ctrl-left-arrow, ctrl-right-arrow to go 5 columns at a time.  You can also use end, home, up, down, page-up, page-down to move around.  Press ESC to exit the event loop.

If a selection already exists it operates on that selection only, otherwise it does select-all.  If you have the cursor on a blank line and run the command it will do a shift right equal to the number of visible columns you have  - which is probably not what you want.  If the first non blank character on the current line is in column 15 and you have 100 visible columns it will do a shift right of 35 columns to get the first non blank on the current line to be at column 50.

You can call this macro from the earlier code I posted.  If you didn't know about the arg_shift_selection command - it might be all you need.  It prompts you for the number of columns you want to shift the selection by.


Code: [Select]
bool xhz_center_text_is_enabled = false;

_command void xhz_center_text_enable_toggle() name_info(',')
{
   xhz_center_text_is_enabled = !xhz_center_text_is_enabled;
   _message_box(xhz_center_text_is_enabled ? "enabled" : "disabled");
}


_command void xhz_center_text() name_info(','VSARG2_READ_ONLY|VSARG2_REQUIRES_EDITORCTL|VSARG2_MARK)
{
   typeless save_sel;
   bool was_sel = false;
   if ( !xhz_center_text_is_enabled ) {
      return;
   }
   if ( select_active() != 0 ) {
      if (save_selection(save_sel) == 0)
      {
         was_sel = true;
         begin_select();  // goto to start of selection
      }
   }

   entry_start_col := _mdi.p_child.p_col;
   entry_start_line := _mdi.p_child.p_line;
   typeless p1;
   save_pos(p1);
   begin_line();   // make col 1 visible
   end_window();   // bottom right of visible window
   
   x1 := _mdi.p_child.p_col / 2;  // we want first non blank to be here
   if ( _mdi.p_child.p_left_edge != 0 ) {
      // the window has scrolled horizontally - means end_window() went wrong
      x1 = 0;
   }

   restore_pos(p1);
   center_line();            // vertical
   first_non_blank();
   first_nbcol := _mdi.p_child.p_col;

   if ( was_sel )
      restore_selection(save_sel);
   else
   {
      select_all();
      restore_pos(p1);
   }
   // say(x1 :+ " " :+ first_nbcol);

   if ( x1 == 0 )
      arg_shift_selection("R");    // end_window() went wrong
   else if ( x1 > first_nbcol)
      shift_selection_right(x1 - first_nbcol);
   else if ( first_nbcol > x1 )
      shift_selection_left(first_nbcol - x1);
   else
      arg_shift_selection("R");   // the text was already centered

   _message_box("Press ESC to exit, -> shift right, <- shift left, +ctrl=faster");

   while ( 1 ) {
      // make numpad keys work properly
      // int orig_auto_map_pad_keys=_default_option(VSOPTION_AUTO_MAP_PAD_KEYS);
      // _default_option(VSOPTION_AUTO_MAP_PAD_KEYS,0);
      _str key = get_event('N');   // refresh screen and get a key
      _str keyt = event2name(key);
      // _default_option(VSOPTION_AUTO_MAP_PAD_KEYS,orig_auto_map_pad_keys);
      switch (keyt) {
         case ' ' :
            xhz_center_text_is_enabled = false;
         case 'ESC' :
         case 'ENTER' :
            if ( !was_sel ) {
               deselect();
            }
            _mdi.p_child.p_col = entry_start_col;
            _mdi.p_child.p_line = entry_start_line;
            center_line();            // vertical
            return;
         
         case 'RIGHT' :
            shift_selection_right(1);
            continue;
         case 'LEFT' :
            shift_selection_left(1);
            continue;
         case 'HOME' :
            begin_select();
            continue;
         case 'END' :
            end_select();
            continue;
         case 'C-LEFT' :
            shift_selection_left(5);
            continue;
         case 'C-RIGHT' :
            shift_selection_right(5);
            continue;
         case 'PGUP' :
            page_up();
            continue;
         case 'PGDN' :
            page_down();
            continue;
         case 'DOWN' :
            cursor_down();
            continue;
         case 'UP' :
            cursor_up();
            continue;

      }
   }
}


« Last Edit: March 10, 2021, 09:16:20 am by Graeme »

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #4 on: March 10, 2021, 09:18:45 am »
I've just updated the code to allow you to enable/disable the command from doing anything  - since you probably don't want text files to get centered at editor startup or when you switch workspaces.  In the event loop you can hit the SPACE key to disable the command and exit.

xhz_center_text_enable_toggle toggles enable / disable.


bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Re: Centre text on open
« Reply #5 on: March 10, 2021, 11:34:40 am »
Thank you for taking your time out to write code to add this feature it is impressive work. i sincerely appreciate it.

the macro works well when bound to a hotkey but i'd like to have it run when a specific filetype is opened without having to use the hotkey(correct me if i'm wrong, but would adding the "_buffer_add_" command to "xhz_center_text" to make "_buffer_add_xhz_center_text" make the macro run at file open ?). would it be possible to add an option to set a filetype(s) for the macro to work on ? so if a user wants it to only work on .ini files they can set it in the macro or if they wanted it to work on only .ini and .log files it would be possible to set it to only run when these files are opened ?

is it possible to specifiy the number of columns to shift left or right for the "arg_shift_selection" command ? if so you are right in that it may be easier to configure the macro to shift the text block a specific number of columns and call it a day since it seems that centring it could turn out to be tricky.

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #6 on: March 10, 2021, 01:02:48 pm »
You can type
shift-selection-right  25
on the slick command line or you can call
shift_selection_right(25);
in macro code.  (or left)

You can call arg_shift_selection("R", 25) in macro code but the main point of this function is to prompt the user for the number and it won't prompt if you specify the number of columns.

If you add the _buffer_add prefix to the xhz function then that function will get called whenever any file is opened in the editor  - including at startup or workspace switch - I suspect that's not what you want.
You could add this code to the xhz function to restrict the file types.

if ( !(get_extension(p_buf_name) == "txt")
     && !(get_extension(p_buf_name) == "ini")  )
     return;

To stop the function from running on workspace open you need the enable / disable code I added.

You could write your own gui-open function
_command gui_open_and_center_text()
{
   xhz_center_text_is_enabled = true;
   gui_open();
   xhz_center_text_is_enabled = false;
}
or just
_command gui_open_and_center_text()
{
   gui_open();
   xhz_center_text();
}


 

bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Re: Centre text on open
« Reply #7 on: March 10, 2021, 10:08:07 pm »
You can type
shift-selection-right  25
on the slick command line or you can call
shift_selection_right(25);
in macro code.  (or left)

You can call arg_shift_selection("R", 25) in macro code but the main point of this function is to prompt the user for the number and it won't prompt if you specify the number of columns.


this is valuable information, i've combined the code you've written in this thread and come up with this(please overlook and correct any mistakes made as i'm not a programmer)

Code: [Select]
_command void xhz_center_text()
{
   if ( !(get_extension(p_buf_name) == "txt")
     && !(get_extension(p_buf_name) == "ini")  )
     return;
   select_all()
   arg_shift_selection("R", 60)
   deselect()
}

what i'm trying to accomplish with this(Thank you very much for the code you posted as this is derived from it) is:

- double click a .txt or .ini file in a file manager,
- since the two are already associated with SlickEdit, they'll be opened in the editor,
- have the macro run without user input and centre the text in the .txt or .ini file opened,
- the macro will only run when .ini and/or .txt files are opened.

with those objectives laid out, the above code only works when called by a hotkey, it is not automatic. how can the code be modified to run when an .ini and/or .txt file is opened ?


Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #8 on: March 11, 2021, 10:59:26 am »
As I've mentioned before, if you add the _buffer_add prefix to your function name it will run when any buffer is opened  - including at startup and when you switch workspaces.

If the only time you want the macro to run is when you double click a file in explorer, then you can associate the txt and ini file extensions with a batch file  - if you're using Windows.  The batch file can run slickedit like this

vs.exe %1  -#xhz_center_text

You could also add the batch file to the Windows "send to" list and use right click send-to.

Another way as I already mentioned  - the following command will allow you to choose a file to open, then run the xhz command.

_command void gui_open_and_center_text()
{
   gui_open();
   xhz_center_text();
}

You're missing some semicolons in your code

_command void xhz_center_text()
{
   if ( !(get_extension(p_buf_name) == "txt")
     && !(get_extension(p_buf_name) == "ini")  )
     return;
   select_all();
   arg_shift_selection("R", 60);           // could be just shift_selection_right(60);
   deselect();
}


bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Re: Centre text on open
« Reply #9 on: March 14, 2021, 05:57:48 pm »
Thank you for the tips and indeed, as you mentioned, adding _buffer_add_ now ensures that the macro is run when a specified file is opened in SlickEdit. i had to remove the _command from _command void xhz_center_text() to make it work, it now works very well. i'm impressed by SlickEdit's macro feature it is very very feature rich.

now to some questions if you do not mind:

- i have not found references to _buffer_add_ in the manual is this an undocumented command or have i not looked hard enough. same goes for the arg_shift_selection("R", 60) way of writing the command.

- is it possible to use a macro to hide the toolbars and tool-windows only when a particular filetype is opened ? let say you want to edit a .html file in a minimal editing environment, is there a macro that can be configured to run when a html file is opened that will hide all toolbars and tool-windows or hide toolbars and tool-windows that a user specifies ?

Thank you.

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #10 on: March 14, 2021, 11:12:41 pm »
Regarding _buffer_add prefix, if you search slick source code for call_list whole word only, you'll see all of the prefixes that are available.  It's an undocumented feature.  You'll see there's a prefix _switchbuf_ that is for when you switch to a different buffer, also _cbsave_ for when you save a buffer.  This should really be in the help  - or maybe in SlickCMacroBestPractices.pdf

For arg-shift-selection, it is in the help.  One way to find things like this is go to help in the main menu, then "macro functions by category" then "selection functions".  The function names give you a pretty good idea what the function will do.

For tool windows  -  Slick V23 introduced save_named_layout and load_named_layout commands.  These allow you to save and restore all your tool-windows and toolbars with a particular layout  - you get prompted for a name for each layout.  So if you call save_named_layout from the command line and save a layout as "t1" you can create a command to load that layout like this  - and bind a key to it.

Code: [Select]
_command void  t1() name_info(',')
{
   load_named_layout("t1");
}

https://community.slickedit.com/index.php/topic,17426.msg71156.html#msg71156


Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #11 on: March 14, 2021, 11:16:39 pm »
Also in case you didn't know, each workspace remembers its own toolbar / toolwindow layout.

bogedo

  • Community Member
  • Posts: 23
  • Hero Points: 0
Re: Centre text on open
« Reply #12 on: March 15, 2021, 11:12:41 am »
Regarding _buffer_add prefix, if you search slick source code for call_list whole word only, you'll see all of the prefixes that are available.  It's an undocumented feature.  You'll see there's a prefix _switchbuf_ that is for when you switch to a different buffer, also _cbsave_ for when you save a buffer.  This should really be in the help  - or maybe in SlickCMacroBestPractices.pdf


agreed, SlickEdit is extremely powerful and it is a pity that a user someimes has to go out of their way to seek out all its features. the help could also benefit from a few examples to get people going with Slick-C this way new users can get up to speed quicker with the language and macros in SlickEdit.


For arg-shift-selection, it is in the help.  One way to find things like this is go to help in the main menu, then "macro functions by category" then "selection functions".  The function names give you a pretty good idea what the function will do.


noted, Thank you for the suggestion.


For tool windows  -  Slick V23 introduced save_named_layout and load_named_layout commands.  These allow you to save and restore all your tool-windows and toolbars with a particular layout  - you get prompted for a name for each layout.  So if you call save_named_layout from the command line and save a layout as "t1" you can create a command to load that layout like this  - and bind a key to it.

Code: [Select]
_command void  t1() name_info(',')
{
   load_named_layout("t1");
}

https://community.slickedit.com/index.php/topic,17426.msg71156.html#msg71156

this looks promising. i've tested it with the extension restricting code you posted and it works when a specified fileype is tied to a saved layout

Code: [Select]
if ( !(get_extension(p_buf_name) == "html"))
     return;
   load_named_layout("minimal");

but i've run into an issue.

- i would like to open html files in a minimal environment that has no toolbars and tool-windows. i've created such a layout and named it "Minimal".

- i've also created a layout called "Default" for all other files other than html's that i would like to view/edit with the toolbars and tool-windows i've configured visible.

when i open a html file the layout "minimal" is loaded. but unless "default" is re-loaded, all other files other than html's will be loaded in the "minimal" layout. this is where i need help. i've determined that the best option would be to have .html files open a new window with the "minimal" layout. but i foresee some issues:

- how would other html files opened from the system be assigned to the new window using the "minimal" layout ?
- how would files that i would not want to be opened in the window running the "minimal" layout be assigned to the default window running the "default" layout ?

to illustrate the two questions with a use case:

- open a .ini file and it opens in a window running the "default" layout.
- open a .txt file and it will open in the same window.
- open a .html file and a new window will open running the "minimal" layout.
- open an xml file and it will be opened in the window with the "default" layout
- open another .html file and it will open in the window with the "minimal" layout

in total there should be two windows(is it even possible to accomplish this in one window ?) with multiple edit tabs. the default layout window with three tabs(.ini, .txt, .xml) and the minimal layout window with two tabs(.html and .html)

i appreciate your continued patience with me in sharing your knowledge as it is inspiring me to do more with Slick-C.

Dan

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 2545
  • Hero Points: 141
Re: Centre text on open
« Reply #13 on: March 15, 2021, 12:55:57 pm »
Thank you for the tips and indeed, as you mentioned, adding _buffer_add_ now ensures that the macro is run when a specified file is opened in SlickEdit. i had to remove the _command from _command void xhz_center_text() to make it work, it now works very well. i'm impressed by SlickEdit's macro feature it is very very feature rich.

now to some questions if you do not mind:

- i have not found references to _buffer_add_ in the manual is this an undocumented command or have i not looked hard enough. same goes for the arg_shift_selection("R", 60) way of writing the command.

- is it possible to use a macro to hide the toolbars and tool-windows only when a particular filetype is opened ? let say you want to edit a .html file in a minimal editing environment, is there a macro that can be configured to run when a html file is opened that will hide all toolbars and tool-windows or hide toolbars and tool-windows that a user specifies ?

Thank you.

++heroPoints;

Graeme

  • Senior Community Member
  • Posts: 2517
  • Hero Points: 327
Re: Centre text on open
« Reply #14 on: March 15, 2021, 10:55:04 pm »

Quote
in total there should be two windows(is it even possible to accomplish this in one window ?) with multiple edit tabs. the default layout window with three tabs(.ini, .txt, .xml) and the minimal layout window with two tabs(.html and .html)

I can't tell what you mean by "window" or what you mean by "open a file".

When you open a file in slick that isn't already open, functions with the _buffer_add prefix get called because a new buffer is created (added) for the file.  If you switch to a file that is already open in slick, functions with the _switchbuf_ prefix get called  - because you are switching buffers.  Hence you might be able to get what you want just by changing your _buffer_add prefix to _switchbuf_.  If you need to center text, then use _buffer_add_ to do the centering and _switchbuf_ to select the layout.

When you say "window" do you mean a floating edit window?

What setting do you have for the "one file per window" option
tools -> options -> editing -> editor window -> files per window.
I don't really know what this option does any more but it might make a difference to you.

Floating edit windows can choose a tool-window layout by right click on the doc tab and select "layouts".  This layout setting is completely separate from the "save-named-layout" "load-named-layout" thing.  The non floating MDI window does not have a "layout" option in the doc tab context menu.  Also a floating edit window seems to be always on top of the MDI window so if you're going to use floating windows then you probably need one for html and one for default.  This would be hard to get working properly I think - it's not easy to get html files to open in the html window and others to the other window.

For _switchbuf_ you probably want to avoid switching layouts every time you switch buffers if the correct layout is already open, so you need a local static variable.

Code: [Select]
void _switchbuf_xselect_twlayout(_str oldbuffname, _str flag)
{
    static bool layout_is_default;
    if ( (get_extension(p_buf_name) == "html"))
    {
        if (layout_is_default || oldbuffname :== "")
              load_named_layout("minimal");
         layout_is_default = false;
         return;
    }

    if (!layout_is_default || oldbuffname :== "")
          load_named_layout("minimal");
     layout_is_default = true;

}

There's a potential problem with the above code - when the editor first starts and the first buffer is opened, the static variable might not match the layout.  The check for oldbuffname being empty may or may not fix it so you should call switchbuf from buffer_add like this

void _buffer_add_xhz_center_text()
{
     _switchbuf_xselect_twlayout("", ""); 
}