Take the My Slickedit Macros Challenge

Saturday, August 21, 2010 1 comments

My Slickedit Macros challenge:

Create a Slick-C macro that will show, at a glance, all unbound keys and key combinations in your current Slickedit configuration. It's the opposite of generating a Key Chart (Options > Keyboard and Mouse > Key Bindings > "Save Chart") or a keydefs.e file ("list_keydefs" command). If you already have such a macro, I invite you to share it.

Having a list of currently unbound keys can improve the efficiency of identifying keys and key combos that are free to be assigned. The macro will reduce the need to identify unbound keys from memory or by hunt and peck.

The macro should apply to the Default mode key bindings but it can also be used on the current mode or language--HTML, C++, Ruby, etc.--if you like.

Awhile back, Slickedit added "Search by Key Sequence" to the Key Bindings window. This is a wonderful feature. Better yet, they added the same search feature to several other configuration dialogs as well. Still, however, these features don't show unbound keys.

Prior to moving to Slickedit around 10 years ago, my text editor of choice was Kedit. Its macro language, KEXX, was based on Mike Cowlishaw's great REXX language. Incidentally, Slickedit's original macro language was REXX, and if I'm not mistaken, Slickedit spent its early years maturing on a single platform: OS/2. I started out with Visual Slickedit version 4.0b on OS/2 version 2.11 (or Warp, I don't remember).

On Kedit I had a macro, unbound.kex, which did everything I described above. Due to the crude composition of that macro, and the differences in Slick-C and KEXX, the Kedit macro is insufficient to translate into a Slick-C version. I'm rusty on my Slick-C, and haven't been able to get myself to write the macro or module--let's call it "unbound.e" So I'm entreating the public to meet the challenge of creating the unbound macro.

The developer with the winning solution by December 31, 2010 gets a free hardcover copy of John Hurst's book, Professional Slickedit.

25 Throwaway Macros

Monday, May 18, 2009 0 comments

How many lines of good Slick-C macros wind up in the bit dumpster every day because we can't be bothered to name the macro, shove it into a file, stick the file in a folder and make it available for others to share?

Some, maybe? Below I present 25 of my throwaway macros. Maybe you'll find something of interest here. Some of the macros are simple Slick-C batch files which I created to use in my work. Others are simple macros that I wrote or cobbled together for one reason or another.

Side Note: Occasionally, you'll see line breaks in unusual places in a command or line of code, like this:

_command void html_validator_preview()

name_info(','VSARG2_MARK|VSARG2_READ_ONLY|
VSARG2_REQUIRES_EDITORCTL)


This is necessary because Blogger apparently truncates, without a line break,
code on the right side of the blog at approx. column 54 and buries the
rest of the line on the right where it can't be seen. Unfortunately, this means
that we must hand-edit nearly every line of code to ensure that the lines are not
too long for Blogger.

So I have to put a lot of line breaks into the code just so people can actually
read it and possibly benefit from it.
I do not use continuation characters at
the end of the lines because they are not necessary for display and might make
the code more confusing.
If anyone knows what I'm doing wrong, please
post a note or send me an email.


Additionally, Slickedit seems to have added a lot of new commands or functions
in the last few major version upgrades. This is highly commendable, especially
since much of the new code consists of simple commands that, in my opinion,
should have existed long ago. It's possible that some of the commands below
duplicate some of the new Slick-C commands.

Here are your throwaways.

// Move cursor to end of line, add a

// space, and join with next line.

// Should intelligently remove any extra
// spaces at the end of the
top line
_command dh_bring_up, join_line_with_space()
name_info
(','VSARG2_REQUIRES_EDITORCTL)
{
save_pos(p);
end_line();
last_event(name2event(' '));maybe_complete();
linewrap_delete_char();
restore_pos(p);
}

// Open current file in external program
// CSE HTML Validator and proceed to
// validate with the current Slickedit file in
_command void html_validator_preview()
name_info(','VSARG2_MARK|VSARG2_READ_ONLY|
VSARG2_REQUIRES_EDITORCTL)

{
_str filename=p_buf_name;
shell("F:\\Software\\CSE_HTMLValidator80\\
cmdlineprocessor.exe -o "
filename);
}


// Balance_windows: Neatens up two MDI windows
// by making the two windows the same height
// and width. Makes
adjacent windows snug
// like they look right after
you split a
// window. Based on a routine from emacs
// emulation.

//
// This macro currently doesn't work on
// more than two MDI windows
at once. If
// you do execute the command with more than 2

// windows open, multiple windows will be
// displayed at once, instead of two windows
// balanced next to each other.
/
// Returns: 0 if the windows were
// resized, otherwise 1.

_command int balance_windows()
name_info
(','VSARG2_READ_ONLY|VSARG2_ICON|
VSARG2_REQUIRES_MDI_EDITORCTL
|VSARG2_REQUIRES_MDI)
{
if (_no_child_windows()) {
// No child windows, so they can't be balanced.
return(1);
}
if (_mdi.p_child.p_window_state:=='M') {
message('Only one visible window');
return(1);
}
int count;
int orig_wid;
orig_wid=p_window_id;

count=0;
do {
next_window();
count++;
} while ( p_window_id!=orig_wid );
if (count>1 && count <4) {
_no_resize=1;
tile_windows('h');
_no_resize='';
return(0);
} else {
if (count>=4) {
letter=letter_prompt('More than three '\\'
windows active. Tile them? (y/n/q)'
,'YNQ');
if (upcase(letter)=='Y') {
tile_windows('h');
return(0);
}
}
}
return(1);
}


// example of using filter selection
_command test_filter()
{
if (select_active()) {
lock_selection();
_end_select();
end_line=p_line;
_begin_select();
filter_init();
while (p_line<end_line) {
filt_status=filter_get_string(text);
if (!(_lineflags() & HIDDEN_LF)) {
messageNwait('p_line 'p_line' VIS,
text= '
text' filt_status= 'filt_status);
} else {
messageNwait('line 'p_line ' is HIDDEN');
}
}
filter_restore_pos();
}
}

// run external cmd unh.exe on html file in
// current buffer
and display in
// new/current window

_command unhtm()
name_info
(','VSARG2_REQUIRES_EDITORCTL)
{
html_fid=p_buf_name;
txt_fid=html_fid:+'.txt'
shell('unh.exe ' html_fid txt_fid);
e(txt_fid);
}
// if arg appears in current line, just delete
// that line

_command del(...) name_info(','VSARG2_REQUIRES_EDITORCTL)
{
// requires a line target
searchstr=arg(1); // TODO: differentiate bet
// numeric & string arg

parse searchstr with delim +1 sstring(delim)opts
save_pos(p);
select_line();
status=search(sstring, 'e>':+opts);
cursor_up();
select_line()
delete_selection();
restore_pos(p);
}

// Show count of hidden lines in a
// selective display

_command count_hidden_lines()
{
NoflinesShown0=((p_Noflines)-p_Nofhidden);
message( NoflinesShown0' visible (selected) lines,
p_Noflines= '
p_Noflines'; p_Nofhidden = 'p_Nofhidden);
}

// insert a horizontal separator line
// consisting of any character
selected
// on being prompted

_command insert_separator(...)
name_info
(',' VSARG2_READ_ONLY|
VSARG2_REQUIRES_EDITORCTL)

{
parse p_margins with left_ma right_ma new_para_ma;
if (arg(1)=='') {
message('Type a separator character');
key=get_event();

if (event2name(key)=='ESC') {
clear_message();
stop;
}

sepchar=event2name(key);
} else {
sepchar=arg(1);
}
textstr=substr('',1,right_ma,sepchar);
insert_line(textstr);
insert_line('');
down();
clear_message();
}

// expands selective display on selected
// (marked) lines

_command expand_selected()
{
// TODO: test for select_active()
end_select();
selend=p_line;
begin_select();
selbegin=p_line;
row_count=(selend - selbegin + 1);
for (i=0;i<=row_count;++i) {
_lineflags(0,PLUSBITMAP_LF|MINUSBITMAP_LF|
HIDDEN_LF
|LEVEL_LF);
down();
}
message('Expanded ' selbegin ' through ' selend);
// might detect + lines and msg
// which ones were expanded

}

// Toggle selective display of all
// _commands in vusrmacs.e or any other file.

// I use this macro frequently, whenever
// I want a quick overview of all my commands by

// name
_command show_commands,cmds()
name_info
(','VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL|
VSARG2_READ_ONLY
|VSARG2_REQUIRES_TAGGING)
{
// show all section headers and _commands
all('(^_command|^/\* \<-|/\*\>)','r');
// all('^_command', 'r');
}


// get mark_id for selection in another buffer
_command get_mark_id()
{
if (!select_active()) {
message(get_message(TEXT_NOT_SELECTED_RC));
} else {
mark_id=_alloc_selection();
message('mark_id= 'mark_id);
if (mark_id<0) {
message(get_message(mark_id));
return(mark_id);
}
}
}

// is selection hidden?
// to fix: hide_selection currently deselects after hiding,
// so there's no selection here to check for to toggle
_command is_selhid()
name_info(','VSARG2_EDITORCTL|VSARG2_READ_ONLY|VSARG2_REQUIRES_AB_SELECTION|VSARG2_REQUIRES_MDI_EDITORCTL|VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL)
{
if (!select_active()) {
message get_message(TEXT_NOT_SELECTED_RC);
stop;
}
mark_id=_alloc_selection();
_get_selinfo(start_col, end_col, dummy);
NofSelectedLines=count_lines_in_selection();
NofSelectedCols=(end_col - start_col);
begin_select();
topline=p_line;
end_select();
botline=p_line;
sticky_message('Marked block:
rows='
NofSelectedLines', cols='NofSelectedCols',
left='
start_col', right='end_col', top='topline',
bot='
botline);

goto_line(topline);

if (!(_lineflags() & HIDDEN_LF)) {
messageNwait("topline not hidden");
} else {
messageNwait('is_selhid: topline is hidden');
}

goto_line(botline);

if (!(_lineflags() & HIDDEN_LF)) {
messageNwait("botline not hidden");
} else {
messageNwait('is_selhid: botline is hidden');
}
}


// add toggle ability to select_all key
_command select_all_toggle()
name_info
(','VSARG2_REQUIRES_EDITORCTL)
{
if (!select_active()) {
select_all();
} else {
deselect();
}
}

// append a cmd to end of ".command" retrieve buffer
_command append_retrieve_buffer()
name_info(','VSARG2_CMDLINE|VSARG2_ICON|
VSARG2_REQUIRES_EDITORCTL
|VSARG2_READ_ONLY)

{
if (!command_state()) {
cmdline_toggle();
}
get_command(text);
append_retrieve_command(text);
set_command('',1);
}


Character, Word and Line Count for Current File

, , , Thursday, March 19, 2009 1 comments

// command wc(): Display on the message line,
// the total numbers of characters, words and
// lines
in the current file.
//
// This ubiquitous procedure
has been done ad
// infinitum by many developers. It's almost
// as common
as Hello World! I don't presume
// to hold any claim to it.
//
// On a large file of several thousand lines
// or more, it can take a few seconds to
// display its results

_command wc() {
cc = 0; // character count
wc = 0; // word count
lc = 0; // line count
item = 0;
_save_pos2(p);
top_of_buffer();
for (;;) {
get_line line;
lc++;
for (i = 1; i < length(line); i++) {
cc++;
if (isalnum(substr(line,i,1))) {
item = 1;
} else if (item && !isalnum(substr(line,i,1))) {
wc++;
item = 0;
}
}
status=down();
if (status == BOTTOM_OF_FILE_RC) {
message("chars: " cc " / words: " wc " / lines: " lc);
break;
}
}
_restore_pos2(p);
}

Count Lines Traversed

, , , , , , , , , , , Tuesday, March 17, 2009 0 comments

// Using the cursor-up or cursor-down keys,
// display on the message line the total number
// of lines the cursor has moved.


// Assign
a key combination to the line_counter
// command. Press the key combo to start the counter.
// It initializes with a value of 0. Press ESC to stop.
//
// Move your cursor up or down to reach your target.
// The target is typically a certain number of lines you
// want to traverse, or some specific text you want to
// reach. With each cursor-up/down keystroke the displayed
// count will decrement or increment by 1.
Moving the
// cursor up
will decrement the number of lines;
// moving the cursor down increments the line count.
// Change this if you want.
//
// This macro can actually be valuable once in a while.
// But I must plead ignorant for now; I've forgotten what I
// use it for!

_command line_counter() name_info(','VSARG2_REQUIRES_EDITORCTL|VSARG2_READ_ONLY)
{
lines=0;
message('Number of lines traversed='lines)

for (;;) {
key = get_event();
keyname=event2name(key);

if (keyname=='DOWN') {
cursor_down();
++lines;
}

if (keyname=='UP') {
cursor_up();
--lines;
}
message('Linecount='lines)

if (keyname=='ESC') {
message('Linectr cancelled')
break;
}
}
}

I repeat myself when under stress, I repeat myself when under stress . . .

, , , , , , Thursday, March 12, 2009 0 comments

// repeat_n [how many times] [command name]
// Repeats a command the number of times specified.

// Args are "n command", where n is the number of times
// to execute the command, and command is the name of
// the command to run.
//
// Usage example: repeat_n 15 cursor_down
// This will execute the cursor-down command 15 times, with the
// expected results.

// Source: Professional Slickedit by John Hurst
// Copyright 2007 Wiley Publishing Inc, Indianapolis, Indiana, USA.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0

_command void repeat_n(_str args = null) \\
name_info(','VSARG2_EDITORCTL)
{
if (args == null) {
message("Specify number of times and " \\
"command to run."
);
return;
}
_str n;
_str command;
parse args with n command;
if (n <= 0 || command == null) {
message("Specify number of times and " \\
"command to run."
);
return;
}
int i;
for (i = 0; i < n; i++) {
execute(command);
}
}

// repeat_n_last_macro [how many times]
// Repeats the last recorded macro the number of times specified
// Usage example: repeat_n_last_macro 25
// Executes the last recorded macro 25 times

//
Source: Professional Slickedit by John Hurst
// Copyright 2007 Wiley Publishing Inc, Indianapolis, Indiana, USA.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0

_command void repeat_n_last_macro(_str args = null) \\
name_info
(','VSARG2_EDITORCTL)
{
repeat_n(args :+ " last_macro");
}


Circuitous Logic

, , , , , 0 comments

// (1) Get and set your margin settings at desired increments.
// Assign this macro to a key combination.
// Stick your favorite margin presets into the macro code.
// I like to use 1 80 1, 1 128 1, 1 256 1, 1 512 1 and 1 1024 1.

// The same "cycling" method can be used on almost any setting.
// For example, you can easily modify this macro to take a text
// selection and cycle the text through all caps, initial caps,
// all lower case, and so on.

// Currently the macro will automatically increment to the next
// setting each time the key combo is pressed (including the
// first press). If the margins are currently 1 256 1, executing
// the command will increment the setting to 1 512 1. If 512
// is not the setting you want, just press the key combo again
// to set your desired value.
//

// (2) Cycle through display modes: hex, line hex, normal edit.
//


_command cycle_right_margin() name_info(','VSARG2_REQUIRES_EDITORCTL, VSARG2_READ_ONLY)
{
parse p_margins with left_ma right_ma new_para_ma;
// message("Current margin settings "left_ma' 'right_ma' 'new_para_ma);
switch (right_ma) {
case 80:
p_margins=left_ma' '128' 'new_para_ma;
message('Margins 'p_margins);
break;
case 128:
p_margins=left_ma' '256' 'new_para_ma;
message('Margins 'p_margins);
break;
case 256:
p_margins=left_ma' '512' 'new_para_ma;
message('Margins 'p_margins);
break;
case 512:
p_margins=left_ma' '1024' 'new_para_ma;
message('Margins 'p_margins);
break;
case 1024:
p_margins=left_ma' '80' 'new_para_ma;
message('Margins 'p_margins);
break;
default:
p_margins=left_ma' '80' 'new_para_ma;
message('Margins 'p_margins);
break;
}
}


// (2) Cycle through display modes: hex, line hex, normal edit.
// From Thom Little & Associates, www.tlanet.net


#define TLA_DISPLAY_EDIT 0
#define TLA_DISPLAY_HEX 1
#define TLA_DISPLAY_LINE_HEX 2

_command void tlaViewCycle( ) name_info( ',' VSARG2_ICON | VSARG2_REQUIRES_MDI_EDITORCTL )
{
switch ( p_hex_mode )
{
case TLA_DISPLAY_EDIT :
p_hex_mode = TLA_DISPLAY_HEX ;
break ;
case TLA_DISPLAY_HEX :
p_hex_mode = TLA_DISPLAY_LINE_HEX ;
break ;
case TLA_DISPLAY_LINE_HEX :
p_hex_mode = TLA_DISPLAY_EDIT ;
break ;
default :
tlaError( "tlaViewCycle", "Unknown view state" );
break ;
}
return ;
}

Change current file's file extension

Wednesday, March 11, 2009 0 comments

// change fext or prompt for fully qualified buffer name
_command fe, fext() name_info(','VSARG2_EDITORCTL|VSARG2_CMDLINE)
{
fid=p_buf_name;
new_fext=arg(1);
if (new_fext=='') {
name();
return(0);
}
buf_nofext=strip_filename(fid,'E');
new_fid=buf_nofext:+'.':+new_fext;
status=name(new_fid);
if (status) {
message('Fext was not changed');
return(0);
} else {
save_as(new_fid);
return(1);
}
}

GlossyBlue Blogger by Black Quanta. Theme & Icons by N.Design Studio
Entries RSS Comments RSS