Vous êtes sur la page 1sur 506

www.dbebooks.

com - Free Books & magazines

Professional

SlickEdit
John Hurst

Wiley Publishing, Inc.

Professional SlickEdit
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv

Part I: Getting Started with SlickEdit

Chapter 1: Introducing SlickEdit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Chapter 2: Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Chapter 3: Managing Windows. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Part II: Using SlickEdit

41

Chapter 4: Workspaces and Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Chapter 5: Context Tagging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Chapter 6: Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Chapter 7: Search and Replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Chapter 8: Editing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Chapter 9: Editing Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Chapter 10: Editing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Chapter 11: Aliases and File Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Chapter 12: Document Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Chapter 13: Comparing and Merging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Chapter 14: Version Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

Part III: Advanced SlickEdit

295

Chapter 15: Other Tools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Chapter 16: Slick-C Macro Programming . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Chapter 17: Customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 Appendix A: Settings for Different Emulations. . . . . . . . . . . . . . . . . . . . . . . 391 Appendix B: Regular Expression Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Appendix C: SlickEdit Callbacks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 Appendix D: Whats on the CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451

Professional

SlickEdit

Professional

SlickEdit
John Hurst

Wiley Publishing, Inc.

Professional SlickEdit
Published by Wiley Publishing, Inc. 10475 Crosspoint Boulevard Indianapolis, IN 46256 www.wiley.com Copyright 2008 by Wiley Publishing, Inc., Indianapolis, Indiana Published simultaneously in Canada ISBN-13: 978-0-470-12215-0 Manufactured in the United States of America 10 9 8 7 6 5 4 3 2 1 Library of Congress Cataloging-in-Publication Data is available from the publisher. No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should be addressed to the Legal Department, Wiley Publishing, Inc., 10475 Crosspoint Blvd., Indianapolis, IN 46256, (317) 572-3447, fax (317) 572-4355, or online at http:// www.wiley.com/go/permissions. Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose. No warranty may be created or extended by sales or promotional materials. The advice and strategies contained herein may not be suitable for every situation. This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional services. If professional assistance is required, the services of a competent professional person should be sought. Neither the publisher nor the author shall be liable for damages arising herefrom. The fact that an organization or Website is referred to in this work as a citation and/or a potential source of further information does not mean that the author or the publisher endorses the information the organization or Website may provide or recommendations it may make. Further, readers should be aware that Internet Websites listed in this work may have changed or disappeared between when this work was written and when it is read. For general information on our other products and services please contact our Customer Care Department within the United States at (800) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002. Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affiliates, in the United States and other countries, and may not be used without written permission. SlickEdit is a registered trademark of SlickEdit, Inc. All other trademarks are the property of their respective owners. Wiley Publishing, Inc., is not associated with any product or vendor mentioned in this book. Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.

For Zena.

About the Author


John Hurst has been programming computers for fun and profit since he was 14. He started with BASIC on a home computer and then moved on to Pascal and C. He has worked with many other languages since, and today works mostly with Java and Ruby. He is an independent consultant/developer and provides design, development and training services to companies in New Zealand and Australia. You can find out about John on his website at http:// www.skepticalhumorist.co.nz. John lives in Wellington, New Zealand, with his partner, Zena, and their two children, Rose and Oliver.

Credits
Acquisitions Editor
Chris Webb

Compositor
Kate Kaminski, Happenstance Type-O-Rama

Development Editor
Kenyon Brown

Proofreader
Nancy Carrasco

Technical Editor
Mark Berger

Indexer
Melanie Belkin

Production Editor
Debra Banninger

Project Coordinator, Cover


Lynsey Osborn

Copy Editor
Cate Caffrey

Media Development Project Supervisor


Laura Atkinson

Editorial Manager
Mary Beth Wakefield

Media Development Specialist


Angie Denny

Production Manager
Tim Tate

Media Quality Assurance


Kit Malone

Vice President and Executive Group Publisher


Richard Swadley

Anniversary Logo Design


Richard Pacifico

Vice President and Executive Publisher


Joseph B. Wikert

Acknowledgments
Ive read that writing a book is harder than writing software. It certainly seems harder, and it is not as much fun. But, if writing is not as much fun, reviewing must be even worse. Nevertheless, my friend and colleague Mark Berger has devoted himself thoroughly to this project, checking everything carefully and pointing out many errors. If you do find errors in the book, they were added by me after Mark had finished his job. Mark has also provided stimulus throughout my career, being well informed and passionate about software development tools and practices. My thoughts about programming and software systems have been refined continuously through many discussions with Mark over the years. The team at SlickEdit should be proud to have created one of the most useful and enduring software tools ever made. They continue to refine and enhance it every year, and during 2007 their release schedule overlapped the writing of this book for the most part. All the same, they made time to support me in writing this book, by providing early builds, explaining features, and reviewing material. It was a great privilege to talk to several SlickEdit developers and discuss SlickEdit and the book with them. Most of the SlickEdit team has made a contribution to this book in one form or another, many through providing tips and assistance on the SlickEdit Community Forums. I thank Clark Maurer, Dan Henry, Dennis Brueni, Lee Baldwin, Lisa Rodwell, Matthew Etter, Mike Cohen, Rodney Bloom, Ryan Huff, Sandra Gaskin, Scott Hackett, Scott Westfall, and the other folks at SlickEdit for all their help. Scott Westfall, in particular, reviewed every chapter and contributed material on Workspaces and Projects for Chapter 4. Dan Henry, Dennis Brueni, Lisa Rodwell, Rodney Bloom, and Sandra Gaskin reviewed chapters and contributed feedback. Rodney contributed code samples. Dennis contributed code samples, and also the troubleshooting checklist for Context Tagging in Chapter 5. Hartmut Schaefer, aka hs2, is an outstanding member of the SlickEdit online community. He has posted hundreds of posts in the Community Forums, answering questions, suggesting improvements, and finding (and fixing) bugs. Several of hs2s tips appear in this book. Thanks for everything, hs2. Other community members have also provided material online that helped this book. Graeme Prentice made several useful suggestions relating to forms and GUI elements. Graeme is a frequent contributor to the online forums. Ding Zhaojie also posts bug fixes and improvements, some of which have directly assisted me in writing this book. Dierk Knig wrote Groovy in Action (Manning, 2007), from which Ive adapted his technique for illustrating code snippets using unit testing assertions. Kenyon Brown, the Development Editor for this book, put up with a lot of annoying questions from a novice author. He also moved the book through the writing process, doing what he could to keep me focused and on schedule.

Acknowledgments
Cate Caffrey, the Copy Editor, has made me realize that I ought to go back to school and learn English. I own several books on clear writing and good English usage (more awkwardly, a number of them). However, the fact of ownership has done little to improve my own usage. If any sentence of this book reads well, it is largely thanks to Cate. Id like to thank Chris Webb, Executive Editor at Wiley, for finding me and giving me this opportunity. Chris has been wonderfully supportive (and persuasive). I also thank the management at the client where I currently do most of my work, Red Energy in Melbourne, Australia. Lucy Aston and Steve Byrne have put together a great team and a great work environment, and Im grateful that they were so understanding and supportive of this project. There is never any shortage of work to do at a startup, and I hope I can catch up on all the things I have neglected the last few weeks. Unfortunately, I think Lucy will be disappointed with this book, since it is rather dry and humorless. Wait until you see the movie though. My mother bought me my first computer, many years ago. But shes pretty smart, and before she got the computer, she gave me a book about computer programming. I think I had read the whole book at least once before I got the computer. My partner, Zena, has a ThinkGeek T-shirt that says I love my geek, and I have to believe it. Shes been wonderful, always. Maybe she can write the next book, about something other than computers.

xiv

Contents
Acknowledgments Introduction xiii xxv

Part I: Getting Started with SlickEdit


Chapter 1: Introducing SlickEdit
Programmers Edit Code Power Editing with SlickEdit
SlickEdit As a Development Environment Multiple Platforms Customizable Extensible: Slick-C

1
3
3 4
5 5 5 6

This Book SlickEdit Terminology Overview of Interface


The Build Tool Window

6 7 7
9

Commands and the Command Line


The Command Line

9
10

Key Bindings
Setting Key Bindings Listing Key Bindings

11
12 13

Macros
Recording a Macro Writing a Macro Loading a Macro Supplied Macro Source

14
14 16 17 18

Summary

18

Chapter 2: Configuration
Emulations and Key Bindings
The WROX Emulation Alt Keys

19
19
21 21

Contents
Macro Variables
Using the Set Variable Dialog Using the set-var Command

22
22 23

Common Settings
Appearance Fonts Line Behavior

24
24 25 26

Managing Configurations
Configuration Directory Reverting to the Default Configuration Working with a Different Configuration

30
30 30 31

Summary

32

Chapter 3: Managing Windows


Windows and Buffers Split Windows Full Screen Toolbars Tool Windows
Tool Window Arrangement Activating Tool Windows with the Keyboard Tool Window Animation Restoring the Defaults

33
34 34 35 35 35
36 38 40 40

Summary

40

Part II: Using SlickEdit


Chapter 4: Workspaces and Projects
How to Organize Your Files The Example Creating a GNU C/C++ Project
Creating the Project Building the Project Executing the Project Adding Unit Tests Target Configurations Build Systems

41
43
45 46 47
49 52 53 54 60 60

Creating a Java Project


Creating the Project

61
61

xvi

Contents
Building the Project Executing the Project Adding Unit Tests Managing the Project with Ant 61 62 62 65

Creating a Project for a Dynamic Language


Creating the Project Executing the Project Adding Unit Tests

65
66 66 67

Custom Projects Summary

70 72

Chapter 5: Context Tagging


Setting Up for Tagging
Tagging Your Workspace Tagging Built-in and Standard Libraries

73
74
74 74

Listing Members
Configuring List Members

76
78

Getting Parameter Information


Configuring Parameter Information

78
80

Navigating with Symbols


The Preview Tool Window Navigating to Definitions Navigating to References Pushed Bookmarks

81
81 81 82 83

Finding Symbols
The Find Symbol Tool Window Using the grep-tag command

84
84 85

Browsing Definitions
The Defs Tool Window The Class Tool Window The Symbols Tool Window

85
85 86 87

Managing Tag Files


Global Tag Databases Auto-Updated Tag Databases Tagging Dynamic Languages Tagging C/C++ Libraries Tagging Java Libraries Tagging .NET Runtime Libraries

88
89 90 90 92 98 102

The C/C++ Preprocessor Troubleshooting Tagging


Go to Definition Doesnt Work

104 105
105

xvii

Contents
Go to Reference Doesnt Work Auto-List Members Doesnt Work Auto-Parameter Information Doesnt Work Solution A: Define C/C++ Preprocessing Solution B: Add Symbol to Tag File Solution C: Configure C/C++ Extensionless Header Files Solution D: Create a File Extension Alias Solution E: Rebuild Your Tag File(s) 107 107 107 107 108 108 109 109

Performance Tuning
Tuning Maximums Tag Cache Size References Complex Code

109
110 111 111 111

Summary

112

Chapter 6: Navigation
Finding and Opening Files
Using File Open Using File and Directory Aliases Using the edit Command Using Tool Windows Using the File Manager Navigating to Header Files

113
114
114 116 117 117 119 119

Moving Around
Navigating in the buffer Positioning the Window Navigating to a Line, Column, or Byte Offset Navigating among Buffers

119
120 123 124 125

Bookmarks
Pushed Bookmarks Named Bookmarks Configuring Bookmarks

127
127 128 129

Summary

130

Chapter 7: Search and Replace


Keyboard Searching
Terminating a Long Search Quick Search Incremental Search

131
131
132 132 132

xviii

Contents
The Find and Replace Tool Window
Using Find Using Find in Files Using Replace and Replace in Files

133
134 135 137

Regular Expressions
Tagged Expressions Regular Expression Examples

137
140 141

Command-Line Search and Replace


Command-Line Options Command-Line Search Examples

141
143 145

Selective Display
Predefined Selective Display Custom Selective Display

146
146 148

Configuring Default Search Options Summary

149 150

Chapter 8: Editing Text


Using Basic Editing
Undo and Redo Line Commands

151
152
152 152

Using Selections and Clipboards


Working with the Clipboard Locked Selections Selection Models Special Selection Commands Working with Selections Using Selection Scopes Saving and Reusing Selections Configuring Selection Options

153
153 155 157 160 161 162 163 164

Saving Typing with Word Completion


Introduction to Word Completion Word Completion in Programming Options with Word Completion

165
165 168 169

Summary

171

Chapter 9: Editing Code


File Extensions, Modes, and Lexers
Extensionless Files

173
173
175

Syntax Highlighting

175

xix

Contents
Indentation and Code Style
C/C++ Options Java and C# Options HTML Options Other Languages

177
178 179 180 180

Working with Control Structures


Syntax Expansion Adding a Control Structure Dynamic Surround Deleting a Control Structure Avoiding Syntax Assistance

180
181 182 183 184 185

Unified Completions with Auto-Complete


Introduction to Auto-Complete Auto-Complete in Programming Configuring Auto-Complete Manual Completion or Auto-Complete?

186
186 188 189 190

Embedded Languages
Web Programming Here Documents in Scripts

190
190 191

Working with Comments


Line Comments Multiline Comments JavaDoc Comments Configuring Comments

192
193 194 195 195

Summary

197

Chapter 10: Editing Data


Block Selection
Moving, Copying, and Deleting with Block Selections Navigating Block Selections

199
200
200 202

Entering Data in Columns


Filling Data Using Block Insert Mode

202
203 203

Sorting Data Generating Data Calculating with Data Manipulating Data


Block Editing Macro Record and Playback Search and Replace with Data

204 205 206 207


208 213 220

xx

Contents
Aligning Data Large Data Files Summary 222 226 227

Chapter 11: Aliases and File Templates


Aliases
File Aliases Using Aliases in Code Dynamic Directory Aliases Extension-Specific Aliases Syntax Expansion with Aliases Surround Aliases Aliases with Parameters Aliases and Configuration

229
229
230 232 234 235 237 238 239 240

File Templates
Instantiating a Template Creating a Template Substitution Parameters Managing Templates Instantiating Templates in Macros

241
241 242 246 248 248

Summary

252

Chapter 12: Document Types


Document Mode Binary Files Character Sets and Encodings XML Document Types Summary

253
253 254 254 255 258

Chapter 13: Comparing and Merging


Comparing Files and Directories
Comparing Two Files Comparing Sections within a File Comparing Directories DIFFzilla Options Running DIFFzilla Standalone

259
259
260 262 265 266 266

Merging Changes Backup History Summary

266 269 270

xxi

Contents
Chapter 14: Version Control
CVS
Using an Existing Working Copy Checking Out an Existing Project Reviewing Changes Adding Files Committing Changes Merge Conflicts Using Commit Sets to Group Changes Branches and Tags Browsing the History Keyboard Bindings

271
271
272 274 275 277 278 278 279 282 283 284

Subversion
Configuring SlickEdit for Subversion Creating a New Project Checking Out a Working Copy Reviewing and Committing Changes, Adding Files Merge Conflicts Branches and Tags Browsing the History Keyboard Bindings

285
287 287 288 289 289 290 291 292

Summary

293

Part III: Advanced SlickEdit


Chapter 15: Other Tools
The File Manager
File Manager Commands Selecting Files Automating Tasks

295
297
298
299 300 301

FTP/SSH for Remote Editing


The FTP Client Using HTTP To Open Web Pages

302
304 305

The Regex Evaluator Summary

305 306

Chapter 16: Slick-C Macro Programming


The Slick-C Language
Modules and Names

307
308
309

xxii

Contents
Preprocessor Functions Properties Data Types Control Structures Declarations and Definitions 311 311 312 314 324 326

Working with Macros


Executing Slick-C Code Terminating a Macro Writing Messages Stack Traces Finding Slick-C Objects

331
332 332 332 333 334

Useful Techniques
Interacting with the Buffer Searching Selections Temporary Buffers Listing Files and Directories Choosing Files Useful Macro Files Callbacks

336
337 337 339 339 340 342 342 343

Example Macros
Example: Example: Example: Example: Example: Example: Counting Duplicate Lines Inserting HTML End Tag Moving Lines Up and Down Callback Traces WROX Function Names N-Queens

346
347 348 351 353 355 357

Summary

359

Chapter 17: Customization


Keyboard Customization
Example: Page-Down Example: Joining Lines Example: Tabbing Behavior

361
362
362 362 363

Custom Language Support


Example: Portable Game Notation Files Example: Groovy Language

365
365 367

Customizing Menus and Dialogs


Customizing a Dialog Creating a Pop-up Menu

372
372 375

xxiii

Contents
Programmatic Configuration
Loading Key Definitions and Code Defining Aliases General Configuration Settings Determining Programmatic Configuration

378
380 381 382 384

Summary

389

Appendix A: Settings for Different Emulations


Command Keys by Category
Debugging Commands Editing Commands File Commands Macro Commands Miscellaneous Commands Navigation Commands Project Commands Search Commands Toolbar Commands Window Commands

391
392
392 394 398 399 399 402 405 405 406 407

Key Commands Macro Variable Settings WROX Emulation Key Commands

408 429 431

Appendix B: Regular Expression Syntax


Predefined Expressions

435
438

Appendix C: SlickEdit Callbacks Appendix D: Whats on the CD-ROM


System Requirements Using the CD with Windows Using the CD with Linux and UNIX Using the CD with the Mac OS Whats on the CD
Author-Created Materials Applications

441 445
445 447 447 448 448
448 449

Troubleshooting
Customer Care

449
449

Index

451

xxiv

Introduction
I have been using SlickEdit almost every day for more than 10 years. For most of that time, it has been my editor of choice for almost every programming language Ive used. I strongly believe that a really powerful and versatile programming editor is the most important tool that a professional programmer uses. Im dismayed sometimes when I see programmers using IDEs ineffectively or producing substandard code because of limitations in their development environment. I wrote this book to help you get the most out of SlickEdit. I hope you enjoy it.

Whos the Book For?


This book is intended for experienced programmers. You are more than comfortable with computers. You do not need to be told how to install simple software packages, or how to navigate your directory tree to open a file, or how to select text with a mouse. You should have a preference for using the keyboard rather than the mouse, for tasks you do regularly. If you are using SlickEdit, you almost certainly have experience in other programming environments, and you probably program in more than one language, perhaps on more than one platform. On the other hand, SlickEdit is not about any particular programming language.

Whats Covered in the Book?


SlickEdit is a very feature-rich product. This book does not attempt to document every feature. The SlickEdit User Guide that is shipped with the product does not even document every feature, and it is longer than this book! Instead, this book covers techniques and strategies to make the most of SlickEdit. I hope that, by reading this book, you will learn about one or two (at least!) nice features you didnt know about. But more importantly, if you are new to SlickEdit or havent explored it in detail, I hope you will learn some ways of making it work effectively for you. It would be hard to guess which programming languages and environments are most common among SlickEdit users, since SlickEdit works well with all programming languages and most operating systems. SlickEdit has many features that support certain programming languages, but I personally feel that its feature set for C/C++ is the strongest. Nevertheless, in this book, we will not be focusing very much on particular languages. SlickEdit supports compiling running and debugging programs in C/C++ and other languages, but we wont concentrate on those aspects. Instead, were going to focus mainly on editing and related tasks, and also on how you can customize and extend SlickEdit to meet your needs, regardless of what programming language you are using. Most of the information in this book should apply to all programming languages. If you dont find examples in the language youre using, you should still find the techniques useful.

Introduction
This book is not a substitute for the online Help and other reference documentation that comes with SlickEdit. The online Help system contains detailed information organized around the features and is comprehensive and up-to-date. When we discuss features in this book, we will often give one or more examples of typical use. In some cases, well discuss options and strategies for the feature in detail, but in other cases you will be referred to the online Help for more information. I debated with myself about including so many screen shots of dialogs. In some ways theyre redundant too, since they are all covered in the online Help and you can bring up the dialogs easily enough for yourself. However, Ive found that with so many options, and so many dialogs, there are probably a few of them you wont have noticed, or wont have come across during your ordinary use of SlickEdit. Also, sometimes just seeing the options that are available in the dialogs can tell you, at a glance, something about the features available.

Conventions
To help you get the most from the text and keep track of whats happening, weve used a number of conventions throughout the book. Boxes like this one hold important, not-to-be forgotten information that is directly relevant to the surrounding text.

Tips, hints, tricks, and asides to the current discussion are offset and placed in italics like this. As for styles in the text: We highlight new terms and important words when we introduce them. We show keyboard strokes like this: Ctrl+A. We show filenames, URLs, and code within the text like so: persistence.properties. We present code in two different ways:
In code examples we highlight important code in bold

Source Code
As you work through the examples in this book, you may choose either to type in all the code manually or to use the source code files that accompany the book. All of the source code used in this book is available for download at http://www.wrox.com. Once at the site, simply locate the books title (either by using the Search box or by using one of the title lists), and click the Download Code link on the books detail page to obtain all the source code for the book. Because many books have similar titles, you may find it easiest to search by ISBN; this books ISBN is 978-0-470-12215-0.

xxvi

Introduction
Once you download the code, just decompress it with your favorite compression tool. Alternately, you can go to the main Wrox code download page at http://www.wrox.com/dynamic/books/download.aspx to see the code available for this book and all other Wrox books.

Errata
We make every effort to ensure that there are no errors in the text or in the code. However, no one is perfect, and mistakes do occur. If you find an error in one of our books, like a spelling mistake or faulty piece of code, we would be very grateful for your feedback. By sending in errata you may save another reader hours of frustration, and at the same time you will be helping us provide even higher quality information. To find the errata page for this book, go to http://www.wrox.com, and locate the title using the Search box or one of the title lists. Then, on the Book Details page, click the Book Errata link. On this page you can view all errata that have been submitted for this book and posted by Wrox editors. A complete book list including links to each books errata is also available at http://www.wrox.com/misc-pages/booklist.shtml. If you dont spot your error on the Book Errata page, go to http://www.wrox.com/contact/ techsupport.shtml, and complete the form there to send us the error you have found. Well check the information and, if appropriate, post a message to the books errata page and fix the problem in subsequent editions of the book.

p2p.wrox.com
For author and peer discussion, join the P2P forums at http://p2p.wrox.com. The forums are a Webbased system for you to post messages relating to Wrox books and related technologies and interact with other readers and technology users. The forums offer a subscription feature to e-mail you topics of interest of your choosing when new posts are made to the forums. Wrox authors, editors, other industry experts, and your fellow readers are present on these forums. At http://p2p.wrox.com, you will find several different forums that will help you not only as you read this book, but also as you develop your own applications. To join the forums, just follow these steps:

1. 2. 3. 4.

Go to http://p2p.wrox.com, and click the Register link. Read the Terms of Use, and click Agree. Complete the required information to join as well as any optional information you wish to provide, and click Submit. You will receive an e-mail with information describing how to verify your account and complete the joining process.

You can read messages in the forums without joining P2P, but in order to post your own messages, you must join.

xxvii

Introduction
Once you join, you can post new messages and respond to messages other users post. You can read messages at any time on the Web. If you would like to have new messages from a particular forum e-mailed to you, click the Subscribe to This Forum icon by the forum name in the forum listing. For more information about how to use the Wrox P2P, be sure to read the P2P FAQs for answers to questions about how the forum software works as well as many common questions specific to P2P and Wrox books. To read the FAQs, click the FAQ link on any P2P page.

xxviii

Professional

SlickEdit

Part I: Getting Started with SlickEdit


Chapter 1: Introducing SlickEdit Chapter 2: Configuration Chapter 3: Managing Windows

Introducing SlickEdit
Welcome to SlickEdit, a text editor for programmers. In this first chapter, I start by telling you something about what makes SlickEdit so good, and why I think it is one of the best programming tools around. In the remainder of the chapter, we cover some of the central concepts of SlickEdit, which we use throughout the rest of the book.

Programmers Edit Code


These days programming is dominated more and more by Integrated Development Environments (IDEs). IDEs can be very useful and productive in many situations. They tend to emphasize certain aspects of the development process such as setting up projects, organizing code, and debugging. Many tasks in IDEs are done with wizards, which lead the user through a process, collecting information to complete a task. Software development does involve a lot of different activities. Its important to use tools that make your workflow smooth and efficient. But the focus on wizards and other bells and whistles in IDEs misses an important point. Despite all these other activities, the single thing programmers spend most of their time doing is editing code. In his book Code Complete (2nd ed., Microsoft Press, 2004), Steve McConnell cites evidence that some programmers estimate they spend as much as 40 percent of their time editing source code. He recommends using a good IDE, and gives a list of features: Compilation and error detection from within the editor. Integration with source-code control, build, test, and debugging tools. Compressed or outline views of programs. Jump to definitions of classes, routines, and variables. Jump to all places where a class, routine, or variable is used.

Part I: Getting Started with SlickEdit


Language-specific formatting. Interactive help for the language being edited. Brace (begin-end) matching. Templates for common language constructs. Smart indenting. Automated code transforms or refactorings. Macros programmable in a familiar programming language. Listing of search strings so that commonly used strings dont need to be retyped. Regular expressions in search and replace. Search and replace across a group of files. Editing multiple files simultaneously. Side-by-side diff comparisons. Multilevel undo.

McConnell adds, Considering some of the primitive editors still in use, you might be surprised to learn that several editors include all these capabilities. SlickEdit is one of those editors. SlickEdit provides all the features in McConnells list, to some degree, and more. However, it is not just about features. Some of these features are about the workflow of developing software: compiling, debugging, source code control, and so on. IDEs typically do these things fairly well. Where SlickEdit really comes out on top is in editing code. Most IDEs editors, although they may have a lot of fancy features such as toolbars and Class Wizards and so forth, are simply not advanced editors. They make you type and click too much. Then there is the problem that most IDEs are only good for a single programming language or environment. Many programmers need to work in a lot of different environments, and it is frustrating and inefficient to use a different editor for each one.

Power Editing with SlickEdit


In The Pragmatic Programmer (Addison-Wesley, 1999), Andrew Hunt and Dave Thomas devote a section to Power Editing. They summarize their position as Use a Single Editor Well. They list several environment-specific features it is desirable for an editor to have, such as syntax highlighting, autocompletion, and autoindentation. But more important than any such specific features, they outline three basic abilities we think every decent editor should have: Configurable All aspects of the editor should be configurable to your preferences, including fonts, colors, window sizes, and keystroke bindings (which keys perform what commands). Using only keystrokes for common editing operations is more efficient than mouse or menudriven commands, because your hands never leave the keyboard.

Chapter 1: Introducing SlickEdit


Extensible An editor shouldnt be obsolete just because a new programming language comes out. It should be able to integrate with whatever compiler environment you are using. You should be able to teach it the nuances of any new language or text format (XML, HTML version 9, etc.). Programmable You should be able to program the editor to perform complex, multistep tasks. This can be done with macros or with a built-in scripting language (Emacs uses a variant of Lisp, for instance).

These abilities are at the center of SlickEdits philosophy and design.

SlickEdit As a Development Environment


IDEs tend to be targeted at specific programming platforms and specific development processes. They automate a variety of standard tasks with wizards and other tools. They can be very productive if you are comfortable working the IDEs way. SlickEdit has a lot of overlap with IDEs. It also provides support for a lot of IDE-type features: building, running, and debugging programs. The main focus of SlickEdit is a little different though. Rather than focusing on a particular programming platform, SlickEdit places the emphasis on editing and navigating code. The SlickEdit philosophy is that programmers spend most of their time writing code, and SlickEdit aims to make that as fast and productive as possible. SlickEdit is fast. IDEs get loaded up with more and more features. Many of them are useful, but they all come at a price. How long does it take the IDE to open a file? How responsive is it while typing in code? Many IDEs have so many intelligent features that they spend a lot of time thinking while youre trying to type in code. SlickEdit is always responsive.

Multiple Platforms
SlickEdit is not tied to a particular programming platform. Most of its features are generic and apply equally well to any programming language or platform. On top of that, it does provide IDE-like tools and language-specific support for many popular programming languages. SlickEdit is also not tied to an operating system. I started using SlickEdit on OS/2, but Ive also owned copies for Windows, AIX, and GNU/Linux. Virtually all the functionality is the same. Just as importantly, the customizations and macros Ive done while using one operating system have all been carried through to other operating systems. I dont have to learn a whole new tool and create a whole new set of customizations, just because I am switching from Windows to GNU/Linux for a project.

Customizable
SlickEdit is very customizable. Out of the box, SlickEdit provides emulations for more than a dozen popular editors. These emulations provide a basic starting point for the behavior of the editor. Virtually every aspect of the editor can be customized. Dont like the way the Enter key moves to the next line? You can change it. Dont like the indentation or brace style? You can change them.

Part I: Getting Started with SlickEdit


Many configuration settings are available as settings in the extensive configuration dialogs. Others are controlled by environment and macro variables. But it doesnt stop there. Beyond configuration, SlickEdit is also very extensible. Many Integrated Development Environments (IDEs) are extensible to some degree. These days, plug-ins are a popular way to extend IDEs. But in most cases, the plug-in system is relatively complex, with a steep learning curve before anything useful can be achieved. Because most plug-ins require a considerable amount of work, plug-ins are generally used for significant add-on modules only.

Extensible: Slick-C
You can customize and extend SlickEdit using Slick-C, a macro, or scripting language. One of the most important goals in this book is to introduce you to Slick-C and show you how easy it is to use it to customize or extend SlickEdit. Slick-C is easier to use than most plug-in systems. Slick-C is named after C and derives many of its features from C, such as control structures and declaration style. But Slick-C is really more of a scripting language. It is remarkably easy to learn and to use and is much more productive to code in than C. So if youre not a C programmer, or you dont like C, dont worry. Even if it sounds too hard for you, try it! You will be surprised. Many of SlickEdits features are implemented in Slick-C. The complete source code for those features is provided with the product, more than 750,000 lines of it at last count! Having the source code to such a major part of SlickEdits functionality makes using it a lot like using an open-source product. If youve worked with open-source libraries or tools, you probably know how useful it is to be able to dive into the source code. You can often use features more effectively if you know how they really work. You can extend or alter features if they dont fit your needs. You can write your own features. And, sometimes, you may even find a bug and see how to fix it. All of these benefits apply to SlickEdit and its supplied Slick-C source code, even though SlickEdit is a commercial product. This book aims to explain some details about macro programming and provides many useful examples you can use or adapt to your own needs. As we discover features of SlickEdit, we will often show examples of how they can be used or extended with Slick-C. The last two chapters of the book go into Slick-C in depth and show detailed examples of customization. But, as we mentioned already, the main point is to show you how easy it is and to get you started on your own macros.

This Book
SlickEdit is a powerful and versatile programming editor. Much of its power comes from its design and the large number of features that are included. Some important features are very simple, like being fast to edit and navigate even very large files. Some features are advanced and specific, such as syntax assistance for various programming languages. We will be covering a lot of these features throughout this book. However, most of these features are already covered pretty well in the User Guide and Online Help shipped with the product. This book is not a reference manual and is not intended to replace the user guide. While we will cover some details of many of the features, we will focus more on general capabilities and the versatility of SlickEdit.

Chapter 1: Introducing SlickEdit


This book is written from my own perspective. I was a C++ programmer when I started with SlickEdit, and C/C++ programming is perhaps SlickEdits strongest area. But Im not a C/C++ programmer now, and I have not used SlickEdit for C or C++ for quite some time. I dont know the details of many aspects of C/C++ features in SlickEdit, and we wont be covering those features. For example, SlickEdit has debugger integration, but we dont cover that at all in this book. Although SlickEdit is available for many different operating systems, Windows is probably the most common. The screen shots in this book are almost all taken on Windows. In most cases, the discussion should apply to all operating systems equally well, but in some cases there are differences. For example, Macs use different keyboards from most computers, thus the discussion of Alt key bindings in Chapter 2 does not work with Macs. The current version of SlickEdit at the time of this writing is 12.0.2, which was released in July 2007. The 12.x series of SlickEdit is marketed as SlickEdit 2007. Most of this book was written using SlickEdit 12.0.0 and 12.0.1 for examples. Naturally, things change from version to version. I hope that most of the material in this book will remain useful and relevant through future versions of SlickEdit, but without doubt some changes in future versions will be incompatible with information presented here. Updates to macro sources will be placed online.

SlickEdit Terminolog y
Before we start to look at SlickEdit concepts, we should get a few terms straight. When you open a file in SlickEdit, the file is loaded into a buffer. The buffer is the in-memory representation of the file. The buffer has the same name as the physical file. Changes to the buffer are saved to disk when you save the file. Sometimes the terms file and buffer are used interchangeably. The buffer is displayed in a window. The window is the GUI view of the buffer. In the default configuration, there is one window created for each buffer. We talk about managing windows in more detail in Chapter 3. In this book, while explaining certain dialogs, we use phrases such as Click OK to dismiss the Project Properties dialog. Most of the time, of course, you will not actually click OK; rather, you will simply press Enter, because OK is the default button. However, we stick to the Click terminology most of the time, because it is commonly used in help and user guides, and it makes it clear which dialog control we really mean. After all, if you tab around, the focus might change to a control where the Enter key is not the same as clicking OK.

Over view of Interface


Figure 1-1 shows the SlickEdit user interface. The main part of the window is the editing pane. Below the editing pane is the File Tabs toolbar, showing the open files. SlickEdit has several other toolbars, not shown. Toolbar functions are generally invoked using the mouse, and in most cases it is a lot faster and easier to use the keyboard, rather than the mouse.

Part I: Getting Started with SlickEdit

Figure 1-1

Many computer users use the mouse a lot. The mouse is a great way to learn a program. When you first start using a program, you use the mouse to browse around. Its kind of like browsing the Web: Youre just looking around; you arent really doing anything. Once you start really using a program to do things, you tend to find youre doing some things a lot. For those things, you will do them a lot faster using the keyboard. For example, saving a file is something you do a lot. You can use the mouse to click the File menu on the menu bar, and then click Save. But thats a lot of work just to save the file. Having a toolbar with a Save icon isnt much better. Since the goal of this book is to save you work, well mostly be looking at using the keyboard, especially for things you need to do a lot. For that reason, we wont talk much about toolbars. As well as toolbars, SlickEdit also has tool windows. Tool windows tend to contain considerably more information and functionality than toolbars. They are like miniature applications within the editor. There are many tool windows, and it is not feasible to show them all on the screen at the same time. In Figure 1-1, there are several tool windows that are hidden and are only visible through their tabs, which are arranged down the left- and right-hand sides, and across the bottom (under the File Tabs toolbar). In Chapter 3, we will see how to arrange the tool windows effectively and how to invoke them using the keyboard. The most commonly used tool windows can be used quite effectively without the mouse. At the bottom of the screen, on the left, is the message area, which doubles as the command line. Well discuss commands and the command line in detail shortly.

Chapter 1: Introducing SlickEdit


To the right of the message area are several status indicators. For example, you can see the current line and column, the state of the current selection, and the character code at the cursor position. There is a lot more to SlickEdit than this main window. We cover many dialogs and tool windows throughout the book.

The Build Tool Window


One tool window worth mentioning now is the Build tool window. This tool window contains build output when you compile and/or run programs within SlickEdit. We cover compiling and running in Chapter 4. The Build tool window also provides an operating system shell environment. For example, Figure 1-2 shows the Build tool window with the output of a dir command on Windows. You can enter any operating system command in the Build tool window. You can also navigate around the window, scroll back through its history, and copy/paste from and to it.

Figure 1-2

Commands and the Command Line


Commands are at the core of SlickEdits power and flexibility. Virtually every operation in SlickEdit is a command. For example, simple cursor movement is performed by the commands cursor-up, cursordown, cursor-left, and cursor-right. Complex operations are also performed by commands, such as config and project-compile. In fact, SlickEdit ships with several thousand commands! Dont worry though; you only need to remember a small fraction of these to master SlickEdit. When a command consists of two or more words, it is defined internally in SlickEdit with the words separated by underscores, like cursor_up. You will use this form when you define your own commands. However, for better readability, SlickEdit displays these commands using hyphens instead of underscores, and they can usually be entered either way: cursor-up or cursor_up. Commands are fundamental to the way SlickEdit works, particularly when customizing and extending SlickEdit via macro programming. For example, when doing macro programming, you probably will have occasion to use the cursor-up command to move the cursor. With this in mind, we focus on command names first and give keyboard shortcuts and menu choices when applicable. When we introduce a feature, well show the SlickEdit command for that feature, and then, if there is one, the standard key binding or menu item.

Part I: Getting Started with SlickEdit


Commands can be invoked in several different ways: All commands can be entered on the command line. Commands without mandatory arguments can be bound to keyboard shortcuts. Commands without mandatory arguments can also be added to toolbars and menus. Commands can be invoked by other Slick-C macros and commands.

Commands can have arguments, and these arguments can be mandatory or optional. For example, cursor-up can take an optional numeric parameter specifying how many lines to move up. When you invoke a command via a keyboard shortcut, toolbar, or menu, no arguments are provided. A command may prompt for an argument in these cases. An example of a command for which you would normally provide an argument is find.

The Command Line


The bottom-left area of the SlickEdit window doubles as both a message area and the command line. Use the Escape key to toggle the cursor between the edit buffer and the command line. Even toggling from and to the command line is done by a command: cmdline-toggle. The cmdlinetoggle command is bound to the Escape key in CUA and several other emulations. In other emulations, it is bound to different keys. When you start typing a command, SlickEdit begins prompting with matching commands based on what you have typed, as shown in Figure 1-3.

Figure 1-3

When you enter a command on the command line, you can specify arguments. Many commands know what kinds of arguments they require, and SlickEdit can autocomplete arguments for these commands. For example, if a command requires a filename, SlickEdit can complete filenames or directories from the current directory on the command line. Figure 1-4 shows an example.

Figure 1-4

Autocompletion for command-line arguments works for several other kinds of arguments, as well as files.

10

Chapter 1: Introducing SlickEdit


Well show how you can make autocompletion work with your own commands in Chapter 16. When autocomplete for command-line arguments is active, you can also press the question mark key to open a selection list for matching arguments. The command line also supports history. You can navigate backward and forward through the history list using the up and down arrow keys. You can edit commands and execute them again. You can enter several different types of commands on the command line. These include: SlickEdit Commands These can be commands provided by SlickEdit, such as find, or commands you write yourself in Slick-C. There is no difference between SlickEdit-provided commands and user-written commands. Slick-C batch macros These are routines written in Slick-C that are not compiled into internal commands. Operating System Commands You can enter any operating system command on the SlickEdit command line, as well as in the Build tool window.

We cover Slick-C batch macros in Chapter 16. If you want to enter an operating system command that has the same name as a SlickEdit command, use the dos command. For example, suppose you want to run the operating system find command. Since there is a SlickEdit command named find, you need to enter dos find on the command line. Although the dos command appears to be named after the DOS operating system, it actually works on all operating systems. An operating system command is run in its own window. The window closes after the command completes. You can use the dos command with the w option to keep the window open until you press a key. Alternatively, if a command has output you want to see, you can use the Build tool window instead of the command line. There are several SlickEdit commands with the same name as operating system commands. Weve seen find as one example. A few more are:
cd del dir and ls pwd

Key Bindings
You can bind commands to keys. Many commands are bound to keys already when you install SlickEdit. The set of default key bindings you select when you install SlickEdit is called an emulation. In this book, we assume that you are using the CUA emulation. We cover emulations in more detail in Chapter 2.

11

Part I: Getting Started with SlickEdit


If you want to find out what command is bound to a key, use the what-is command, like this:

1. 2.

Enter what-is on the command line, and press Enter. SlickEdit prompts you to press a key. Press a key. If the key has a command bound to it, SlickEdit tells you what command the key runs. Otherwise, SlickEdit pops up a message box saying that the key is not defined.

If you want to find which key(s) a command is bound to, use the where-is command. For example, to find out which key the save command is bound to, enter the command where-is save. SlickEdit displays a message showing the key for the save command.

Setting Key Bindings


You can review and edit key bindings using the Key Bindings dialog (Tools Options Key Bindings). The Key Bindings dialog is shown in Figure 1-5.

Figure 1-5

The Key Bindings dialog has several different features. Lets use it to bind a command to a key. The quick-search command is a useful shortcut for searching for the word at the current cursor position. But the command is not bound to a key in the CUA emulation. Lets bind it to Ctrl+F3 using the Key Bindings dialog. With the dialog open, follow these steps:

1. 2.

Enter quick-search in the Search by command field. SlickEdit updates the commands listed as you type. When youve typed the whole command, the list is narrowed down to just that command. This list also shows that the command is not currently bound to any key. Click in the Search by key sequence field.

12

Chapter 1: Introducing SlickEdit


3. 4.
Press Ctrl+F3. If the key is already used by a command, that command is added to the list so that you can see it. Click the Add button to add the binding. SlickEdit displays the Bind Key dialog, shown in Figure 1-6.

Figure 1-6

5.

Click Bind to bind the key. If the key you have chosen is currently bound to a command, SlickEdit warns you and asks you to confirm that you wish to continue.

A given command can be bound to many different keys, but a given key or key combination can have only one command bound to it. You can use Ctrl, Alt, and Shift combinations to make key bindings unique. For example, Ctrl+Shift+F3 is distinct from Ctrl+F3. Ctrl+Alt+Shift+F3 is different again. Commands can be bound to sequences of keys. For example, you could bind a command to Alt+T followed by P. The beginning part of the sequence cannot itself have a command bound to it, because that would be ambiguous. But you can use different keys for the ending part. You could have one command bound to Alt+T followed by P, and another to Alt+T followed by F. This is one way to overcome the problem of running out of keys, if you want to bind a lot of commands. Well see a couple of applications of this idea below. You can use the Key Bindings dialog to review related commands and their key bindings. If you type search into the Search by command field, you see all commands containing the word search. The Key Bindings dialog has several other features too. You can remove key bindings, and you can export your key bindings as an HTML file. Most key bindings are done for the default mode, called the fundamental mode in SlickEdit. SlickEdit also has several other modes. Each family of programming languages has a mode, for example, C, Java, HTML. There are also specialized modes for certain SlickEdit features. Some keys have special commands bound to them per mode. For example, some keys trigger syntax assistance for certain programming languages, such as Space, (, and { in C. The Key Bindings dialog shows modes for key bindings, if they apply. Bindings with modes showing as default apply to the fundamental mode.

Listing Key Bindings


To list all the key bindings, enter the command list-keydefs. SlickEdit creates a new buffer called keydefs.e and fills it with Slick-C definitions for all the key bindings. This listing can be useful for

13

Part I: Getting Started with SlickEdit


comparing large sets of key bindings, such as those provided by different emulations. It can also help sometimes if you are trying to plan a set of key bindings and need to review which keys are currently in use and which are not. Appendix A contains several tables listing key bindings.

Macros
The term macro is used generically in SlickEdit to mean any of these things: Any Slick-C routine. A Slick-C command. A Slick-C batch macro.

In this section, we are referring to macros in the command sense. This section shows you how to create your own commands in SlickEdit. Well start with recorded macros and then give an introduction to writing macros in Slick-C and compiling them. After reading this section, you will be ready to compile and load the example macros presented throughout the book. We cover macro programming in more detail in Chapter 16.

Recording a Macro
The first kind of macro that most people encounter is the recorded macro. This is probably the quickest way to get started with Slick-C programming and is also a great way to see how easy it is. SlickEdit provides two commands for creating recorded macros and playing them back, shown in Table 1-1.

Table 1-1
Command
record-macro-toggle

Key Ctrl+F11

Description Start recording macro, or stop recording and save macro. Stop macro recording and execute macro.

record-macro-end-execute

Ctrl+F12

Lets record a macro to duplicate the current line. Well also bind this key to Alt+quote. It turns out that SlickEdit already has a duplicate-line command. Also, we cover line selections and copy commands in more detail in Chapter 8. For now, just follow along with the example. This example assumes that you have the CUA emulation loaded. Before you start, you also need to have a buffer open with the cursor on a line in the buffer. To record the macro, follow these steps: 1. Invoke record-macro-toggle (Ctrl+F11). SlickEdit prompts you with a message and shows the macro recording status indicator as shown in Figure 1-7.

14

Chapter 1: Introducing SlickEdit

Figure 1-7

2. 3. 4. 5.

Invoke select-line (Ctrl+L). SlickEdit selects the line. Invoke copy-to-clipboard (Ctrl+C). Invoke paste (Ctrl+V). SlickEdit pastes a copy of the line. Invoke record-macro-toggle. SlickEdit displays the Save Macro dialog, shown in Figure 1-8.

Figure 1-8

6. 7.

Enter wrox-dup-line as the Macro Name. This becomes the name of the command, if you should want to invoke it from the command line or from another macro. Click Save. SlickEdit displays the List Macros dialog, shown in Figure 1-9. The List Macros dialog lists user-recorded macros and allows you to manage them.

Figure 1-9

8.

Click Bind to Key. SlickEdit displays the Key Bindings dialog, with wrox-dup-line shown in the command list.

15

Part I: Getting Started with SlickEdit


9. 10. 11. 12. 13.
Click in the Search by key sequence field. Press Alt+quote. Click Add. SlickEdit displays the Bind Key dialog with wrox-dup-line as the command, and Alt+ as the key sequence. Click Bind. SlickEdit adds the binding and updates the Key Bindings dialog. Click Close to close the Key Bindings dialog.

Congratulations! You have created a macro and bound it to a key. Try it now by pressing Alt+quote a few times. It should duplicate the line the cursor is on. The exact behavior of commands like copy-to-clipboard and paste can vary with some configuration settings. If you are not using CUA emulation, or you have altered other settings, you may need to follow a slightly different sequence of steps to duplicate a line. In particular, if the line remains selected after you invoke copy-to-clipboard, you need to invoke deselect (Ctrl+U) afterward. When you record a macro and save it with a name, SlickEdit places the source code for your macro into a file called vusrmacs.e in your configuration directory. On Windows, the default location for the configuration directory is in the My SlickEdit Config directory in My Documents. The configuration directory is named after the SlickEdit version number, for example, 12.0.2. We cover the configuration directory in more detail in Chapter 2, including how you can specify its name and location. If you record a macro and do not give it a name (e.g., by pressing Escape in the Save Macro dialog), SlickEdit names it last_recorded_macro and stores the source in lastmac.e in your configuration directory. Unnamed macros are handy for sequences of commands you want to repeat quickly a few times, but not save. You can invoke the last unnamed recorded macro using record-macro-end-execute (Ctrl+F12). If you can plan to finish recording your macro so that your cursor is already set up for the first invocation, you can use record-macro-end-execute to finish the recording and execute the macro immediately. This is very handy for doing repetitive edits on multiple lines, or at multiple search matches. We cover some more examples of unnamed macro recording and playback in Chapter 10. If you are recording a macro and wish to abort recording, press Escape. SlickEdit confirms that you have canceled recording with a message, shown in Figure 1-10.

Figure 1-10

Writing a Macro
Locate and open the vusrmacs.e file. You should find that it contains content like this:
#include slick.sh _command wrox_dup_line() name_info(,VSARG2_MACRO|VSARG2_MARK|VSARG2_REQUIRES_MDI_EDITORCTL) {

16

Chapter 1: Introducing SlickEdit


_macro(R,1); select_line(); copy_to_clipboard(); paste(); }

The macro youve recorded for duplicating a line is a nice start, but it could be somewhat better. Some of the drawbacks of the macro as it stands are: It uses selections, which means it disrupts any existing selection. It uses the clipboard.

It would be better if we had a command for duplicating a line without disrupting either the selection or the clipboard. We can do this by editing the code SlickEdit placed in vusrmacs.e. Dont worry too much about the details for now. Change the macro body of wrox_dup_line() to look like this:
#include slick.sh _command wrox_dup_line() name_info(,VSARG2_MACRO|VSARG2_MARK|VSARG2_REQUIRES_MDI_EDITORCTL) { push_bookmark(); _str the_line; get_line(the_line); insert_line(the_line); pop_bookmark(); }

Now, instead of using clipboard and selection commands, we are manipulating the buffer directly. We also added push_bookmark() and pop_bookmark() to ensure the cursor remains on the original line after duplicating it. We cover bookmarks in more detail in Chapters 5 and 6. However, simply changing the text in the source file is not enough to change the behavior of the macro in SlickEdit. SlickEdit macros are loaded (compiled), thus we need to get SlickEdit to reload our macro. (Recorded macros are automatically loaded.)

Loading a Macro
Compiling a macro and loading it into memory in SlickEdit is referred to as loading the macro. To load the macro, ensure that vusrmacs.e is in the current buffer. Then invoke the load command (F12). If there are no errors, SlickEdit reports that the module is loaded, as shown in Figure 1-11.

Figure 1-11

You can place macro code in any file you like. By convention, Slick-C code is stored in files with the extension .e. Throughout this book, we give more examples of Slick-C code. The examples are all included on the accompanying CD-ROM, in files under directories corresponding to the chapter in

17

Part I: Getting Started with SlickEdit


which the code is presented. For example, the wrox-dup-line command above is found in Author/ Chapter01/wrox_dup_line.e. To load any example, simply open the .e file in SlickEdit, and invoke the load command (F12). We cover modules and loading in more detail in Chapter 16, along with other aspects of Slick-C programming.

Supplied Macro Source


The entire source code for all of SlickEdits features that are implemented in Slick-C is included with the product. The macro source is installed in the macros/ directory underneath the product installation directory. In this book, we occasionally refer to files in the supplied macro source.

Summar y
In this chapter, we introduced SlickEdit and explained what differentiates it from IDEs and other tools for programming. The most important things that differentiate SlickEdit are: SlickEdit is configurable. SlickEdit is extensible. SlickEdit is programmable.

We covered some central concepts in SlickEdit: the command line, key bindings, and recording and loading macros. These concepts are used throughout the rest of this book. In the next chapter, we look in detail at some general aspects of SlickEdit configuration.

18

Configuration
SlickEdit has hundreds of configuration options. It is one of the most configurable software products you will ever find. As with most configurable software, SlickEdit comes with reasonable defaults. Nevertheless, in this book, we suggest that you should consider some alternatives to the defaults. In some cases, the default settings are designed to make SlickEdit familiar to users with experience with other common programs, such as Visual Studio or Windows Notepad. But Notepad is not the most effective programming editor, and SlickEdit has alternative ways of doing things that can be more powerful. We introduce a few of these in this chapter. In the first part of this chapter, we cover some general information about configuration to give you the big picture. We discuss SlickEdits emulations, which provide behavior compatible with a selection of other editors. We introduce the WROX Emulation, which extends SlickEdits default emulation to provide more key bindings for useful commands. In the second part of the chapter, we take a look at several common settings you might consider changing in order to get the most out of SlickEdit. These include obvious things such as fonts and also some subtler points like how SlickEdit treats cursor movement and line wrapping. Finally, we explain SlickEdits configuration directory, and how you can manage SlickEdit configuration data.

Emulations and Key Bindings


During the installation process, you are prompted to select an emulation. The emulation defines keyboard shortcuts and other behavior in the editor. SlickEdit ships with more than a dozen emulations, providing compatibility with several other popular editors. Appendix A includes listings of key bindings for some popular emulations. The default emulation is CUA (Common User Access). Some of the other emulations, such as Visual C++ and Visual Studio, are very similar to CUA. Others are different, reflecting quite different user-interface styles.

Part I: Getting Started with SlickEdit


CUA is an acronym for Common User Access, the user interface standard developed by IBM and Microsoft during the 1980s. CUA defines standard menus such as the File and Help menus. It also defines standard behavior for some function keys, such as F1 for help, and key combinations such as Ctrl+X, Ctrl+C, and Ctrl+V for cut, copy, and paste, respectively. You can change emulation at any time by choosing Tools Options Emulation from the main menu. You should be aware that changing emulations is not a perfectly reversible process. If you change from CUA emulation to Brief, for example, and then back to CUA, your CUA settings are not completely restored to what they were before. To get a clean configuration with a given emulation, you need to start with a default, or empty, configuration. We cover managing configurations in more detail below in this chapter. Configuring your settings programmatically is also a good way to reset your settings reliably. We cover programmatic configuration in Chapter 17. You can understand key bindings for emulations by reading the emulation chart or using the Key Bindings dialog. To understand emulation settings other than key bindings in detail, you need to study the Slick-C code defining the emulation. The Slick-C files defining the different emulations are listed in Table 2-1.

Table 2-1
Emulation BBEdit (Mac) Brief CodeWarrior CodeWright Epsilon GNU Emacs ISPF SlickEdit Visual C++ 6 Vim Visual Studio CUA Xcode Source File
bbeditdef.e briefdef.e codewarriordef.e codewrightdef.e emacsdef.e gnudef.e ispfdef.e slickdef.e vcppdef.e videf.e vsnetdef.e windefs.e xcodedef.e

20

Chapter 2: Configuration

The WROX Emulation


This book provides an extension to the CUA emulation called the WROX emulation. You can find the definitions for the WROX emulation in the file Chapter02/wrox_emulation.e on the books CD-ROM. To load the emulation, open wrox_emulation.e in SlickEdit, and invoke the load command (F12). The WROX emulation affects only key bindings. In most cases, it defines additional key bindings for commands not bound in the CUA emulation. In a few cases, it changes CUA key bindings. Many of the bindings in the WROX emulation are copied from the SlickEdit emulation, where the SlickEdit defines a key binding for a key not bound in the CUA emulation. Throughout this book, we assume that you are working with either the CUA or the WROX emulation. When we present key bindings, we identify WROX-specific bindings explicitly; otherwise, all key bindings in this book are defined in the CUA emulation. You can use the WROX emulation as a starting point for your own customizations. As well as adding or changing bindings for commands you use frequently, you can also remove bindings for commands you dont use, so that you dont invoke them accidentally.

Alt Keys
One standard defined by CUA is that you can use Alt key combinations to access the main menu. Thus, for example, you can press Alt+F to open the File dropdown menu from the main menu bar. This is a convenient and intuitive way to learn the menus in an unfamiliar program. This discussion of Alt keys applies to PC-type keyboards, generally for Windows, Linux, and often for UNIX too. Because Macs use a different keyboard, much of this discussion does not apply to them. Also, the WROX emulation would need to be modified for its Alt key bindings to work on a Mac. Many programs use Alt keys for other functions besides invoking menus. Some programs split the use of Alt keys: The ones that are required for invoking main menu items such as File and Help are reserved for those, and the others are free to be mapped to other functions in the program. SlickEdit provides an option to get more use out of the Alt keys. This option is based on the premise that the menus are mainly used when learning the program, or for functions that are used infrequently. For often-used functions, direct invocation by a keyboard shortcut is faster than using the menu. (Its less keystrokes, and less screen activity.) If you bind an Alt key that is used as a menu shortcut to a command in SlickEdit, the command takes precedence. For example, Alt+F is the shortcut for the File menu in the menu bar, but the WROX emulation binds Alt+F to fill-selection. When you press Alt+F, you get fill-selection. You might be wondering how you access menu functions with the keyboard with this setting. You press and release the Alt key by itself to invoke the main menu. (This works on most Windows programs as an alternative way to invoke the main menu.) Then you press the mnemonic key for the menu item you wish to invoke, for example, F for the File menu. If you change your mind while the focus is in the menu bar and do not wish to invoke a menu item, press the Escape key to return the focus to the buffer. It should be noted that the Alt menu setting on the General tab of the General Options dialog (Tools Options General) controls this behavior. If you unselect Alt menu, you cannot use the Alt key to toggle the focus to and from the menu bar.

21

Part I: Getting Started with SlickEdit

Macro Variables
Macro variables control a large number of SlickEdits configuration settings. Many settings can be changed through the configuration dialogs, but some settings can be changed only by setting the values of macro variables. For example, the def_undo_with_cursor macro variable controls whether undo steps backward through cursor movement. The setting can only be changed through the macro variable. See Chapter 8 for more details about undo in SlickEdit. It is important to understand macro variables for several reasons: Some settings have no GUI dialog to configure them and can be controlled only by setting macro variables. Macro variables provide a way to configure SlickEdit programmatically. Understanding macro variables can help you understand the behavior of many features of the editor, when viewing macro source code.

See Chapter 17 for more details about programmatic configuration using macro variables, and understanding editor behavior. In many parts of this book, when we discuss features, we mention macro variables that are used to configure options on those features. The following sections explain how to query the current value of a macro variable, and how to set a macro variable.

Using the Set Variable Dialog


The Set Variable dialog provides a GUI dialog you can use to query or change the value of any macro variable. To query or set a macro variable using the Set Variable dialog, follow these steps:

1.

Invoke gui-set-var (Macro Set Macro Variable). The Set Variable dialog appears, shown in Figure 2-1.

Figure 2-1

2.

Specify the name of the variable. As you type, a dropdown appears with matching names, as shown in Figure 2-2.

Figure 2-2

22

Chapter 2: Configuration
3.
When you have selected the desired variable, press Enter. The dialog displays the current value, as shown in Figure 2-3.

Figure 2-3

4.

If you wish to change the value, enter the new value and click OK. SlickEdit updates the variable.

Using the set-var Command


While the Set Variable dialog is easy to use, its often faster to use the set-var command on the command line. To query or set a macro variable using the set-var command, follow these steps:

1. 2.

Open the command line. Type the command set-var, followed by a space. The command line appears, as shown in Figure 2-4.

Figure 2-4

3.

Type part of the name of the variable. The command line prompts you for matching variables, as shown in Figure 2-5.

Figure 2-5

4.

When you have selected the desired variable, press Enter. The command line displays the current value, as shown in Figure 2-6.

Figure 2-6

5.

If you wish to change the value, enter the new value and press Enter. SlickEdit updates the variable.

23

Part I: Getting Started with SlickEdit

Common Settings
In this section, we cover various common configuration settings. There are many more settings available in SlickEdit other than those covered here. The ones covered here are chosen because they are commonly needed by users but are not necessarily obvious in the interface.

Appearance
In this section, well mention a few basic things you can do with the appearance of SlickEdit that might not be obvious. Most of these settings have value beyond pure aesthetics. They are intended to provide visual clues to make you more productive.

Maximize First Window


By default when you install SlickEdit, windows are cascaded in the editor. They are small and dont show many lines of your source files. Check the Maximize first window checkbox on the General tab of the General Options dialog (Tools Options General). With this setting, buffers are opened in windows that fill the entire SlickEdit application window. This is usually a more effective way of working when programming. We talk about managing windows in more detail in Chapter 3.

Draw Box around Current Line


It can be quite helpful to be able to see at a glance which line your cursor is on. SlickEdit provides several choices for this, found on the General tab of the General Options Dialog (Tools Options General). You can have no box (the default), a simple box, or one of several ruler styles. Try the ruler styles, and use one of them if you like it; otherwise use the plain box. You can also customize the color of the box or ruler if you wish. You can add per-extension current line highlighting too. This is hidden away in the Advanced tab of the Extension Options dialog (Tools Options Extension Options). There are two checkboxes in the Color coding section labeled Modified lines and Current line. If you check the Current line checkbox, the current line gets color syntax highlighting, in addition to any box or tabs. If you check the Modified lines checkbox, SlickEdit marks changed lines with color in the left margin. The modification markers remain visible as long as the file is loaded. Note that the Current line and Modified lines settings need to be set independently for each file extension. See Chapter 13 to find out other ways you can see what changes you have made to a file.

Vertical Line Column


Also on the General tab of the General Options dialog is the option to place a vertical line on the screen at a certain column. You can use this if you prefer to limit the length of lines in your source files, perhaps for printing purposes. Some coding conventions place a maximum on source file line length. You can change the color of the line and what column it appears in.

24

Chapter 2: Configuration
Show Top of File Line
Also on the General tab of the General Options dialog is the Top of file line option. This line provides a visual cue to show you are at the top of the file. More importantly, depending on your emulation and other configuration settings, some operations that affect the line after the cursor position are not possible unless you can place the cursor before the first line. For example, in the default configuration, copying or moving an entire line places the line after the current line. If you want to copy or move a line to the start of the file, you need to be able to put the cursor before the first line. The top of file line lets you do this. We look at copying and moving lines in Chapter 8.

Left Margin Size


SlickEdit places several markers in the left margin, for example, the modified line colors seen above. Another example is bookmark icons. Sometimes when you activate different features in the editor that use the left margin for visual cues, it causes the margin to be resized. This can be distracting. You can reduce the amount of resizing that occurs by setting the margin to a sufficiently large initial size, such as 0.25 inches. This setting is found on the More tab of the General Options dialog. We cover bookmarks in detail in Chapters 5 and 6.

Special Characters
Another useful setting for visual cues is to make special characters visible. You can do this by invoking view-specialchars-toggle (View Special Characters). Special characters include: End of line. Tab. Space. Virtual Space. End of File.

You can customize how SlickEdit displays each special character on the Special Characters tab of the General Options configuration dialog.

Fonts
Fonts are a rather obvious visual setting. SlickEdit allows you to change the font for several different screen elements. Use the Font Configuration dialog (Tools Options Fonts) to configure fonts. The most important elements are: SBCS/DBCS Source Windows (Single-Byte Character Set and Double-Byte Character Set) Used for most programming work. Hex Source Windows Used mostly for displaying binary files and checking for special characters. Unicode Source Windows Used mostly for XML.

We discuss some Unicode-specific issues in more detail in Chapter 12.

25

Part I: Getting Started with SlickEdit


However, if you change these, you will likely also want to change: File Manager Windows. Diff Editor Source Windows. Selection List.

You need to change the font for each screen element individually. Chapter 17 shows how you can use a Slick-C script to set your fonts programmatically. There are many resources on the Web for fonts for programming. You can find a lot of fonts listed and compared at these sites:
http://keithdevens.com/wiki/ProgrammerFonts http://www.lowing.org/fonts/

The default font for SlickEdit on Windows is Courier New. While this is a widely used monospaced font, it is not specifically designed for programming. Some people find the serif look of Courier New cluttered and distracting and prefer a more open sans-serif font. Lucida Console is also available as standard with Windows and is less cluttered than Courier New. However, the spacing and relative sizes of characters are still not ideal for programming. Bitstream Vera (http://www.gnome.org/fonts/) is an example of a font that works well for programming. It is open and clear. It has a numeric 0 (zero) that is easily distinguished from a capital O (oh), and a numeric 1 (one) that is easily distinguished from a lowercase L. It also has large, easily distinguished punctuation characters such as colon, semicolon, period, and comma. SlickEdit ships BitStream Vera in its Mac installation. For other operating systems, you can download BitStream Vera from the URL above. Try it out.

Line Behavior
One fundamental choice you can make when using SlickEdit is whether you want the editor to treat the buffer as a stream of text, or a collection of lines. Most Windows and UNIX editors lean toward the stream model for text. Thus, for example, if you move the cursor to the end of a line, and then try to move to the right, the cursor comes to the beginning of the next line. This is nice for word processors, but is usually not appropriate for programming. When programming, you are typically working with lines. For most programming languages, a line represents a statement. The next line is the next statement. When you press the right arrow key, you want the cursor to move to the right, even if it is currently at the end of the line. You may be trying to add a line comment, for example. In the CUA emulation, SlickEdit follows the stream model, as that is the most familiar to many users. Some emulations, such as the SlickEdit emulation, use the line model instead. Alternatively, you can control the line behavior using several related configuration settings. Rather than having a single line behavior setting, SlickEdit allows you to change several related behaviors independently. All of the line behavior settings are found in the Redefine Common Keys dialog (Tools Options Redefine Common Keys), shown in Figure 2-7.

26

Chapter 2: Configuration

Figure 2-7

Line Wrapping and White Space


The checkboxes in the lower part of the Redefine Common Keys dialog are mainly concerned with white spaces and tabs. Note that these checkbox settings actually have nothing to do with the common key settings in the upper part of the dialog. Table 2-2 contains descriptions of the checkbox settings, and more notes follow afterward.

Table 2-2
Setting Cursor wrap Description When on, the cursor-left and cursor-right commands wrap when the cursor is at the beginning or end of a line. When off, the cursor commands can take the cursor beyond the end of the line. When on, the cursor stays within the text when moving up and down. When off, the cursor remains in the same column, whether or not the text extends to that column. When on, the cursor moves up and down window lines in soft wrapping mode. When off, the cursor moves up and down buffer lines. See note below.

Up/Down on text

Up/Down within soft wrapped lines Line wrap on text

When on, the cursor can move to column 1 regardless of margins in word wrap mode. When off, the cursor wraps at the left margin in word wrap mode. See note below. When on, the cursor jumps over tab characters in the buffer. When off, the cursor can be moved into tab characters, one space at a time. Typing inside a tab character converts the tab to the appropriate number of spaces. continued

Jump over tab characters

27

Part I: Getting Started with SlickEdit


Table 2-2 (continued)
Setting Pull chars backspace Description When on, in both insert and replace mode, backspace pulls characters to the right of the cursor with the cursor while deleting. When off, in replace mode, characters are not pulled. Spaces are left instead. When on, backspace converts tabs to spaces and deletes only one space. The cursor moves back only one column. When off, backspace deletes entire tab characters, moving the cursor back to the character before the tab. When on, the cursor moves by tab stops in leading spaces on the line. When off, the cursor moves one column at a time.

Hack tabs backspace

Treat leading spaces as tabs

The Up/Down within soft wrapped lines setting applies only in soft wrapping mode. Soft wrapping mode displays long buffer lines as multiple lines in the window, marking a continuation with a little arrow on the right-hand side. Turn on soft wrap globally or per file extension on the Word Wrap tab of the Extension Options dialog (Tools Options File Extension Setup). The Line wrap on text setting applies only in word wrap mode. When word wrap mode is on, SlickEdit wraps text you type to stay within the left and right margin columns. Turn on word wrap per file extension on the Word Wrap tab of the Extension Options dialog. A related setting concerning line wrapping is the Click past end of line checkbox on the General tab of the General Options dialog. This setting permits a mouse click to place the cursor beyond the end of a line with a mouse click. If you turn off Up/Down on text, you would probably also turn on Click past end of line. If you type something beyond the end of a line, the space in between becomes padded with spaces. If you delete the text, the trailing spaces remain. You can remove trailing spaces from a line using removetrailing-spaces (Edit Other Remove Trailing Whitespace). However, if you turn on Strip trailing spaces in the Save tab of the File Options dialog (Tools Options File Options), this is not usually necessary.

Backspace, Delete, and Enter


The Redefine Common Keys dialog contains five common keys and their standard commands in the top part. This part of the dialog is simply a shortcut for binding a limited set of possible commands to each of these five keys. For the Backspace, Delete, and Enter keys, the choices available determine the line behavior. For example, the default command for Delete (in CUA) is linewrap-delete-char. If you press Delete on the end of a line, the following line is joined to it. If you configure the key to the other option, delete-char, then Delete never joins lines. Backspace is similar, with commands linewrap-rubout and rubout. These commands differ when the cursor is on the beginning of the line.

28

Chapter 2: Configuration
For the Enter key, there are three choices: nosplit-insert-line, split-insert-line, and maybesplit-insert-line. When you change the behavior of Enter using the Redefine Common Keys dialog, SlickEdit also changes Ctrl+Enter to the complementary behavior. The behaviors are shown in Table 2-3.

Table 2-3
Command for Enter
nosplit-insert-line

Description Does not split line. A new line is added below the current line. Splits line. In insert mode, splits line. In replace mode, moves cursor to first column of next line.

Command for Ctrl-Enter


split-insert-line

split-insert-line maybe-split-insert-line

nosplit-insert-line nosplit-insert-line

The pair split-insert-line and nosplit-insert-line are both commonly used while programming. Decide which you prefer as your default, and use the other with the Ctrl key. Or use maybe-splitinsert-line if that behavior works for you. All of these commands are integrated with other SlickEdit features. For example, if you are editing a source file with comments, the line splitting and joining in these commands attempt to keep the comment flow intact. Thus if you press Enter to insert a line break in a comment, SlickEdit continues the comment to the next line. If you decide to replace the standard commands with something of your own, you may need to consider whether you will lose some of this functionality. Of course, if you study the Slick-C source for commands such as split-insert-line, you can provide the same functionality in your own commands. Regardless of your settings for common keys for splitting and joining lines, you can also use split-line (WROX: Alt+S) and join-line (WROX: Alt+J) as alternatives. These commands provide more rudimentary splitting and joining, however. They dont preserve comment flow.

Home and End


The Home and End keys also have two behaviors each that can be selected in the Redefine Common Keys dialog. For Home, the choices are begin-line and begin-line-text-toggle. The begin-line command simply takes you to the beginning of the line, regardless of any indentation. The begin-linetext-toggle command toggles you between the first non-blank character and the beginning of the line. This can be handy for heavily indented lines. Similarly, the End key can have either end-line or end-line-text-toggle. The end-line command takes you to the end of the line, including any white space. The end-line-text-toggle command toggles between the last non-blank character and the end of the line. Again, this command would be useful if you had a lot of lines with trailing white space. This isnt as common as having indented lines.

29

Part I: Getting Started with SlickEdit

Managing Configurations
When you install SlickEdit, files are placed in two directories: The program installation directory. The user configuration directory.

The program installation directory contains the static files that dont change once they are installed. These include executable files, libraries, help system, templates, and macro source code. The default location for the program installation directory on Windows is C:\Program Files\SlickEdit 2007\. On UNIX, it is a global directory such as /opt/slickedit/. The user configuration directory contains all configuration data and other user data. The configuration data are initialized to defaults, and then may change as you use SlickEdit. We cover the content and management of the configuration directory in this section.

Configuration Directory
SlickEdit stores all your personal configuration data in the user configuration directory. By default, this directory is located under your home directory. SlickEdit creates a separate configuration directory for each update release. Thus for SlickEdit 12.0.2 on Windows, the default location for the user configuration directory is My Documents\My SlickEdit Config\12.0.2. On UNIX, the configuration directories are placed under $HOME/.slickedit/. If SlickEdit cannot find the default configuration directory when it starts, it tries to find a configuration directory for a previous version. If it finds one, SlickEdit migrates the configuration settings from the previous version to the current version. The configuration directory contains several files. The most important file is the SlickEdit state file, stored in vslick.sta on Windows and vslick.stu on UNIX. This is a binary state file that contains many of SlickEdits configuration data. It includes most of the user settings and all compiled macro code. An important thing to realize about the state file is that it is normally only saved when you exit from SlickEdit. This means that if you change your configuration, and then the editor gets terminated abnormally (e.g., because of a power outage), your changes are not saved. You can force SlickEdit to save the state file during a session using the save-config command. If you have made configuration changes that you do not wish to save, you can discard them by exiting SlickEdit using the safe-exit command. There are several other configuration files and subdirectories too. Some of these are listed in Table 2-4.

Reverting to the Default Configuration


Sometimes you may wish to revert SlickEdit to the default configuration. To do this, delete the contents of your configuration directory before starting SlickEdit. If SlickEdit finds an empty configuration directory, it initializes it with the default configuration.

30

Chapter 2: Configuration
Table 2-4
File/Directory
tagfiles/ templates/ vsdelta/ alias.slk *.als filepos.slk uscheme.ini user.cpp vrestore.slk vusrdefs.e (UNIX: vunxdefs.e)

Description Global runtime library tag files (see Chapter 5). User-defined code templates (see Chapter 11). File backup history (see Chapter 13). Global aliases (see Chapter 11). Extension-specific aliases (see Chapter 11). Cursor positions in files opened. User-defined color schemes. User-defined C/C++ preprocessing configuration settings. GUI state, command history, file histories, etc. Slick-C representation of key bindings, user settings (see Chapter 17). Toolbar customizations.

vusrobjs.e

There are several other files in the configuration directory. Refer to the online Help for a more complete table. If you delete the directory itself, instead of just the contents, then SlickEdit will look for configuration directories for previous versions, which is probably not what you want. You can back up your entire SlickEdit configuration by making a copy of the configuration directory. If you encounter a problem with SlickEdit, it could be due to a corrupt configuration. You can try restoring a backup configuration, or reverting to the default configuration. We cover advanced ways to restore your configuration to a known state in Chapter 17.

Working with a Different Configuration


Occasionally you may wish to run SlickEdit using a different configuration directory from the default. Some examples of times you might want to do this are: You want to place your configuration in a different location. For example, your home directory may be on a network drive, and you want to put your SlickEdit configuration on the local drive. You want to try something with a default configuration. You want to experiment with different settings.

31

Part I: Getting Started with SlickEdit


To use a non-default configuration directory location, you can use one of these options: Set the environment variable VSLICKCONFIG to point to your configuration directory. Use the sc option when invoking SlickEdit to specify the configuration directory.

These options are documented in the online Help. Both of these options override the version migration mechanism described above. If you do override the configuration directory location, be careful to remember that fact. For example, if you need to revert to the default configuration, or you receive instructions from SlickEdit Support, its important that you perform the actions in the correct directory. Another way to use different configurations without changing where SlickEdit looks for the configuration directory is to keep different copies of the directory and contents with different names, and rename the one you wish to use to the default name. For example, suppose in your My SlickEdit Config folder you have two backup copies of the 12.0.2 configuration directory: 12.0.2_safe and 12.0.2_ experimental. By copying or renaming one of these to the default name, 12.0.2, you make it the active configuration. To switch to the other, stop SlickEdit, rename the directories as desired, and restart.

Summar y
We covered a selection of the most common configuration settings in this chapter. There are many, many other settings. Some of these settings are quite obscure and do not affect most users. You are referred to the reference information in the online Help for those. For example, we dont discuss network or proxy settings. Other settings are rather obvious and do not need to be covered here. For example, you should not have much trouble figuring out how to change colors if you decide you want to. Many other configuration settings apply to specific topics that are covered elsewhere in this book, and they are covered together with those topics. In the next chapter, we take a look at using and configuring the different windows of the interface.

32

Managing Windows
When I started using the ancient ancestor of SlickEdit, the E editor on DOS in the 1980s, screens had only 25 lines and 80 columns. The editor had a command line, a status line, and a help line. I could see 22 lines of my file, and those lines were not particularly long. Figure 3-1 shows this old editor.

Figure 3-1

These days we have GUI environments and much bigger screens. Many programmers now use a monitor at a resolution of 1600 1200 or more. With that kind of screen, in full screen mode its easy to get 60 or 70 lines on the screen, with a couple of hundred columns. (And, if you dont mind a 6-point font, you can get a lot more.) This is usually enough space, because most peoples brains cant cope with more lines of code than that anyway. The thing is, our desktops and tools are a lot more sophisticated now, and they want to give us a lot more information, and give us more different ways of doing things. Some Office-style applications start up with three or four rows of toolbars. IDEs usually have extra windows on the sides and bottom, for different types of navigation. SlickEdit also has a lot of toolbars and tool windows.

Part I: Getting Started with SlickEdit


If you use them all, you can easily get back to a situation where you can see only 20 lines or less of your code. The trick is to manage the toolbars, tool windows, and your editing area to maximize your productivity. SlickEdit allows several options for how you arrange its tools. In this chapter, we take a look at those options and recommend some strategies for using the features most effectively.

Windows and Buffers


When you look at the SlickEdit interface with the Edit window maximized, its easy to think that the editor has a single editing window, into which it places the buffer you are editing. This is not really true. The relationship between windows and buffers is controlled by the One file per window setting, found on the General tab of the General Options dialog (Tools Options General). The default is One file per window turned on, which is usually the best setting. With this setting, there is actually a separate window for each buffer. You can move among buffers effectively using either next-window (Ctrl+Tab) or next-buffer (Ctrl+N). We discuss commands for moving between buffers in more detail in Chapter 6. With the One file per window setting turned off, you can associate more than one buffer with a window. With this setting, next-window moves between windows, and next-buffer moves between buffers associated with the window. This is mostly useful when using split windows.

Split Windows
In the default configuration, SlickEdit displays windows cascaded. Usually for programming, its more effective to maximize the Edit window. You can change the default behavior by checking the Maximize first window option on the General tab in the General Options dialog (Tools Options General). Often while programming, you need to look at two files at once. Or, you may want to look at two different parts of the same file at once. Table 3-1 shows some commands you can use for working with split windows.

Table 3-1
Command
hsplit-window

Key Ctrl+H (Window Split Horizontally) (Window Split Vertically) (Window One Window)

Description Split window horizontally

vsplit-window one-window

Split window vertically Restore to single window

34

Chapter 3: Managing Windows


When using split windows, its best to have One file per window turned off. Then you can use next-window/prev-window (Ctrl+Tab/Ctrl+Shift+Tab) to move between the windows, and next-buffer/prev-buffer (Ctrl+N/Ctrl+P) to move between buffers in a window.

Full Screen
Regardless of your monitor size and resolution, there are times when you want to see as much of your buffer as possible, and nothing else. An example of this is when editing a large, badly formatted HTML file. Another example is when you are working with many columns of data, and splitting the lines is not possible because it would prevent block editing. In these cases, you may find full screen mode handy. Use the fullscreen command (View Full screen) to toggle full screen mode. When in full screen mode, SlickEdit displays the menu bar, the left margin, the scroll bars (if turned on), and the command line and status area. Nothing else is shown, and you have the maximum amount of your buffer visible.

Toolbars
I have a rather harsh view of toolbars. I think they are basically invented for and useful only for marketing purposes. Everybody seems to have one these days, whether useful or not. SlickEdits Standard toolbar has many frequently used tools. The tools are used so frequently that you will be working very slowly if you use the toolbar to invoke them. These tools include file load and save commands, clipboard and undo commands, and search-and-replace commands. You need to know the keyboard shortcuts for all of these commands to use SlickEdit effectively. There is no reason for most users to use the Standard toolbar. You can save some space by removing it and also the Current Context toolbar. Some of the more specialized toolbars are handy though, especially if they are for features that you dont use frequently. I dont use the debugger very often, so when I do use it, I use the toolbar for a lot of its commands. If I used the debugger more often, I would learn the keyboard commands. As a general rule, you should avoid using toolbars when using SlickEdit. Learn and use the keyboard bindings for commands. If you like toolbars regardless, you can adjust the size and other options for the icons on the Options tab of the Toolbar Customization dialog (View Toolbars Customize).

Tool Windows
Tool windows are different from toolbars. Tool windows provide you with different kinds of information, and different functionality, from that available in the main editing area. Depending on the work you are doing, you will use some tool windows frequently and others not at all.

35

Part I: Getting Started with SlickEdit


Even so, for most of the tool windows, you wont want to have them visible all the time they simply take up too much room. There are more than a dozen of them, thus its impossible to display them all anyway. The best strategy is to arrange the tool windows so that you can access the ones you need quickly, and dismiss them just as quickly. With the default configuration this is not possible, since you need to use the mouse to activate most of the tool windows and also to hide them. Fortunately, tool window features make it pretty easy to set things up to be productive with the keyboard. The WROX emulation supplied with this book contains one approach to managing the tool windows with the keyboard. Before we go into details of the key bindings, lets take a bit of time to understand some things about tool windows.

Tool Window Arrangement


Tool windows can be either floating or docked. Floating tool windows can be placed anywhere on the screen. They do not have to be placed within the SlickEdit window. In fact, its often better to place them outside it, so that they do not obstruct the view of the buffer. If you place a floating tool window outside the main SlickEdit window, you can leave it visible all the time if you choose. You can close a floating tool window by clicking the X in its top-right corner. You can also press Escape to close some floating tool windows. For most floating tool windows, though, pressing Escape does not close the window but instead restores the focus to the main SlickEdit window. Docked tool windows are stuck to the inside of one edge of the main SlickEdit window: either the left, top, right, or bottom edge. Docked tool windows belong to docking groups. Only one tool window in a docking group can be visible at a time. The others show only their tabs in the docking group. You can switch among tool windows in a docking group by clicking tabs, but our goal is to switch using the keyboard, not the mouse. Docking groups can have auto-hide enabled for them. If auto-hide is not enabled, the docking group remains visible all the time, taking up a certain amount of screen space. If auto-hide is enabled, the docking group remains visible only while it has the focus or the mouse is over it. When the focus is moved away and the mouse is not over the docking group, it disappears. Auto-hide is indicated by a pin icon on the top right of the docking group, next to the Close icon. If the pin is upright, auto-hide is disabled. If the pin is on its side, auto-hide is enabled. Figure 3-2 shows some arrangements of tool windows. The Find Symbol tool window is floating and appears over everything else. It could be moved outside of the SlickEdit window if desired. The lefthand docked group contains the Projects, Defs, Class, Symbols, and Files tool windows. The group has auto-hide enabled and is, in fact, hidden so that only the tabs are visible. The bottom docked group contains the Search Results, Preview, Build, Output, and References tool windows. The group has auto-hide enabled, as indicated by the pin on its side in the upper-right. The group is visible because the Build tool window, displaying a directory listing, currently has the focus. The right-hand docked group contains the Bookmarks and Backup History tool windows. The group has auto-hide disabled, indicated by the upright pin in the upper-right corner. The Bookmarks tool window is visible. The Backup History tool window is shown only by a tab, which is, in fact, covered by the Build tool window. Auto-hidden tool windows appear over non-auto-hidden tool windows when they are showing. When tool windows are not auto-hidden, SlickEdit arranges them so that they dont overlap.

36

Chapter 3: Managing Windows

Figure 3-2

You change a tool window to floating or docked mode by right-clicking on its title bar. To change a floating tool to docked, and to add it to a docking group, follow these steps:

1. 2. 3. 4.

Ensure that the docking group has auto-hide turned off and is visible. Right-click on the floating tool windows title bar. SlickEdit displays its title context menu. If the window is not already dockable, click Dockable to make it dockable. Drag the window to dock it in the desired docking group. Drag the mouse pointer to the title bar of the desired docking group. When the mouse pointer is in the title bar, the docking group pane is selected with a black rectangle. This is shown in Figure 3-3, where a tool window is being docked to a group already containing the Projects tool window.

Figure 3-3

37

Part I: Getting Started with SlickEdit


5. 6.
Drop the tool window. It now joins the docking group. Enable auto-hide on the docking group, if desired.

You can rearrange the order of tabs in a docking group by dragging them. To change a docked tool window to floating, follow these steps:

1. 2. 3. 4. 5. 6. 7.

Ensure that the docking group has auto-hide turned off and is visible. Select the tool window you wish to make floating. Right-click on the tool windows title bar. SlickEdit displays its title context menu. Click Floating to make the tool window floating. It detaches from the docking group. Right-click on the tool windows title bar. SlickEdit displays its title context menu again. Click Dockable to make the tool window not dockable. Now, when you drag the window around to position it, SlickEdit will not accidentally dock it. Drag the tool window to the desired location, and resize it if necessary.

Whats the best arrangement for tool windows? It depends on you. If you have a large screen and dont mind SlickEdit putting its tool windows all over it, you may find floating tool windows convenient. They can be shaped more flexibly than docked tool windows. If you prefer to keep all SlickEdits tool windows within the main editor window, you will prefer docked tool windows. When docked, some tool windows work better with a horizontal layout, and some work better vertically. For example, the Build tool window works best docked at the bottom of the screen, as in the default configuration. Some tool windows can adapt themselves to either horizontal or vertical orientation. For example, the Find Symbols tool window moves its options panel to the right-hand side of the tool window when it is docked horizontally, and to the bottom if it is in a vertical arrangement. When choosing docking groups for docked tool windows, consider which combinations of tool windows you might like to have visible at the same time. Some tool windows, such as Preview, are constantly updated and can be useful while working with your code. Others are used for specific tasks and are best closed or hidden when not being used.

Activating Tool Windows with the Keyboard


Make sure that you have loaded the WROX emulation, described in Chapter 2. The WROX emulation defines keyboard sequences for activating each of the tool windows, listed in Table 3-2. The keyboard sequences all begin with Alt+T, for tool window, and are followed by a key that is supposed to be a mnemonic for the specific tool window. Many of the tool windows start with the same letter, thus some of the mnemonics are less natural than others. If you have a preferred set of tool windows you use, you can easily customize the emulation to personalize your mnemonics. Most of the tool windows dont have standard keyboard bindings in SlickEdit, but some of them can also be reached by other means using the keyboard. For example, activate-files-files is the same as list-buffers, which is bound to Ctrl+Shift+B. Of course, all of them can be reached via View Toolbars, but thats a little slow for frequent use, particularly since there are no mnemonics for the tool windows in the cascaded menu.

38

Chapter 3: Managing Windows


Table 3-2
Command
activate-bookmarks activate-build activate-call-stack activate-tbclass activate-defs activate-deltasave activate-files-files activate-files-project activate-files-workspace activate-find-symbol activate-ftp activate-open activate-output activate-preview activate-projects activate-references activate-regex-evaluator activate-search activate-symbols-browser

Key Alt+T, K Alt+T, B Alt+T, A Alt+T, C Alt+T, D Alt+T, H Alt+T, L Alt+T, P Alt+T, W Alt+T, F Alt+T, T Alt+T, O Alt+T, U Alt+T, V Alt+T, J Alt+T, R Alt+T, X Alt+T, S Alt+T, Y

Tool Window Bookmarks Build Slick-C Call Stack Class Defs Backup History Files: Open Files tab Files: Project Files tab Files: Workspace Files tab Find Symbol FTP Open Output Preview Projects References Regular Expression Evaluator Search Results Symbols

With this configuration in place, you can use the Alt+T keyboard sequence to activate any tool window, then Escape to dismiss it or move the focus back to the buffer. In this way, you can maximize your screen space and access any tool window functionality with a couple of key strokes. An alternative to this scheme is to use keyboard bindings to toggle tool windows, rather than only to activate them. For most of the activate-xyz commands shown in Table 3-2, there are corresponding toggle-xyz commands that toggle the tool windows. You can find all the tool window commands in the supplied Slick-C macro source, in the tbcmds.e file. By consulting that file, you can find out how

39

Part I: Getting Started with SlickEdit


the tool windows are managed in detail and possibly design your own scheme for managing and arranging them. If you want to keep a tool window visible for an extended period, while you work on a particular task, you can turn auto-hide off for its group. Turn auto-hide back on afterward to get better screen utilization.

Tool Window Animation


Another thing you may or may not like about tool windows in docked mode is the way they slide across the screen when being activated or hidden. You can adjust the rate at which they move, or disable the animation altogether, in the Options tab of the Toolbar Customization dialog (View Toolbars Customize). I recommend turning off the animation, since it is distracting and slows things down.

Restoring the Defaults


You can restore your toolbars and tool windows to the shipped settings by invoking the tbResetAll command on the command line.

Summar y
The SlickEdit user interface is powerful and flexible. Learn which tool windows are useful for your work, and make sure they are quickly available. You can use the keyboard scheme presented in this chapter, or adapt it for your own needs. In the next chapter, we look at workspaces and projects, which enable many of SlickEdits advanced code editing features.

40

Part II: Using SlickEdit


Chapter 4: Workspaces and Projects Chapter 5: Context Tagging Chapter 6: Navigation Chapter 7: Search and Replace Chapter 8: Editing Text Chapter 9: Editing Code Chapter 10: Editing Data Chapter 11: Aliases and File Templates Chapter 12: Document Types Chapter 13: Comparing and Merging Chapter 14: Version Control

Wor kspaces and Projects


With most programming IDEs, you organize your work into projects. In some IDEs, you cannot open a file unless it is part of your project. With SlickEdit, its easy to open any file on your system, but all the same its usually best to organize your work to get the most effective use of the editors features. SlickEdit organizes your work using two concepts: workspaces and projects. Workspaces and projects are important for two main reasons: They allow you to organize, manage, and tag the files in your project. They provide structure around tasks such as building, running, and debugging your project.

Tagging refers to SlickEdits ability to index the symbols in your code for navigation and smart assistance features. We go into SlickEdits tagging features in more detail in Chapter 5. To organize your work using SlickEdits workspaces and projects, you create a workspace. In the workspace you add one or more projects. SlickEdit stores the workspace details in a .vpw file, and the project details in one or more .vpj files. SlickEdit also creates a tag file (.vtg) to tag your project files and a .vpwhist file that contains state information about your workspace. A workspace contains a set of projects and retains the state of an editing session. Opening a workspace returns you to the same state you were in when you last worked on this workspace, including the set of open files. Files are added to projects, and projects are added to workspaces, thus you cannot directly add a file to a workspace. You can open files that do not belong to any of the workspaces projects, and they will be available for editing in the next session if not closed. A project can be just a set of files, but if you are using the SlickEdit build system, then a project corresponds to a build target, something that gets built. For Java, its common to have a single

Part II: Using SlickEdit


project. For C/C++, you would have a project for each library, DLL or SO, that is built and one for each executable. Even if you dont use the SlickEdit build system, partitioning files into projects like this is useful so that you can see the structure of your projects and do things like restricting searches to the current project. Projects can be shared between workspaces. Once a project is defined, you can add it to a different workspace. The exact same project is shared; it is not a copy. This is useful if you have internal libraries that might be used and edited in multiple programs. SlickEdit does not require that the files in a workspace be under the workspace directory. They can be located anywhere on the local machine or on a network, although local is always best. Some prefer that structure, creating a single root directory that contains subdirectories for each project, which contains a source tree. However, you can create a workspace directory that has no subdirectory and stores projects and files in other directories. Even if your source files are remote, it is very important to have your workspace and project files stored locally. SlickEdit tags all of the files in a workspace (i.e., all of the files in the projects that the workspace contains) and creates the workspace tag file. It does not have project-specific tag files. For code that is used but not edited, it is generally best not to add it to the project. Instead, tag the library, and add the tag file to your environment. Because of the way in which Context Tagging works, its best to restrict your files to those that will be edited. When you create a project, it is critical to get the project type correct. It is impossible to change some project types into others. For example, if you create a Generic C/C++ project, you will never be able to configure it through the GUI to work properly with GNU C/C++. You need to start with that project type to be successful. Projects can be dependent on one another, creating a build dependency. If you have multiple projects, certain operations work on the Active Project. It is shown in bold in the Project tool window. You can change the Active Project by right-clicking on it or using Project Set Active Project. SlickEdit cannot create Microsoft Visual Studio project types. It can open them and change the set of defined files, but you have to create the solution or project in Visual Studio before opening it in SlickEdit. You will also have to make most of the changes related to build settings in Visual Studio. In this chapter, you will see how to create workspaces and projects. Well take a look at how to set up projects for different build targets in your work, and how to automate building and testing your project in SlickEdit. Well look at several examples using programming languages with compilers C/C++ and Java and also an example of using SlickEdit projects with an interpreted language, Ruby. You can find the code for the sample projects on the accompanying CD-ROM. For compiled languages such as C++ and Java, SlickEdit provides dialogs with a large number of compiler and linker options. Most of the options you can use with the command-line tools are available through the SlickEdit GUI. However, we dont cover the compiler options in detail here, or even all the compilers. You can find better information about using a compiler in that compilers own documentation. Instead, we focus on using SlickEdit with programming language compilers and interpreters in general, and how to create an effective and productive development workflow using SlickEdit.

44

Chapter 4: Workspaces and Projects

How to Organize Your F iles


When you create a workspace and a project, SlickEdit creates these files:
project_name.vpw the workspace definition. project_name.vpj the project definition. project_name.vtg the tag file. project_name.vpwhist the workspace state.

The workspace definition contains a list of projects in the workspace, and other global parameters. The project definition defines all the files in a project, and all the tools and configuration targets for the project. These two files could be checked into version control along with the rest of your project source, if you want to share project definitions and tool configuration with other team members. The tag file contains tags for your projects. The tag file is derived from data in your source files and should not be checked into version control. It should be considered a transient file, like compilation outputs. The workspace state file saves the state so that SlickEdit can restore it when you reopen the workspace. For example, it contains the list of buffers open and the file history. The workspace state file should not be checked into version control, as it is transient and specific to each developer. When you add files to a project, you have three choices: Add files. Add tree. Add wildcard.

Add tree is really just an alternative form of add files. They both result in the same information in the project file: Each file is explicitly listed in the project. Add wildcard is different. It stores the wildcard pattern in the project, rather than the specific files. Each of these approaches has its advantages and disadvantages. Storing each specific file gives more precision and can give better performance. Storing wildcards gives more convenience. Which you choose depends on the nature of your project and what other tools you and your other developers are using. If you are all using SlickEdit, and no other tool to create files in your project, you may find that storing specific files in your project works best. If a team member adds a file and commits his project definition file, other team members will pick up the changes next time they update from the repository. On the other hand, if you often have new files added to the project from outside of SlickEdit, you may find that it is too labor-intensive and error-prone to keep the SlickEdit project file up-to-date with the correct project source files. In this case, you may find that wildcards are better. Generally speaking, wildcards are more convenient than specific files. Once you have them set up correctly, you can pretty much forget about them, and SlickEdit will always be up-to-date with the source files in your project.

45

Part II: Using SlickEdit


Some people have experienced performance problems with wildcards with large projects. If you run into performance problems, you should try both methods to see if one is faster.

The Example
For our example projects, well create a simple console application that uses only a few files. Well see how to: Organize the source files. Compile or build the application. Run automated unit tests, and then review the results. Run the application itself.

Well see how SlickEdit integrates with popular build tools such as Make and Ant. Well also see how SlickEdit can interpret output from compilers and tests to help you navigate to errors. Our simple console application solves the n-queens problem. This is a nice programming puzzle where you have to find an arrangement of n queens on an n n chessboard so that none of the queens attacks any other. The smallest board that its possible to do this on is a 4 4 board. A 4 4 solution is shown in Figure 4-1.

Figure 4-1

To show how to set up SlickEdit projects for different languages and compilers, well work through the example in three different languages: GNU C/C++. Java. Ruby.

The source code for each project is included on the accompanying CD-ROM, under Author/Chapter04/
projects.

46

Chapter 4: Workspaces and Projects

Creating a GNU C/C++ Project


To use SlickEdit with a GNU C/C++ project, you need to have the GNU C/C++ compiler and related tools installed already. On GNU/Linux, you should have this installed by default on your development machine. On Windows, the easiest way to install GNU C/C++ is to install CygWin: http:// www.cygwin.com. Well start with a very simple GNU C++ project. Suppose we already have some files for this project:
board.h The header for the Board class. board.cpp The definition of the Board class. queens.cpp The main() function.

On my system these files are in the directory Z:\ProfessionalSlickEdit\projects\gnu_queens. The code for this project is included on the accompanying CD-ROM. The listing for board.h follows:
#include <vector> class Board { public: Board(int size); int size(); void place(int row, int col); int unplace(int row); bool is_ok(int row, int col); bool solve(); int col(int row); private: int size_; std::vector<int> pos_; std::vector<bool> col_; std::vector<bool> diag1_; std::vector<bool> diag2_; };

The listing for board.cpp is below:


#include board.h Board::Board(int size) : size_(size), pos_(size, -1), col_(size, false), diag1_(2*size+1, false), diag2_(2*size+1, false) { } int Board::size() { return size_; }

47

Part II: Using SlickEdit


void Board::place(int row, int col) { pos_[row] = col; col_[col] = true; diag1_[col-row+size_] = true; diag2_[col+row] = true; } int Board::unplace(int row) { int col = pos_[row]; pos_[row] = -1; col_[col] = false; diag1_[col-row+size_] = false; diag2_[col+row] = false; return col; } bool Board::is_ok(int row, int col) { return !(col_[col] || diag1_[col-row+size_] || diag2_[col+row]); } bool Board::solve() { int row = 0; int col = 0; while (row >= 0 && row < size_) { while (col < size_ && !is_ok(row, col)) { col++; } if (col < size_) { place(row, col); row++; col = 0; } else { row--; if (row >= 0) { col = unplace(row) + 1; } } } return row == size_; } int Board::col(int row) { return pos_[row]; }

Finally, the driver program is in queens.cpp:


#include #include #include #include <ctime> <iostream> <string> board.h

int main (int argc, char *argv[]) {

48

Chapter 4: Workspaces and Projects


if (argc < 2) { std::cerr << I need a number. << std::endl; exit(-1); } int size = atoi(argv[1]); Board b(size); time_t start = time(0); if (b.solve()) { time_t elapsed = time(0) - start; for (int i = 0; i < size; i++) { std::cout << std::string(b.col(i), ) << * << std::endl; } std::cout << elapsed << seconds. << std::endl; } return(0); }

The driver program creates a Board of the required size, asks the Board to solve itself, and then outputs the Board and the elapsed time to solve.

Creating the Project


To create a GNU C/C++ project for these files, follow these steps:

1.

Open the New Project dialog (Project New). The dialog is shown in Figure 4-2.

Figure 4-2

SlickEdit supports several project types. Some of the project types provide wizards to set up the project configuration. Some project types provide template files. You can also create your own custom project types with your own configurations. We look at custom project types later in the chapter. For now well continue with the GNU C/C++ project.

49

Part II: Using SlickEdit


2. 3. 4.
Select project type GNU C/C++ Wizard. Enter gnu_queens for the Project name. Enter the Location for SlickEdit to place its project files. Its often simplest to place the SlickEdit project files in the top directory of your source tree. However, you can place them wherever you wish. The most important thing is that they are on a local drive, because SlickEdit accesses them frequently. On my system, the source files are in Z:\ProfessionalSlickEdit\projects\ gnu_queens; thus I will put this as the location for the SlickEdit project files too. Enter queens for the Executable name. This is the name given to the output executable produced by the build process. Click OK. SlickEdit opens the first page of the Create GNU C/C++ Project wizard, shown in Figure 4-3. For the queens application, the source code is C++, and the output is a console executable; thus the default settings are correct.

5. 6.

Figure 4-3

7.

Click Next. SlickEdit displays the second page of the wizard, shown in Figure 4-4. Here we can request that SlickEdit add a file containing one of two very simple main() templates. For the queens project, we have a main() function already in queens.cpp; thus well leave the An empty project option selected.

Figure 4-4

50

Chapter 4: Workspaces and Projects


8.
Click Next. SlickEdit displays the third page of the wizard, shown in Figure 4-5. Here we can choose between three options for the build system. For the queens project, there are only a couple of source files, thus the first option, Build without a makefile, will be fine.

Figure 4-5

9. 10.

Click Finish. SlickEdit completes the wizard and displays the New Project Information dialog, summarizing our choices. Click OK to dismiss the dialog. SlickEdit opens the Project Properties dialog, as shown in Figure 4-6. The Project Properties dialog is where you configure most of the important options for your project. You can open this dialog at any time via Project Project Properties. For the purposes of the queens application, all well do for now is add the source files to the project.

Figure 4-6

51

Part II: Using SlickEdit


11. 12. 13.
Click Add Files. SlickEdit displays the Add Source Files dialog, where you can select one or more source files to add to the project. As mentioned above, for a larger project you would use Add Tree or Add Wildcard. Select the three files board.cpp, board.h, and queens.cpp, and click OK. SlickEdit shows the three Project files. Were done setting up the project. Click OK to close the Project Properties dialog.

We have now concluded the basic steps for setting up a project. We are now ready to compile, execute, or debug it. Some compiler projects may require a little more configuration to get everything working.

Building the Project


To build the project, invoke project-build (Ctrl+M). SlickEdit invokes the configured build process and displays output in the Build tool window. If there is an error, the details are shown in the Build tool window. An example of a build with compile errors is shown in Figure 4-7.

Figure 4-7

If you hide the Build tool window, SlickEdit shows the message for the current compiler error in the message area, as shown in Figure 4-8.

52

Chapter 4: Workspaces and Projects

Figure 4-8

You can navigate among errors in the buffer using prev-error (Ctrl+Shift+Up) and next-error (Ctrl+Shift+Down). When the last error in one buffer is reached, next-error takes you to the next buffer containing errors.

Executing the Project


You can execute the project target with project-execute (Ctrl+F5). For the queens project, the program requires a number as a command-line argument. On the Tools tab of the Project Properties dialog, select the Execute tool, and click Options. SlickEdit displays the GNU C Options dialog. On the Run/Debug tab, you can provide program arguments. By the way, dont try to run the queens program with large numbers! It is a hard problem, and even on a fast computer it takes a long time to solve. A 30 30 board takes nearly a minute to run on my machine, and boards not much larger take much longer. There are many other options available on the different tabs for the GNU C compilers. Most of these options are translated directly into compiler or linker options for the command-line GNU tools that SlickEdit invokes.

53

Part II: Using SlickEdit

Adding Unit Tests


Unit tests are an effective way to detect bugs in your code. They are becoming increasingly popular, and there are frameworks for unit testing for most major programming languages today. For Java, the JUnit framework is a de facto standard, although other alternatives exist. Well see SlickEdits support for JUnit shortly. For C++, there is no standard testing framework, but many are available. In this section, well show an example of how to get SlickEdit to work with CxxTest (http://cxxtest.sourceforge.net/). Most of the time, you would develop unit tests before or while you develop your main code. But because we are learning mostly about SlickEdit in this book, rather than about unit testing, well cover unit testing now, even though our program is already working. (The tests would be useful if we changed the program later.) To test with CxxTest, we follow these steps:

1. 2. 3.

Write CxxTest test suites. Generate a CxxTest test runner to run the test suites. Execute the test runner to run the tests.

Writing the Test Suite


CxxTest test suites are simply classes that contain tests. The simplest way to organize tests for your own classes is to create a test suite for each class under test. An example of a CxxTest suite for our Board class is in board_tests.h:
#include board.h #include <cxxtest/TestSuite.h> class BoardTests : public CxxTest::TestSuite { public: void test_create(void) { Board b1(1); Board b4(4); Board b20(20); TS_ASSERT(true); } void test_size(void) { Board b1(1); TS_ASSERT_EQUALS(1, b1.size()); Board b4(4); TS_ASSERT_EQUALS(4, b4.size()); Board b20(20); TS_ASSERT_EQUALS(20, b20.size()); } void test_place(void) { Board b(4); TS_ASSERT_EQUALS(-1, b.col(0)); TS_ASSERT_EQUALS(-1, b.col(1)); TS_ASSERT_EQUALS(-1, b.col(2));

54

Chapter 4: Workspaces and Projects


TS_ASSERT_EQUALS(-1, b.col(3)); b.place(0, 1); b.place(1, 3); b.place(2, 0); b.place(3, 2); TS_ASSERT_EQUALS(1, b.col(0)); TS_ASSERT_EQUALS(3, b.col(1)); TS_ASSERT_EQUALS(0, b.col(2)); TS_ASSERT_EQUALS(2, b.col(3)); } void test_unplace(void) { Board b(4); b.place(0, 1); TS_ASSERT(!b.is_ok(1, 1)); TS_ASSERT(!b.is_ok(0, 1)); TS_ASSERT(!b.is_ok(2, 3)); b.unplace(0); TS_ASSERT(b.is_ok(1, 1)); TS_ASSERT(b.is_ok(0, 1)); TS_ASSERT(b.is_ok(2, 3)); b.place(1, 3); b.place(2, 0); b.place(3, 2); TS_ASSERT_EQUALS(3, b.unplace(1)); TS_ASSERT_EQUALS(-1, b.col(1)); TS_ASSERT_EQUALS(2, b.unplace(3)); TS_ASSERT_EQUALS(-1, b.col(3)); } void test_is_ok(void) { Board b(4); TS_ASSERT( b.is_ok(0, TS_ASSERT( b.is_ok(0, TS_ASSERT( b.is_ok(0, TS_ASSERT( b.is_ok(0, TS_ASSERT( b.is_ok(1, TS_ASSERT( b.is_ok(1, TS_ASSERT( b.is_ok(1, TS_ASSERT( b.is_ok(1, TS_ASSERT( b.is_ok(2, TS_ASSERT( b.is_ok(2, TS_ASSERT( b.is_ok(2, TS_ASSERT( b.is_ok(2, TS_ASSERT( b.is_ok(3, TS_ASSERT( b.is_ok(3, TS_ASSERT( b.is_ok(3, TS_ASSERT( b.is_ok(3, b.place(0, 1); TS_ASSERT(!b.is_ok(1, TS_ASSERT(!b.is_ok(1, TS_ASSERT(!b.is_ok(1, TS_ASSERT( b.is_ok(1, TS_ASSERT( b.is_ok(2,

0)); 1)); 2)); 3)); 0)); 1)); 2)); 3)); 0)); 1)); 2)); 3)); 0)); 1)); 2)); 3));

0)); 1)); 2)); 3)); 0));

55

Part II: Using SlickEdit


TS_ASSERT(!b.is_ok(2, TS_ASSERT( b.is_ok(2, TS_ASSERT(!b.is_ok(2, TS_ASSERT( b.is_ok(3, TS_ASSERT(!b.is_ok(3, TS_ASSERT( b.is_ok(3, TS_ASSERT( b.is_ok(3, b.place(1, 3); TS_ASSERT( b.is_ok(2, TS_ASSERT(!b.is_ok(2, TS_ASSERT(!b.is_ok(2, TS_ASSERT(!b.is_ok(2, TS_ASSERT( b.is_ok(3, TS_ASSERT(!b.is_ok(3, TS_ASSERT( b.is_ok(3, TS_ASSERT(!b.is_ok(3, b.place(2, 0); TS_ASSERT(!b.is_ok(3, TS_ASSERT(!b.is_ok(3, TS_ASSERT( b.is_ok(3, TS_ASSERT(!b.is_ok(3, } void test_solve_false(void) { Board b(3); TS_ASSERT(!b.solve()); } void test_solve_true(void) { Board b(4); TS_ASSERT(b.solve()); TS_ASSERT_EQUALS(1, b.col(0)); TS_ASSERT_EQUALS(3, b.col(1)); TS_ASSERT_EQUALS(0, b.col(2)); TS_ASSERT_EQUALS(2, b.col(3)); } }; 1)); 2)); 3)); 0)); 1)); 2)); 3));

0)); 1)); 2)); 3)); 0)); 1)); 2)); 3));

0)); 1)); 2)); 3));

Refer to the online user guide at http://cxxtest.sourceforge.net/guide.html to find out more about writing tests with CxxTest. We wont make board_tests.h part of our main project. Instead, well create a second project specifically for building and running the unit tests. This project will include the board.h and board.cpp files defining our Board class, as well as the board_tests.h file containing the test suite. It will also include the test runner, which well create below. It wont include the queens.cpp file with the main() function of our application. Follow these steps to set up a new project:

1. 56

Open the New Project dialog (Project New).

Chapter 4: Workspaces and Projects


2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Select the GNU C/C++ wizard again. Enter tests for the Name of the second project Specify the same location as the gnu_queens project. Enter test_runner for the Name of the executable. Select the option to add this project to the current workspace. Click OK. SlickEdit displays the first page of the Create GNU C/C++ Project wizard. Again, the default settings are appropriate for a console C++ application. Click Next. SlickEdit shows the second page of the wizard. Leave An empty project selected, and click Next. SlickEdit shows the last page of the wizard. Again, well let SlickEdit deal with the dependencies for this example project. Leave Build without a makefile selected, and click Finish. SlickEdit shows the New Project Information dialog. Click OK to dismiss the dialog. SlickEdit shows the Project Properties dialog. Click Add Files. Select the three files board.cpp, board.h, and board_tests.cpp, and click OK. SlickEdit shows the three Project files. Youre done setting up the project. Click OK to close the Project Properties dialog.

You now have a project for building and running the tests. You can switch between the tests and the main application using Project Set Active Project. You cant actually build or run the tests yet, because we still need to generate the test runner.

Generating the Test Runner


The CxxTest tool uses Perl to generate a test runner for your test suites. If you dont already have Perl, you need to install that. If youre running on GNU/Linux, you almost certainly have Perl already. If you are running on Windows with Cygwin, as we use for this example, you can install Perl as part of your Cygwin installation. If you are using Windows without Cygwin, you can get a good Windows distribution from http://www.activestate.com. If you are using another platform, you should be able to get Perl by consulting http://www.perl.com. Once you have Perl, download and install CxxTest. The package comes as a ZIP file, which expands to create a cxxtest/ folder. On my system Ive unzipped the archive in C:\Cygwin\usr\local, so that the package is in C:\Cygwin\usr\local\cxxtest. Using CxxTest, we will generate a test runner to run the tests. The command to generate a test runner for the board_tests.h file is
perl cxxtestgen.pl -o runner.cpp --error-printer board_tests.h

Well add a tool to our project to generate the test runner. Follow these steps:

1.

Open the Project Properties dialog.

57

Part II: Using SlickEdit


2. 3.
Select the Tools tab. Click New. SlickEdit displays the New Project Tool window, as shown in Figure 4-9.

Figure 4-9

4. 5.

Enter Generate Test Runner for the New Tool Name. Click OK. SlickEdit adds the tool to the tool list and shows you its properties. Enter the command line:

C:\cygwin\bin\perl.exe C:\cygwin\usr\local\cxxtest\cxxtestgen.pl -o runner.cpp --error-printer board_tests.h

The command line should be all one line. You may need to adjust the paths for your own installation of Perl and CxxTest.

6.

Click OK to close the Project Properties dialog.

You now have a new item on the Build menu: Generate Test Runner. Try it now. If everything was configured correctly, a file runner.cpp should be generated in your project working directory. The contents of runner.cpp are not particularly important. You can take a look if you want to find out more about how CxxTest works. For our purposes, the important point is that it contains a main() function and thus can be used to run an application. The runner.cpp file does include other header files from the CxxTest distribution. For it to compile without errors, we need to add the CxxTest distribution directory to our projects include directories. To do this, follow these steps:

1. 2. 3. 4. 5.

Open the Project Properties dialog. Select the Directories tab. Double-click on the bottom line in the Includes list to add a new directory. Enter the directory where CxxTest is installed, for example, C:\cygwin\usr\local\cxxtest. Click OK to close the Project Properties dialog.

Well now add runner.cpp to our project, so that it will be included in the compilation step, and well be ready to run.

1. 2. 3. 4. 58

Open the Project Properties dialog. Select the Files tab. Click Add Files, and add runner.cpp. Click OK to close the Project Properties dialog.

Chapter 4: Workspaces and Projects


Running the Tests
Everything is now set up to run the test suite. To run it, Invoke project-execute (Ctrl+F5 or Build Execute). If everything is set up correctly, you should see output from a successful test run, as shown in Figure 4-10.

Figure 4-10

Lets introduce a bug in the code and see what happens when we run the tests. Well change the last assignment in Board::unplace() from false to true, as shown below:
int Board::unplace(int row) { int col = pos_[row]; pos_[row] = -1; col_[col] = false; diag1_[col-row+size_] = false; diag2_[col+row] = true; return col; }

After making this change, we execute the tests again. This time, we get a bunch of failures, as shown in Figure 4-11. You can use SlickEdits error navigation commands prev-error (Ctrl+Shift+Up) and next-error (Ctrl+Shift+Down) to navigate among the test failures. This works because the CxxTest output looks like compiler output, with line numbers of errors. For this to work properly with SlickEdit, its important that you have Capture output and Output to build window checked in the configuration for the Execute tool in your project properties.

59

Part II: Using SlickEdit

Figure 4-11

Target Configurations
SlickEdit supports multiple target configurations. The default configurations for a new project are Debug and Release, familiar to developers who have used Microsoft Visual C++ products. The configurations allow you to store compiler options in a named configuration.

Build Systems
SlickEdit supports three different build system alternatives for C/C++ projects: Build without a makefile (dependencies automatically checked). Build with a user-maintained makefile or custom build command. Build with an auto-generated, auto-maintained makefile.

For experimenting or for small projects, you can use SlickEdits automatic dependency checking, as we did in our example. For large professional projects, you will probably have additional artifacts and other steps in the build process, and you will probably use your own makefile.

60

Chapter 4: Workspaces and Projects

Creating a Java Project


To use SlickEdit with a Java project, you need to have a JDK installed. In this section, well create a Java version of the queens program we developed in C++. First well show how to set up the project, then how we can compile Java code from within SlickEdit. Finally, well show how to execute the Java application and its tests. The structure of the Java project is the same as the C++ project. Well have these files:
Board.java The definition of the Board class. Queens.java The main() function.

Ive placed these files in Z:\ProfessionalSlickEdit\projects\java_queens on my system. The code for this project is also included on the accompanying CD-ROM, and we wont use space by listing it here. Its very similar to the C++ code already presented.

Creating the Project


To create a Java project for these files, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9.

Open the New Project dialog (Project New). Select project type Java Empty Project. There are many other Java project types, but most of them are more for demonstration purposes than for real programs. Usually for Java projects you will use the Java Empty Project project type. Enter java_queens for the Project name. Enter the Location for the SlickEdit project files. On my system, I put the project files in the root of the source tree, in Z:\ProfessionalSlickEdit\projects\java_queens. Enter Queens as the Executable name. For Java programs, the executable name is the class containing the main() function. Click OK. SlickEdit opens the Project Properties dialog. Click Add Files. SlickEdit displays the Add Source Files dialog. Select the two files Board.java and Queens.java, and click OK. SlickEdit shows the two Project files. Were done setting up the project. Click OK to close the Project Properties dialog.

We now have the Java project set up. We can use SlickEdit to build it.

Building the Project


To build the project, invoke project-build (Ctrl+M or Build Build), as for C/C++. SlickEdit invokes the configured build process and displays output in the Build tool window. An example of a build with compile errors is shown in Figure 4-12.

61

Part II: Using SlickEdit

Figure 4-12

As with C/C++, you can use prev-error (Ctrl+Shift+Up) and next-error (Ctrl+Shift+Down) to navigate among your compilation errors.

Executing the Project


To execute the Java program, invoke project-execute (Ctrl+F5). Again, this project requires a number as a command-line argument. Java options are completely different from GNU C/C++. To specify the command-line argument, follow these steps:

1. 2. 3. 4.

Open the Java Options dialog (Build Java Options). This dialog has several tabs to configure all aspects of compiling, running, and debugging Java programs. Select the JRE tab. Enter a number (such as 4) in the Arguments field. Click OK to dismiss the Java Options dialog.

Adding Unit Tests


Lets add some JUnit tests to our project. SlickEdit has integrated JUnit support; thus theres no need to add a separate project for running the tests, as we did with C/C++. This is a more natural way to work, reflecting Javas more standardized approach to unit testing. Well write the tests using JUnit 3.8.1.

62

Chapter 4: Workspaces and Projects


At this writing, SlickEdit does not support the 4.x versions of JUnit. See www.junit.org for more information about JUnit and downloads.

Writing the Test Suite


The standard approach to unit testing with Java is to write a test class for each main class in your application. The test classes are usually named with Test (or sometimes TestCase) appended to the name of the application class. The test classes must extend junit.framework.TestCase. In our case, we write the test class as BoardTest in file BoardTest.java. This file is included on the accompanying CD-ROM. An excerpt of the test class is shown below:
import junit.framework.TestCase; public class BoardTest extends TestCase { // ... other test methods ... public void testUnplace() { Board b = new Board(4); b.place(0, 1); assertFalse(b.isOk(1, 1)); assertFalse(b.isOk(0, 1)); assertFalse(b.isOk(2, 3)); b.unplace(0); assertTrue(b.isOk(1, 1)); assertTrue(b.isOk(0, 1)); assertTrue(b.isOk(2, 3)); b.place(1, 3); b.place(2, 0); b.place(3, 2); assertEquals(3, b.unplace(1)); assertEquals(-1, b.getCol(1)); assertEquals(2, b.unplace(3)); assertEquals(-1, b.getCol(3)); } // ... other test methods ... }

We need to add this source file to the project. Use Add Files on the Files tab of the Project Properties dialog to do that. We also need to add junit.jar to the classpath, for compilation and execution of the unit tests. To do that:

1. 2. 3. 4. 5. 6.

Invoke javaoptions (Build Java Options). The Java Options dialog appears. Select the Classpath tab. Click Add Jar File. The Open dialog appears with the title Add Jar File. Navigate to and select junit.jar. Click OK to close the Add Jar File dialog. Click OK to close the Java Options dialog.

63

Part II: Using SlickEdit


Running the Tests
SlickEdit has JUnit support integrated, using the JUnit tool window. To activate this window and run the tests:

1. 2. 3.

Activate the Projects tool window. (Click its tab or use View Toolbars Projects.) Expand the project root to display the package or test case you wish to run. In this case, the files are all in the default package (i.e., they are not in a package); thus we select that. Right-click on the package, and select Unit Test Run from the context menu. SlickEdit displays the Unit Testing tool window and runs the tests. The results are shown in the tool window.

If there are test failures, they are shown in the Unit Testing tool window, along with stack traces. Lets experiment with a test failure. Again, we change the last assignment in the unplace() method from false to true:
public int unplace(int row) { int col = pos[row]; pos[row] = -1; this.col[col] = false; diag1[col - row + size] = false; diag2[col + row] = true; return col; }

Run the tests again from the Unit Testing tool window:

1. 2.

Activate the Unit Testing tool window if it is not displayed (View Toolbars Unit Testing). Right-click BoardTest, and select Run Test from the context menu. SlickEdit runs the tests again. This time, there are failures, as shown in Figure 4-13.

You can double-click in the Tests pane or the stack traces to navigate to the failure locations in the source files.

Figure 4-13

64

Chapter 4: Workspaces and Projects

Managing the Project with Ant


Many Java projects are managed using Ant (http://ant.apache.org/). SlickEdit can execute Ant tasks in the editor. Heres an example of an Ant project file, build.xml, for the queens project:
<project name=queens basedir=. default=all> <target name=clean> <delete dir=build/> </target> <target name=prepare> <mkdir dir=build/> </target> <target name=compile depends=prepare> <javac srcdir=. destdir=build/> </target> <target name=test depends=compile> <junit printSummary=true fork=true> <classpath path=build/> <formatter type=brief usefile=false/> <test name=BoardTest/> </junit> </target> <target name=all depends=clean,test/> </project>

To manage the project with Ant, add the build.xml file to the projects files. Once you have done this, SlickEdits Build menu should include a menu entry called Execute Ant Target, which cascades down to the targets in your build.xml file.

Creating a Project for a Dynamic Language


Dynamic languages dont have compilers, thus in many ways they are a lot simpler to deal with than compiled languages. For one thing, there are no default tools or compiler settings. For this reason, SlickEdit doesnt contain specific project types for dynamic languages. Its still worthwhile to use SlickEdits workspaces and projects for dynamic languages, for the benefits of file organization and tagging. In this section, we show how you can also use SlickEdits project settings and build menu to run code from your dynamic language project. For this example, well port the queens project to Ruby. The techniques shown apply just as well to any other interpreted language, such as Perl or Python. To follow this example, you need to have Ruby installed. See http://www.ruby-lang.org/en/. Ruby downloads are at http://www.ruby-lang.org/en/downloads/. If you are running Windows, use the one-click installer for Windows. If you are using a UNIX-like system, you may already have Ruby. Otherwise, you can download the source and build Ruby from source.

65

Part II: Using SlickEdit


For the Ruby version, we have these files:
board.rb The definition of the Board class. queens.rb The main program.

Ive placed these files in Z:\ProfessionalSlickEdit\projects\ruby_queens on my system. The code for this project is also included on the accompanying CD-ROM. The class uses the same algorithm as the C++ and Java versions.

Creating the Project


This part should be familiar by now. Here are the steps to create the Ruby project:

1. 2. 3. 4. 5. 6. 7. 8. 9.

Open the New Project dialog (Project New). Select the project type (Generic). This is the project type you use for all projects that dont use specific compilers and tools. For example, you would use Generic for an ASP or PHP Web project, or a PL/SQL database project. Enter ruby_queens for the Project name. Enter the Location for the SlickEdit project files. On my system, I put the project files in the root of the source tree, in Z:\ProfessionalSlickEdit\projects\ruby_queens. Enter queens.rb as the Executable name. Click OK. SlickEdit opens the Project Properties dialog. Click Add Files. SlickEdit displays the Add Source Files dialog. Select the two files board.rb and queens.rb, and click OK. SlickEdit shows the two Project files. Were done setting up the project. Click OK to close the Project Properties dialog.

We now have the Ruby project set up. We can use SlickEdit to run it.

Executing the Project


SlickEdit has no built-in support for executing dynamic languages, but its easy to add customized tools to SlickEdits build menu to run them. Here well customize the Execute tool to run our program with the Ruby interpreter. Follow these steps:

1. 2. 3. 4. 5. 6. 66

Open the Project Properties dialog. Select the Tools tab. Select the Execute tool. Change the Command line to ruby queens.rb 4. This will run the script with the argument 4. Select the Capture output and Output to build window options. This will cause the program output to appear in the Build tool window. Click OK to close the Project Properties dialog.

Chapter 4: Workspaces and Projects


You can now run the program using project-execute (Ctrl+F5). SlickEdit can provide some error navigation for Ruby. Suppose we alter the main script so that the output line is missing its terminating quote:
puts #{elapsed} seconds.

If we now run this using project-execute, we see the following error output in the Build tool window:
queens.rb:14: unterminated string meets end of file queens.rb:14: parse error, unexpected $, expecting kEND

Because these look like compiler error messages, SlickEdit can navigate among the errors using prev-error (Ctrl+Shift+Up) and next-error (Ctrl+Shift+Down).

Adding Unit Tests


Ruby developers are very enthusiastic about unit testing, and the standard Ruby library has unit testing built in. Well add Ruby unit tests for the Board class in the test_board.rb file. An excerpt of the test class is shown below:
require test/unit require board class TestBoard < Test::Unit::TestCase # ... other test methods ... def test_unplace b = Board.new(4) b.place!(0, 1) assert(!b.ok?(1, 1)) assert(!b.ok?(0, 1)) assert(!b.ok?(2, 3)) b.unplace!(0) assert(b.ok?(1, 1)) assert(b.ok?(0, 1)) assert(b.ok?(2, 3)) b.place!(1, 3) b.place!(2, 0) b.place!(3, 2) assert_equal(3, b.unplace!(1)) assert_equal(nil, b.col(1)) assert_equal(2, b.unplace!(3)) assert_equal(nil, b.col(3)) end # ... other test methods ... end

67

Part II: Using SlickEdit


Running the Tests
To run these tests, well add another item to the build tools. Follow these steps:

1. 2. 3. 4. 5. 6. 7. 8.

Open the Project Properties dialog. Select the Tools tab. Click New. SlickEdit shows the New Project Tool dialog. Enter Run Tests for the New Tool Name. Click OK. Enter ruby test_board.rb for the Command line. Select the Capture output and Output to build window options. This will cause the program output to appear in the Build tool window. Click OK to close the Project Properties dialog.

SlickEdit adds a new item called Run Tests in the Build menu. You can use this item to run the tests. Lets try this with the same bug weve used before in the C++ and Java versions. We change the last assignment of the unplace! method from false to true:
def unplace!(row) col = @pos[row] @pos[row] = nil @col[col] = false @diag1[col-row+size] = false @diag2[col+row] = true col end

Now run the tests using Build Run Tests. SlickEdit shows the test results in the Build tool window, as shown in Figure 4-14. However, this time there is no error navigation. This is because SlickEdit doesnt know how to parse the error messages from the Ruby interpreter.

Error Parsing
The error messages from the tests look like this:
1) Failure: test_solve_true(TestBoard) [test_board.rb:88]: <false> is not true. 2) Failure: test_unplace(TestBoard) [test_board.rb:52]: <false> is not true.

We can set up SlickEdit to recognize these error messages, using Error Regular Expressions configuration.

68

Chapter 4: Workspaces and Projects

Figure 4-14

This procedure makes use of SlickEdit regular expressions. In particular, to understand the procedure completely, you need to understand match groups in regular expressions. For more detail about SlickEdit regular expressions, see Chapter 7. Follow these steps:

1.

Open the Error Regular Expressions dialog (Build Configure Error Parsing). SlickEdit displays the dialog shown in Figure 4-15.

Figure 4-15

69

Part II: Using SlickEdit


2. 3. 4. 5. 6. 7.
Click the + beside the Expression Category list to add a new category. SlickEdit displays the New Expression Category dialog. Enter Ruby for the category. Click OK to close the New Expression Category dialog. The new category appears in the Expression Category list, and is selected and checked. Click the + beside the Expressions list to add a new expression. SlickEdit displays the Edit Expression dialog. Enter Test Error for the Name. Enter this Expression:

{#3[^\[]+}\[{#0:p}\:{#1:i}\]\:

This matches the middle line of a Ruby unit test error message. SlickEdits Error Regular Expression cannot match error messages that span more than one line. The expression is made up of three tagged expressions. The first one, {#3[^\[]+}, matches the test method and class at the beginning of the line, for example, test_solve_true(TestBoard). This match is assigned to match group 3. The second group is {#0:p}, which matches the filename and is assigned to group 0. The last group is {#1:i}, which matches the line number and is assigned to group 1. Ruby unit test error messages dont include a column number. If they did, we could assign another match to group 2 for the column number. SlickEdit uses the filename and line and column numbers for error navigation. See the online Help for more detail.

8. 9. 10. 11. 12.

Type or paste the error message lines into the Test Case text area. Click Validate to test the regular expression. If it is correct, SlickEdit displays a Matched Error Expression window containing details of the match. Click OK to close the Matched Error Expression dialog. Click OK to close the Edit Expression dialog. Click OK to close the Error Regular Expressions dialog.

Run the tests again using Build Run Tests. You can now navigate among the errors using prev-error (Ctrl+Shift+Up) and next-error (Ctrl+Shift+Down).

Custom Projects
SlickEdit includes several preconfigured project types. You can create new customized project types based on these, and change default configuration settings. This is useful if you want to change the default compilation settings or any other tool settings predefined by SlickEdit. If you want to do further customization in your custom project type, you can write a SlickEdit macro that is run when the project type is instantiated. For example, suppose all of your projects use a certain directory structure. This is a common feature in Java projects, which often have a structure similar to that shown in Figure 4-16.

70

Chapter 4: Workspaces and Projects

Figure 4-16

SlickEdits custom projects dont support adding folders to the project upon initialization. Well create a Slick-C macro to do the job, and combine this with a new custom Java project type. The macro will also add a wildcard to the project for all files under the src/ directory. To create the new project type, follow these steps:

1. 2. 3. 4. 5.

Invoke workspace-new (Project New). SlickEdit displays the New Project dialog. Click Customize. SlickEdit displays the Customize Packages dialog. Click New to create a new project type. SlickEdit displays the New Package dialog. Enter Java WROX for the Name. Select Java Empty Project to copy settings from. Select Generic if you do not wish to begin with any specific compiler support. SlickEdit displays a dialog titled Project Package for Java WROX. The dialog is very similar to the Project Properties dialog, but you cannot add files. Click OK to save the new project type, and close the Project Package dialog. Click OK to close the Customize Packages dialog. The new project type should now appear in the project types in the New Project dialog. Click Cancel to close the New Project dialog.

6. 7. 8.

Custom project definitions are stored in the usrprjtemplates.vpt file in your SlickEdit configuration directory. The SlickEdit GUI for custom project types does not allow you to specify the macro to run when a project is instantiated. To do that, well edit the XML file directly. Follow these steps:

1. 2. 3. 4.

Open the usrprjtemplates.vpt file in your SlickEdit configuration directory. Locate the XML element <Template Name=Java - WROX>. Add an InitMacro attribute to the element, so that it reads as follows:

<Template Name=Java - WROX InitMacro=wrox_create_java_dirs>

Save the file.

The macro source for wrox_create_java_dirs.e is shown below. (The source is also on the CD-ROM.) You need to load the module to proceed with this example.
#pragma option(strict, on) #include slick.sh

71

Part II: Using SlickEdit


#include project.sh _command void wrox_create_java_dirs() name_info(,) { // create src/java/com/wrox/ _str java_path = _file_path(_project_name) :+ src :+ java :+ FILESEP :+ com :+ FILESEP make_path(java_path); // create src/test/com/wrox/ _str test_path = _file_path(_project_name) :+ src :+ test :+ FILESEP :+ com :+ FILESEP make_path(test_path);

FILESEP :+ :+ wrox;

FILESEP :+ :+ wrox;

// add wildcard for src/*, recursive, excluding SVN files _ProjectAdd_Wildcard(_ProjectHandle(), src\*, *\.svn\*, true); }

As well as running a macro when a project type is instantiated, SlickEdit allows you to run macros at other points in the project/build cycle. You can configure your project to run one or more commands when the project is open, and before and after a build. These commands are supported through the GUI for predefined and custom project types, in the Open and Build tabs. We could add various other features to the new project. One idea would be to add a starting build.xml Ant file. This could be done in a Slick-C macro, but would involve a lot of ugly code like this:
_insert_text( _insert_text( _insert_text( <target name=\clean\>); <delete dir=\build\/>); </target>);

As well as being ugly, this code is difficult to maintain. A better solution for inserting boilerplate template code into projects with SlickEdit is to use file templates. In Chapter 11, we have a look at templates and show how you can programmatically instantiate a template in a custom project type to initialize common files.

Summar y
SlickEdits workspace and project features are important for getting the most out of SlickEdit. Several useful features depend on you setting up a project for your source files. Tagging is probably the most important of these. We cover tagging in detail in the next chapter. Some navigational and other features also require projects to be set up. By adding custom tools to projects, you can add support for your own workflow in SlickEdit. An example of this is in unit testing, which has become a software development best practice. You can also automate the creation and setting up of new projects using custom project types. By providing your own InitMacro for your custom project type, you get the full power of Slick-C programming to customize your project on creation.

72

Context Tagging
A lot of SlickEdits power comes from a feature called Context Tagging. Many of SlickEdits advanced navigation, editing, and browsing features depend on Context Tagging: Navigating to definitions and references. Automatic completions of functions, members, and parameters. Browsing definitions and references.

Context Tagging creates databases of symbols in your projects and libraries, and uses those databases to provide symbol-based navigation, editing, and browsing. The process of creating a tag database for a set of source files or a library is called tagging. When tagging a set of files, SlickEdit scans the files for symbols and updates the tag database with the symbol information. This information includes various properties about the symbol: The symbols category (class, structure, function, variable, etc.). The name of the symbol (owning class, short name, qualified name, etc.). The location of the symbol (file, line and column numbers, offsets, etc.). Associated data for the symbol (return type, arguments, exceptions, etc.).

SlickEdit uses the symbol information to provide a range of useful features. In this chapter we describe how to ensure that your project is tagged correctly. We cover some of the features that Context Tagging provides. We also go into some detail about how to manage tag databases effectively and some issues that arise with tagging.

Part II: Using SlickEdit

Setting Up for Tagging


For Context Tagging to work, you need to have tag databases for the symbols in your project and libraries. To get the most benefit from Context Tagging, you should tag all these files: All the source files in your workspace. Standard libraries installed as part of the language or compiler. Additional libraries you have installed globally on your system. Additional libraries specific to your project.

In the following section, we explain a little bit about tagging the files in your projects, and also the standard libraries for the languages youre using. Below, in Managing Tag Files, we talk about ways to tag additional runtime libraries used in your projects.

Tagging Your Workspace


To make use of Context Tagging, you must set up a project and an associated workspace. One of the files SlickEdit creates automatically for your workspace is a tag file, with the extension .vtg. This file is the tag database for symbols defined in files in your workspace. SlickEdit maintains the workspace tag database automatically when you add and change files in the workspace. Because of the high level of activity on the workspace tag database, it works best if you store it on your local hard drive. The easiest way to do this is to create your SlickEdit workspace definition on your local hard drive, even if source files are themselves somewhere else, such as on a network drive. Also, because the workspace tag database is frequently rescanned to pick up changes in your source files, you should avoid tagging read-only files in your workspace tag database. For example, if you have libraries associated with your project, you will get better performance if those libraries are tagged as global or per-workspace runtime libraries. That way, SlickEdit will not waste CPU effort rescanning them continuously. To ensure that tagging features work smoothly, avoid getting duplicate definitions of symbols included in your workspace tag file. For example, if you have a build process or directory structure that requires multiple copies of some source files, you should take care that only the main, master versions of the source files are included in your project definition(s), so that the tagging system does not create duplicate definitions.

Tagging Built-in and Standard Libraries


As well as your workspace tag file, SlickEdit maintains global tag databases, categorized by language. In each language category, you can create one or more tag databases. Usually you will use one tag database for the standard library for a given language, and perhaps additional tag databases for other global libraries. Languages such as C/C++ and Java, and many others, have a standard library that is normally installed as part of the compiler or SDK. For C/C++, the standard library is described by header files such as stdio.h and vector. For Java, the standard library consists of all the classes provided in the java.*

74

Chapter 5: Context Tagging


and javax.* packages and subpackages. The Java standard library source code is provided with the JDK, for example, in src.zip. Other languages have similar conventions. Tagging the standard library of your language is hugely valuable, as you will get all the benefits of the Context Tagging system across your standard library classes and functions. When you run SlickEdit for the first time, it performs some one-time configurations. One of these is auto-tagging the standard libraries for several popular languages or SDKs: C/C++. Java. .NET.

SlickEdit tries to find installation paths for each of these languages and displays them in the Create Tag Files for Run-Time Libraries dialog, shown in Figure 5-1. You can amend any of the installation paths, or disable tagging for any language by unchecking its box. Once you have specified all the details, click Create tag file(s), and SlickEdit initializes the tag databases.

Figure 5-1

You can run the auto-tagging again at any point later by invoking autotag. This command is also available via the Auto-Tag button on the Context Tagging Tag Files dialog (Tools Tag Files). Auto-tagging is available for C/C++, Java, and .NET only, but SlickEdit also can tag several other languages automatically as soon as you start using them. For example, Slick-C itself is tagged. Once you invoke any tagging-related feature in a Slick-C file, SlickEdit automatically creates the Slick-C tag database from the installed macro source. SlickEdit automatically creates tag databases for several dynamic languages too, such as Perl, Python, and JavaScript. We cover procedures for tagging in more depth below in this chapter, in the section Managing Tag Files. For now, lets take a look at some of the benefits of tagging.

75

Part II: Using SlickEdit

Listing Members
When you are using classes or structures, SlickEdit can list members for you if it knows the type of the variable you are working with. This is useful because it can remind you of the name of a method, or inform you about an unfamiliar API. It also saves a lot of typing. Suppose you are working with the class shown in Figure 5-2.

Figure 5-2

If we declare a variable foo of type FooBase, and then type a dot after foo, SlickEdits List Members feature activates. Figure 5-3 shows the list that appears. In the figure, the list extends below the cursor position. If you want to see the code below, you can press Shift+Up to move the list to above the cursor. Shift+Down moves it back to below the cursor.

Figure 5-3

The feature works the same if the variable is declared as a pointer, and we use the C/C++ pointer operator ->. Figure 5-4 shows the example with the declaration changed to a pointer.

Figure 5-4

You can use the arrow keys to navigate the list. If you type part of the name of a member, the selection is moved to the first matching item. Press Enter to select a member, or Escape to dismiss list members.

76

Chapter 5: Context Tagging


As you move around the list, SlickEdit displays information about the selected member. An example is shown in Figure 5-5, where SlickEdit shows the containing class and method signature. You can click the green arrow to invoke push-tag and jump to the methods definition.

Figure 5-5

If a method is overloaded, SlickEdit shows the variations as in Figure 5-6. You can click the blue arrows or use Ctrl+PgUp and Ctrl+PgDn to cycle through the variations.

Figure 5-6

If a member has a comment, SlickEdit shows this as documentation for the member. Figure 5-7 shows an example for the cancel() method.

Figure 5-7

If a member has JavaDoc comments, SlickEdit shows them as documentation for the member. Figure 5-8 shows an example for the start() method. You can page through the documentation comment using Shift+PgUp and Shift+PgDn.

Figure 5-8

77

Part II: Using SlickEdit


JavaDoc-style comments are widely used in Java programs, but they are also supported for several other languages such as C/C++ using tools like Doxygen (see http://www.stack.nl/~dimitri/doxygen/). As illustrated by SlickEdit and Doxygen, various programming tools can make good use of a standard format for documentation comments.

Configuring List Members


You can customize the behavior of the list members feature. The configuration options for list members are found on the Context Tagging tab of the Extension Options dialog (Tools Options File Extension Setup). The options are shown in the group titled List members and are described in full in the online Help. Figure 5-9 shows the Context Tagging tab of the Extension Options dialog.

Figure 5-9

List members is normally invoked automatically when you type a dot or -> operator. You can turn off automatic list members in the configuration dialog, by unchecking Auto-list members. You can always invoke list members manually with the list-symbols command (Alt+dot).

Getting Parameter Information


When you are coding a function or method call, SlickEdit can provide information about the parameters for you. Figure 5-10 shows an example using the apply() method of our FooBase sample class. SlickEdit shows the name and type of each parameter to the method, highlighting the current parameter in bold. The editor places the documentation above or under the current line, so that it does not obscure what you are typing. As with list members, you can move the documentation above or below using Shift+Up and Shift+Down.

Figure 5-10

78

Chapter 5: Context Tagging


If the method has Javadoc comments, the parameter help shows those as documentation for the current parameter. Figure 5-11 shows this using the start() method of our example. The cursor is on the first parameter, savepoints, thus it is highlighted in bold both in the parameter list and in the documentation. As with list members, you can use Ctrl+PgUp and Ctrl+PgDn to move between method overrides, and Shift+PgUp and Shift+PgDn to scroll the comments.

Figure 5-11

For some languages, SlickEdit can determine valid completions for parameters based on variables in the current scope. In Figure 5-11, there are no int variables in scope, and the only thing SlickEdit can suggest is a sizeof() expression. In Figure 5-12 we show an example in which there are some int variables in scope: sp and identifier. When SlickEdit shows the parameters for the start() method, it provides a list of suggested completions including these two variables.

Figure 5-12

If a variable exists in scope that matches a parameter in both name and type, SlickEdit goes further. The editor assumes that there is a very good chance that you will want to type in that variable name, thus it does it for you. Figure 5-13 shows this with our start() method again. This time, there is an int variable in scope with the same name as the savepoints parameter, thus immediately after we type the opening parenthesis, SlickEdit suggests that variable for the first parameter. Because the variable is selected, you can easily overtype it if you want something else. You can still use the arrow keys to select from the list of suggestions. Or, you can type a comma and move on to the next parameter.

79

Part II: Using SlickEdit

Figure 5-13

Figure 5-14 shows what happens after typing a comma. The second parameter is a char* named name. Because there is a matching variable in scope, SlickEdit prompts with that. If this is the variable we want to pass for the parameter, all we need to do now is press the closing parenthesis. We didnt have to type any parts of the parameter names!

Figure 5-14

Configuring Parameter Information


You can customize how parameter information works. The configuration options for parameter information are found on the Context Tagging tab of the Extension Options dialog (Tools Options File Extension Setup). The options are shown in the group titled Parameter information and are described in full in the online Help. The Context Tagging tab was shown above in Figure 5-9. For example, the behaviors to insert matching parameters automatically or to list compatible parameters are optional. They can be disabled in the configuration dialog. Parameter information is usually invoked automatically when you press an opening parenthesis. You can turn off automatic parameter information in the configuration dialog by unchecking Auto-display parameter information. You can always invoke parameter information manually with the functionargument-help command (Alt+comma).

80

Chapter 5: Context Tagging

Navigating with Symbols


One of the most useful features supported by Context Tagging is the ability to navigate directly to definitions and references for any symbol with a single keystroke. This is a tagging feature you will come to depend on. There are several different ways to do this.

The Preview Tool Window


The Preview tool window is common to many features that make use of Context Tagging. The Preview tool window shows information about a symbol. An example is shown in Figure 5-15. In the WROX emulation, you can show the Preview tool window with Alt+T followed by V.

Figure 5-15

In this C++ example, the Preview tool window shows information about the solve() method in the Board class. The top-left pane shows the symbol itself, along with an icon to indicate the type of symbol. It also lists different locations if a symbol is overloaded or if it has a separate declaration and definition. The top-right pane shows documentation about the symbol. SlickEdit can parse and format documentation comments for various languages. The bottom pane shows the source file itself in which the symbol is defined. In this case, the source file is a C++ header file. When you are typing code or navigating around your source files, the Preview tool window is automatically refreshed to display information about the symbol the cursor is on. The Preview tool window is also shown during certain other operations, to provide help when choosing among symbols. The Preview tool window is also synchronized with other tool windows, like Defs, Class, Reference, and Symbols. When you select an item in these tool windows, the Preview window displays information about the selected item. We cover these tool windows below in this chapter.

Navigating to Definitions
To navigate to the definition of the symbol the cursor is on, invoke push-tag (Ctrl+dot). If there is a single definition, SlickEdit navigates to it. Otherwise, SlickEdit displays a list of matching symbols, such as that shown in Figure 5-16.

81

Part II: Using SlickEdit

Figure 5-16

In Figure 5-16, there are two different overloads of the same method, each with a declaration and a definition. You can navigate to one of the choices by double-clicking it with the mouse, or using the arrow keys to pick it and pressing Enter. While navigating in the Select a tag window, SlickEdit also opens the Preview tool window and refreshes it to show the preview of the currently highlighted item. Sometimes the information in the Preview tool window is all you need, and there is no need to open the definition in the main editor window. In C and C++, functions usually have a separate declaration and definition. The declaration is often just the prototype for the function, while the definition contains the full body. If you invoke push-tag on a function with a declaration and a definition, SlickEdit displays the Select a tag dialog. You can make push-tag a little faster for this situation by choosing always to navigate first to either the declaration or the definition. You can set this up using the checkboxes on the Select a tag. This can also be configured (e.g., if you change your mind) in the Context Tagging tab of the File Extension options (Tools Options File Extension Setup). If you configure push-tag to go to the definition or declaration first, you can invoke it multiple times to cycle between them. This provides a very fast way to navigate among the declarations and definitions of C/C++ symbols.

Navigating to References
The complement of push-tag is push-ref (Ctrl+slash), which is used to navigate to references to the symbol at the cursor. While a symbol may have a single definition, symbols generally have multiple references. For this reason, SlickEdit provides the References tool window for browsing references. The References tool window is shown in Figure 5-17. In the WROX emulation, you can show the References tool window with Alt+T followed by R.

Figure 5-17

82

Chapter 5: Context Tagging


The left-hand pane shows the files and functions where references to the given symbol exist. You can double-click on an entry to open the file at the line of the reference, or use the arrow keys and Enter. Depending on your needs, you may not need to open the file, because the right-hand pane provides a scrollable preview showing the lines surrounding the reference. If you prefer, you can hide the preview to provide more room for the references themselves. For example, if you prefer to arrange the References tool window vertically by attaching it to the left-hand side of the editor, there isnt really enough room for the preview. To hide the preview pane, click the Hide Preview Pane button in the upper-right corner. To restore the preview pane, click the Display Preview Pane button next to it. If you do use the References tool window arranged vertically, you can view it and the Preview tool window at the same time. The Preview tool window synchronizes automatically with the selected item in the References tool window. The Symbol dropdown at the top of the References tool window contains previously searched symbols, so that you can easily repeat previous searches. You can also type new searches into the entry field. If you have a lot of references, it will be faster to build the list of files but not expand it. That way you can investigate references in the files you want. Select Tools Options Tagging Options, and put a check in Find references incrementally. Also, if you want push-ref to build the list but not jump to the first reference, put a check in Go to Reference only lists references. We cover other aspects of performance tuning for tagging below in this chapter.

Pushed Bookmarks
When you navigate to a definition or a reference using push-tag or push-ref, SlickEdit creates a pushed bookmark at your original location. You can return to the original location quickly by invoking pop-bookmark (Ctrl+comma). Pushed bookmarks form a stack, thus you can navigate repeatedly from one symbol to another and return in the reverse order by popping the bookmarks. If you have been navigating around a lot using push-tag and push-ref, without necessarily popping all of the bookmarks, you can end up with several of them in the bookmark stack. This doesnt cause any problems normally, but it can be annoying if you switch to doing something else, because you can find that popping too many bookmarks takes you back to an unexpected place. You can clear all the pushed bookmarks with the pop-all-bookmarks command. If you find you are popping bookmarks and ending up in files from a previously opened workspace, you might like to load this callback macro, which uses a Slick-C callback to ensure that all pushed bookmarks are popped when you close a workspace:
void _wkspace_close_popallbkms() { pop_all_bookmarks(); }

Thanks to Hartmut Schaefer (hs2) for this tip. The callback is called whenever SlickEdit closes a bookmark. We cover further details of bookmark usage and configuration in Chapter 6. We cover callbacks in more detail in Chapter 16.

83

Part II: Using SlickEdit

F inding Symbols
If you are already at a location where a symbol is used, its easy to navigate to it using push-tag. Sometimes you want to find a symbol, but you dont know the complete name of the symbol. It may be a long class name that you cant remember exactly. Or, you might want to find all symbols containing a certain word. SlickEdit 2007 provides a powerful GUI tool for searching for symbols, in the Find Symbol tool window. You can also perform searches for symbols from the command line.

The Find Symbol Tool Window


The easiest way to search for a symbol is to use the GUI Find Symbol tool window, shown in Figure 5-18. Activate the tool window with the activate-find-symbol command (WROX: Alt+T, followed by F).

Figure 5-18

Usually it is enough simply to enter part of the symbol name and press Enter. If you have a large project, you can use the options to refine your search in various ways. The options are well documented in the online Help. In particular, you can use the Look in dropdown to specify the scope of the search. Usually you use Context Tagging, which searches in all tag files currently associated with the workspace. Alternatively, you can specify to search only in the current file, project, or workspace. You can also search in a specific tag database. If Match case is checked, the symbol search is case-sensitive. If it is unchecked, the search is not casesensitive. In Figure 5-18 the checkbox is in its default state, which is actually the indeterminate state: neither checked nor unchecked. In this case SlickEdit first performs a case-sensitive search. If no items are found using a case-sensitive search, SlickEdit performs a case-insensitive search. You can use the filters to specify if you are interested only in symbols of a particular type, for example, classes.

84

Chapter 5: Context Tagging

Using the grep-tag command


Sometimes you may find it faster to search for symbols from the command line. The grep-tag command provides some of the capabilities of the Find Symbol tool window. One example in which you might prefer grep-tag is in writing your own macros. The syntax of the grep-tag command is:
grep-tag/pattern/options

The options for grep-tag are shown in Table 5-1. The grep-tag command also has a shorter alias, gt, which is handy for using on the command line.

Table 5-1
Option
E I R U B A P

Description Case-sensitive match. Case-insensitive match. SlickEdit regular expressions. UNIX regular expressions. Brief regular expressions. Search all tag files, rather than just the workspace tag file. Search the current project only.

The regular expression options are the same as those for the find command, which is described in Chapter 7.

Browsing Definitions
SlickEdit includes several tool windows that provide different ways to browse your code and view definitions. Most of these tool windows are driven by Context Tagging.

The Defs Tool Window


The Defs (Definitions) tool window shows definitions in the current file. It allows you to browse and navigate among those definitions, and also to other open files. Figure 5-19 shows the Defs tool window. In the WROX emulation, you can show the Defs tool window using Alt+T followed by D.

85

Part II: Using SlickEdit

Figure 5-19

The tool window shows all open files, with the current file expanded. The expanded file synchronizes automatically with the current edit buffer. If you have too many files open and dont wish to see them in the Defs tool window, uncheck the Display Files option in the tool windows context menu. The icons indicate the type of each symbol. Float the mouse over the icon to see bubble Help on what the icon means. You can also filter the list based on symbol type and visibility by checking or unchecking options in the context menu. You can double-click on an entry to navigate to it. Within the tool window, you can also move the focus in the list using the arrow keys or by typing part of an identifier. Press Enter to navigate to the symbol in the editor. If you have the Preview tool window showing, it is synchronized automatically with selections in the Defs tool window.

The Class Tool Window


The Class tool window shows the class hierarchy and members for the current class. You can browse and navigate to any member by double-clicking on it. The Class tool window is shown in Figure 5-20. In the WROX emulation, you can show the Class tool window using Alt+T followed by C.

Figure 5-20

86

Chapter 5: Context Tagging


Notice in the Class tool window that the class hierarchy is actually shown upside-down from what some people are used to. This is because the tree starts with the current class and expands nodes for the superclasses. This scheme works well for classes that have multiple superclasses, as frequently occurs in C++. The arrow buttons at the top work in the direction of the displayed hierarchy; thus you have to click the up arrow button to navigate to a subclass. If you have the Preview tool window showing, it is synchronized automatically with selections in the Class tool window. You can right-click in the Class tool window for a Context menu, and select or deselect Organize members by class to control how members are listed. When the option is on, members are listed under the class that defines them. When it is off, you see all of the members visible in the current class. This is just like the completion list youd get in the editor, but its shown in a big window that provides a preview to the method in the Preview window, helping you make the correct selection.

The Symbols Tool Window


The Symbols tool window is a kind of general-purpose symbol browser. You can browse symbols in the workspace tag database and any other tag database. The Symbols tool window is shown in Figure 5-21. In the WROX emulation, you can show the Symbols tool window using Alt+T followed by Y.

Figure 5-21

As with other browsing tool windows, the Preview tool window is automatically synchronized with selections in the Symbols tool window. The Symbols tool window supports advanced filtering. Right-click in the Symbols tool window to show the Context menu, and choose Filters Filtering Options. SlickEdit displays the Symbol Browser Filter Options dialog, shown in Figure 5-22. Using the options, you can filter what is displayed. For example, using the filtering options and the Class or Member search fields, you could filter the window to show Non-Const Public Data members in classes matching a certain regular expression.

87

Part II: Using SlickEdit

Figure 5-22

Managing Tag F iles


As weve seen, its pretty easy to use tagging with the source files for your own projects. As long as you remember to add each source file to your workspace via a project, tagging is taken care of automatically. To get the full benefits of Context Tagging, you should tag the runtime libraries used in your projects. This will make SlickEdits navigation, completion, and browsing features available for symbols in the runtime libraries. The main tool for managing tag databases is the Context Tagging Tag Files dialog, shown in Figure 5-23.

Figure 5-23

88

Chapter 5: Context Tagging


SlickEdit organizes tag databases across these categories: The Workspace Tag File contains the tag database for all the source files in projects in the current workspace. The Auto-Updated Tag Files group contains tag databases for other files associated with the workspace. The Compiler groups each contain tag databases for compiler runtime libraries for C/C++ and Java. The language groups each contain tag databases for global libraries for that language.

There is only one workspace tag file, and it always contains exactly the files in the projects in your workspace. If you add or remove files in the workspace tag file, they are added or removed from your workspace also, and vice versa. The auto-updated and global library categories can each contain any number of tag databases. Use the auto-updated tag files to manage tag databases that are project-specific. Use a global library category to manage libraries that are common to all projects using that language. The auto-updated tag file feature is designed so that a group of users can share one centrally updated tag file. However, it is also useful for a single user with different projects, as described here. For most languages, tag databases for standard libraries and other global libraries are created in the same category for the specific language. For C/C++, tag databases for compiler libraries are created in C Compiler Configuration Tag Files, while other global libraries are created in C/C++ Tag Files. As of SlickEdit 12.0.2, Java also has a separate configuration for compiler libraries and for other global libraries.

Global Tag Databases


If you have a runtime library that is global, so that you want to use it any time you are using a particular language, you can tag the library in a global tag database under the languages category, just as with the standard libraries. You can add the librarys files to the main tag database for the language if you want to, but it is usually cleaner to set up a separate tag database per additional library or group of libraries. Thus, for example, if you are using the wxWidgets library, you might create a tag database in a file named wxWidgets.vtg. Well use the wxWidgets library for some of the examples. It is an open-source C++ GUI library. You can find out more from http://ww.wxwidgets.org. Note that if you tag a library globally, that version of the library is used whenever you use that language, across all your workspaces. This is often inappropriate, because different workspaces may require different versions of a library. Global tag databases are pretty straightforward. Basically you have a tag database and a set of associated source files. When you create the tag database, you specify the language and the source files. SlickEdit scans the source files for symbols and populates the tag database.

89

Part II: Using SlickEdit


If you edit any file in the global tag database, SlickEdit retags the file when you save it. If you change the source files outside SlickEdit, you can rebuild the tag file manually. This might happen if you upgrade a library. You can also manage specific source files included in the tag database. Therefore, over time, you might move certain files in and out of the tag database as your usage of libraries changes. The idea with global libraries is that they shouldnt change very often. Once you set them up, they shouldnt require much further attention. Well look at some specific examples of setting up global tag databases below in this section.

Auto-Updated Tag Databases


Auto-updated tag databases are designed for sets of source files that are in between being part of your project and being global libraries. For example, you might have some common libraries within your organization that you import into multiple projects. The common libraries dont change as often as the files in specific projects do. You dont want to have SlickEdit rescanning the common library source files all the time, because it would be a waste of resources. With an auto-updated tag database, you control when the tag database is refreshed. Auto-updated tag databases are defined in workspaces. This means that you can have different libraries tagged differently for different workspaces. This is very useful if different workspaces require different versions of runtime libraries. Thus, for example, you could have wxWidgets-2.8.3.vtg being used by one project and wxWidgets-2.0.vtg being used by another. You cannot create an auto-updated tag database from scratch, and you cannot directly manage the source files tagged in an auto-updated tag database. Instead, an auto-updated tag database is linked to another pre-existing tag database, referred to as the shared tag database. You can create the shared tag database using another workspace or as a global tag database. When you open a workspace containing auto-updated tag databases, SlickEdit checks the shared tag databases to see if they have changed since the last refresh. If a shared tag database has changed, SlickEdit automatically refreshes the auto-updated tag databases (hence the name auto-updated). You can automate the creation and refresh of shared tag databases. Well look at some specific examples of setting up and using auto-updated tag databases below in this section.

Tagging Dynamic Languages


The standard library for an interpreted language such as Perl, Python, or Ruby is usually simply a set of source files in that language. For these libraries, you simply tag the source files themselves. The tagging engine tags them in the same way it would tag your own project files, which means that you get all the Context Tagging features for the standard library automatically. For example, you can navigate to function definitions and browse function documentation. Additional installed libraries are often installed in the global library tree, perhaps under a site/ subdirectory. The same benefits apply to these libraries. If additional libraries are installed in a separate directory, it is easy to add files from that directory tree to the same tag database, or a separate tag database. As mentioned above, SlickEdit automatically creates tag databases for most dynamic languages as soon as you start using them. Sometimes it is necessary to manage tag databases for standard libraries manually.

90

Chapter 5: Context Tagging


SlickEdit might not be able to find your language installation, or you might want to update your tag database to use a different installation.

Creating a Global Tag Database for Ruby


For example, suppose you are doing a Ruby project, and you find that SlickEdit has no tag database for Ruby. To tag the installed Ruby libraries, follow these steps:

1. 2.

Invoke gui-make-tags (Tools Tag Files). SlickEdit shows the Context Tagging Tag Files dialog. There is no Ruby category at this stage. Click Add Tag File. SlickEdit displays the Add Tag File dialog, shown in Figure 5-24.

Figure 5-24

3. 4. 5. 6. 7. 8.

Select the Ruby source type. Click OK. SlickEdit displays the Add Tags Database dialog. Type ruby.vtg for the tag file name. Click Open. SlickEdit displays the Add Tree dialog, prompting you for the location of the Ruby source files. Navigate to the location of your Ruby library files. On my system, they are in C:\ruby\lib. Click OK to add the files. The tag database has the source files added, as shown in Figure 5-25.

Figure 5-25

91

Part II: Using SlickEdit

Tagging C/C++ Libraries


The standard library for C/C++ is described by a set of header files. Tagging the header files gives many of the benefits of the Context Tagging system. For example, you can navigate to function declarations. If functions are well documented using a comment style that SlickEdit can understand, you can browse function documentation. Many additional C++ libraries are implemented as C++ code in header files. In these cases, you can navigate to function implementations also. Obviously, if libraries are implemented as compiled object code and you dont have the source, you cannot navigate to implementations.

Creating a Global Tag Database with Header Files


In this section, well work through an example of setting up tagging for a C++ runtime library. For the example, well use the wxWidgets GUI library, available at http://www.wxwidgets.org. Before working through the example, assume that weve downloaded the code archive and expanded into a suitable location. On my system, I have expanded it to C:\lib\wxWidgets-2.8.3. In this example, well create a global tag library for wxWidgets. See the following sections for ways to create workspace auto-updated tag databases. To create the global tag database, follow these steps:

1. 2. 3. 4. 5.

Invoke gui-make-tags (Tools Tag Files). SlickEdit shows the Context Tagging Tag Files dialog. Click Add Tag File. SlickEdit shows the Add Tag File dialog. Select C/C++. Click OK. SlickEdit prompts for the directory and filename for the new tag database. The default location is in the tagfiles/ subdirectory under your SlickEdit configuration directory. Give the tag database a suitable name. A good idea is to name the tag database with a name corresponding to the library being tagged; thus for wxWidgets, we might use wxWidgets.vtg, or wxWidgets-2.8.3.vtg. Note that if you include dot characters in the filename, you will need to add the .vtg extension also. Otherwise, SlickEdit misinterprets the filename. Specify the location for the tag database. The default location is the easiest, because that is where SlickEdit looks for tag databases by default. Click OK. SlickEdit displays the Add Tree dialog. Specify the file types to add to the tag database. For a C/C++ runtime library, choose the item from the dropdown that includes all the C/C++ file types: *.c;, *.cc;, *.cpp, and so forth. Specify the path to the library Include files. In my system, it is C:\lib\wxWidgets2.8.3\include. Click OK. SlickEdit builds the tag database. At this point, we have the tag database defined as a global runtime library.

6. 7. 8. 9. 10.

After following these steps, we have tagging set up for the runtime library, and all Context Tagging features should be available. A quick way to test whether tagging has worked correctly is to type the start of a line of code into a new .cpp file in the project:
wxDialogBase

92

Chapter 5: Context Tagging


The identifier wxDialogBase is a class in the wxWidgets library. You should be able to view symbol information for the class in the Preview tool window, or navigate to the class definition in the header file wx/dialog.h by invoking push-tag (Ctrl+dot). If you are happy to have the library available globally to all your C/C++ projects, you can stop here. If you want to have the library available only in the current workspace, read on through the following sections.

Converting a Global Tag Database to an Auto-Updated Tag Database


Suppose we have already set up the wxWidgets library as described in the above section. But now, we need to work on a different workspace/project that also uses wxWidgets, but an earlier version. If we tag the earlier version as a global tag database, SlickEdit will match symbols in both databases. To have Context Tagging features run smoothly, we need to have the separate workspaces refer to distinct tag databases for wxWidgets. An auto-updated tag file is the way to do this. Given that we have already got a tag database built for wxWidgets, we can convert it to use via an auto-updated tag file. Follow these steps:

1. 2. 3. 4. 5.

Invoke gui-make-tags (Tools Tag Files). SlickEdit shows the Context Tagging Tag Files dialog. Select Auto-Updated Tag Files. This step is important! Click Add Tag File. SlickEdit prompts for the tag file to add. The default location is the tagfiles/ subdirectory under your SlickEdit configuration directory. Select the tag database. In my case, it is wxWidget-2.8.3.vtg. Click OK. SlickEdit adds the tag database to the auto-updated tag files for the workspace. The tag database is now both referenced as a global tag database and linked from the auto-updated tag database. To eliminate duplicate symbols, we need to remove it from the list of global tag files. Select the tag database under the global C/C++ Tag Files category. Click Remove Tag File. SlickEdit prompts you to confirm that you wish to remove the file from your tag file list. Click Yes. SlickEdit prompts you whether you wish to permanently delete the file. Click No. The file is removed from the global tag file list but is still attached to the workspace. Click Done.

6. 7. 8. 9. 10.

After completing this procedure, Context Tagging features should still work with the workspace. But the tag database is now specific to the workspace. You can test Context Tagging using push-tag on a symbol from the wxWidgets library again. Auto-updated tag databases are linked to shared tag databases and are updated automatically from them. In this case, the shared tag database is wxWidgets-2.8.3.vtg in the tagfiles/ subdirectory of the SlickEdit configuration directory, because thats where we created the global tag database originally. The auto-updated tag database is wxWidgets-2.8.3.vtg in the workspace directory.

93

Part II: Using SlickEdit


Creating a Separate Workspace for an Auto-Updated Tag Database
Creating an auto-updated tag database from a global tag database is a fairly long procedure. If you know ahead of time that you want an auto-updated tag database, you can create the shared tag database as a separate workspace instead. Lets begin the example again, using a separate workspace for the wxWidgets library. If you have the tag databases created in the previous examples, you need to delete them for this example. You can delete the auto-updated tag database using the Context Tagging Tag Files dialog. If you still have the global tag database in tagfiles/, you can delete that using the file system, because SlickEdit contains no references to it anymore. To create a separate workspace for wxWidgets, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.

Invoke workspace-new (Project New). SlickEdit displays the New Project dialog. Choose Generic C/C++ for the project type. Enter wxWidgets-2.8.3 for the Project name. Specify the location of the wxWidgets Include directory as the Location. On my system, it is C:\lib\wxWidgets-2.8.3\include. Click OK to create the workspace. SlickEdit displays the Project Properties. Click Add Wildcard to add files. SlickEdit displays the Add Tree dialog. Enter *.* for the Filespec. Ensure that Recurse is checked. All the source files in the include/ directory and subdirectories will be included in the tag database. Click OK to close the Add Wildcard dialog. Click OK to close the Project Properties dialog. SlickEdit scans the files and creates the tag database. Close the workspace (workspace-close, or Project Close Workspace).

At this point, you have the tag database created. You can link an auto-updated tag database in the real project to this tag database using the same procedure as we used above to link one to a global tag database. After creating the auto-updated tag database, you can test tagging by invoking push-tag on a symbol defined in the wxWidgets library. Similarly to before, you should now have a shared tag database in the wxWidgets include/ directory (C:\lib\wxWidgets-2.8.3\include\wxWidgets-2.8.3.vtg) and an auto-updated tag database in your project. Whenever you open your project, SlickEdit checks the shared tag database to see if it has changed. If it has, SlickEdit refreshes the auto-updated tag database. For this method, we have created a separate workspace for the wxWidgets library. If we were doing this to make a tag database for a common project within the organization, this would be quite natural. Whenever you open the wxWidgets project, SlickEdit scans the source files and updates the workspace tag database. This is one way you can keep the tag database up to date.

94

Chapter 5: Context Tagging


If you dont have a reason to open the separate workspace, you can update its tag database using the vsmktags command-line tool. The syntax of the tool is:
vsmktags workspaces

where workspaces are the filenames of the workspaces to update. Run vsmktags with no arguments to get a list of options supported. The vsmktags command scans all the source files in the workspace and updates the workspace tag database. This is why we used Add Wildcard, rather than Add Tree, to specify the files in the project. (If we used Add Tree, new files would not be automatically added to the workspace tag database.) The design of the auto-updated tag database mechanism is for you to use the mechanism for common subprojects within your organization. You can set up nightly jobs to refresh shared copies of workspace tag databases, and then in your personal workspaces, use auto-updated tag databases linked to the shared copies. This reduces the impact on individual developers of rescanning large common code bases that change slowly.

Creating a Tag Database Directly


The wxWidgets library is actually a third-party library, not a part of the code base of our organization. With true third-party libraries, some aspects of the separate workspace/vsmktags approach are often inappropriate. For example, the copy of the library were using probably doesnt change over time. If we upgrade to a new version of wxWidgets, we might prefer to install the new version in a new directory and create another tag database, rather than overwriting the existing one. For this situation, we can dispense with the workspace altogether and get SlickEdit to create just a tag database for a set of files. This functionality is not available through the GUI, however. Instead, it is provided by a SlickEdit batch macro, which we can invoke from the SlickEdit command line. Lets use this technique to repeat our wxWidgets example one more time. Before starting, remove any SlickEdit tag and project files we created for wxWidgets. (Project Organize Workspaces, and use the Delete button.) To create the tag database, follow these steps:

1.

Change the working directory to the include/ directory of the wxWidgets distribution. On my system, this is C:\lib\wxWidgets-2.8.3\include. This is where we will create the tag database. You can create it anywhere you like, and because it is not frequently refreshed, there is less concern about whether you create it on a network drive. Enter this command on the SlickEdit command line:

2.

make-tags -t C:\lib\wxWidgets-2.8.3\include\*.h -o wxWidgets-2.8.3.vtg

3.

SlickEdit scans the source files and creates the tag database. When it has finished, it displays a message in the status area giving the full path of the newly created tag database.

In this example, we used the t option, which scans a tree for files. You can also use L to specify a file containing a list of source files to scan. Other options are described in the macro source in maketags.e.

95

Part II: Using SlickEdit


You can automate the creation of tag databases by invoking SlickEdit from the command line. For example, you can run the above SlickEdit procedure from the command line with a command like this:
vs.exe +new -p make-tags -t C:\lib\wxWidgets-2.8.3\include\*.h -o C:\lib\wxWidgets-2.8.3\include\wxWidgets-2.8.3.vtg -c

The entire command should be entered on one line. Note that you should use absolute paths, otherwise SlickEdit may not behave reliably if it tries to restore its working directory when launching. The single quotes in the command are for a bash shell in Windows such as in Cygwin. For the CMD shell, remove the quotes. On UNIX, use UNIX paths.

Working with Different Compilers


SlickEdits support for C/C++ and Java compilers is more sophisticated than its support for other languages. SlickEdit supports multiple installed C/C++ compilers and can switch among them easily. For each installed compiler, you create a SlickEdit configuration that contains details about the compiler, including a tag database for the compilers runtime library. One compiler is designated as the default C/C++ compiler and becomes associated with new C/C++ projects by default. You can change the default at any time, and you can change the compiler associated with any project. To create a compiler definition and associated tag database, follow these steps:

1. 2. 3.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Click Auto-Tag. SlickEdit displays the Create Tag Files for Run-Time Libraries dialog. The Compiler dropdown list contains C/C++ compilers found on your system. On my system, I have a couple of options from Cygwin, and the Microsoft VC++ compiler, as shown in Figure 5-26. Choose the compiler for which to create a configuration. If your compiler is not in the list, you need to create a new compiler definition, as described below.

Figure 5-26

96

Chapter 5: Context Tagging


4. 5. 6.
Uncheck the Java and .NET compilers if you are not interested in them, or if you have already tagged them. Click Create tag file(s). SlickEdit closes the Create Tag Files for Run-Time Libraries dialog and creates the tag database. Click Done.

You can repeat this process for each compiler on your system. To associate your C/C++ project with a compiler configuration, follow these steps, with your project open:

1. 2. 3. 4.

Invoke project-edit (Project Project Properties). SlickEdit displays the Project Properties dialog. Select the Compile/Link tab. Select the Compiler from the dropdown list. Click OK.

If SlickEdit doesnt list your compiler in its list, you need to create a compiler definition for it. The compiler definition specifies the locations of header files, so that SlickEdit can create a tag database. Suppose we have downloaded the Digital Mars C/C++ compiler from http://www.digitalmars.com and installed it under C:\dm. To add a new custom C/C++ compiler definition for Digital Mars, open a C/C++ file and follow these steps:

1.

Invoke refactor-options. SlickEdit displays the C/C++ Compiler Properties dialog, shown in Figure 5-27. This dialog can also be reached via the GUI. You can find it in the menu under Tools C++ Refactoring C/C++ Compiler Options, but only if you have a C/C++ project open. You can also open it via the Browse button in the C/C++ section on the Create Tag Files for Run-Time Libraries dialog.

Figure 5-27

97

Part II: Using SlickEdit


2. 3. 4. 5. 6. 7. 8. 9. 10.
Click Add. SlickEdit prompts you to enter the name of the new configuration. Enter Digital Mars 8.49 for the name. Click OK. Click the .. button next to the Built-in Compiler Include Directories list. SlickEdit displays the Choose Include Directory dialog for you to choose a directory. Navigate to C:\dm\include. Click OK to add the directory. Click Build Tag File. SlickEdit scans the header files in the include directory and builds a tag database. Click OK. SlickEdit prompts you whether to make the new compiler the default configuration. Click No.

You now have the Digital Mars compiler available for your C/C++ projects. If you select this compiler in a project, the Context Tagging system will use symbol data from the Digital Mars header files.

Tagging Java Libraries


Many of the techniques for managing C/C++ tag databases apply for Java and other languages too. There are some differences, which we cover here. The standard library for Java is supplied in source form in a ZIP file with the Java SDK. By tagging that ZIP file, you get the full benefit of the Context Tagging system for standard library classes. You can navigate to method definitions and browse class and method documentation. Additional libraries for Java are usually supplied as JAR files. You can tag JAR files, and get some of the benefits of the Context Tagging system. The main benefit you get is completions. However, the support is not as good as with source files, because JAR files lack several features from the source files: Parameter information does not show the original names of parameters. Rather, SlickEdit will show parameters as A, B, and so on. Seeing the type of each parameter is helpful, but not as helpful as seeing both the type and the name. No JavaDoc information is available. This also reduces the amount of assistance you get from Context Tagging. You cannot navigate to a symbol defined in a JAR file.

You can tag Java source files for a library, if you have them available. This is certainly desirable, because you will get all the benefits the Context Tagging system can provide. Many Java libraries these days are open source, and it is often useful to download and install the source on your system. As well as enabling more Context Tagging features, you will also be able to learn a lot about a library by reading its source code! Whether you tag JARs or source files for your additional libraries, you need to decide for each one whether to tag it in your workspace or tag it globally in the Java Tag Files category. Usually you will want the option of tagging different versions of runtime libraries for different projects, thus you need to tag them per workspace.

98

Chapter 5: Context Tagging


Creating a Global Tag Database with JAR Files
The quickest and easiest way to get up and running with Context Tagging for Java is simply to add all your JAR files to one or more global tag databases. Lets work through an example. Suppose we wish to do a Java project using the popular Spring framework (http://www.springframework.org). Before starting, download the framework with dependencies, and unzip it under C:\lib. On my system, the full directory of the framework is C:\lib\spring-framework-2.0.2. Well create an empty Java project, called java_spring. In the project directory, create a subdirectory called lib. This is where well put the JARs for the project. The Spring distribution comes with many additional JARs that can be used with various Spring features. Because the framework as a whole has a dependency on commons-logging.jar, well start by copying just spring.jar and commons-logging.jar from the distribution into the projects lib directory. We now have a single Java project, and all of the runtime library JARs are in the projects lib directory. To set up tagging for those libraries in a global tag database, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the Java category. Click Add Tag File. SlickEdit displays the Add Tag File dialog. Select the Java language. Click OK. SlickEdit displays the Add Tags Database dialog, prompting you for the name of your global tag database. Enter java_libs for the File name. Click OK. SlickEdit displays the Add Tree dialog. Change the File types to *.jar. Navigate to your projects lib directory, and select it. Click OK. SlickEdit builds the tag database, containing symbol information for commonslogging.jar and spring.jar. You can see these two files listed in the right-hand pane when you select the java_libs.vtg tag database. Click Done.

The global tag database is created. Many Context Tagging features work, but not all of them. You can confirm this by typing code into an empty .java file:
class Tryme { void foo() { JdbcTemplate } }

When you type JdbcTemplate and press space, SlickEdit adds an import for the org.springframework .jdbc.core.JdbcTemplate class at the top of the source file. But if you place the cursor on

99

Part II: Using SlickEdit


JdbcTemplate and open the Preview tool window, there is no preview available. SlickEdits preview is

based on source files, not symbol information; thus SlickEdit cannot preview a class from a JAR. To get better Context Tagging support for Java libraries, well use Java source files.

Creating a Global Tag Database with Java Source Files


Lets replace spring.jar in the global tag database with the Spring framework Java source files. For Spring on my system, the source code is in C:\lib\spring-framework-2.0.2\src. To change the global tag database to use the source files, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the java_libs.vtg tag database in the Java category. Select the spring.jar file in the right-hand pane. Click Remove Src File. SlickEdit prompts you to confirm that you wish to remove the selected files from the tag database. Click Yes. SlickEdit removes the source file. Click Add Tree. SlickEdit displays the Add Tree dialog. Ensure that the File type is *.java. Navigate to the src directory in the Spring distribution. Click OK. SlickEdit adds the source files and tags them in the tag database. Click Done.

You can verify that Context Tagging is working for the Spring library now by opening the Preview tool window when your cursor is on a symbol from the library, such as JdbcTemplate. In these two examples weve placed two separate libraries into a single global Java tag database: Spring and commons-logging. In practice, you would probably want to tag separate libraries into separate tag databases. A library such as commons-logging is relatively static, and you may find that a global tag database is appropriate for it even if you have more than one Java project using it. Other libraries, such as Spring, have more frequent changes. You may find that different projects need different versions. In this case, you will be better off associating the tag database with your workspace.

Creating a Separate Workspace for an Auto-Updated Tag Database


As with the C++ example, we can create a workspace for a Java runtime library and use an auto-updated tag database to link our project to it. Lets work through this procedure using the Spring library. First, well remove the Spring source files from the global tag database:

1. 2.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the java_libs.vtg tag database in the Java category.

100

Chapter 5: Context Tagging


3. 4. 5. 6.
Select all of the Spring source files in the right-hand pane. Click Remove Src File. SlickEdit prompts you to confirm that you wish to remove the selected files from the tag database. Click Yes. SlickEdit removes the source files and updates the tag database. Click Done.

Now, well create a workspace for the Spring framework source distribution. Follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Invoke workspace-new (Project New). SlickEdit displays the New Project dialog. Select Java Empty Project. Enter spring-framework-2.0.2 for the Project name. Specify the location as the directory containing the Spring distribution (C:\lib\springframework-2.0.2). Click OK. SlickEdit displays the Project Properties for the new project. Click Add Wildcard. SlickEdit displays the Add Wildcard dialog. Enter src\*.java for the Filespec. Check the Recurse checkbox. Click OK. SlickEdit adds the wildcard. Click OK. SlickEdit scans the src directory for .java files and tags them in the workspace tag database.

We now have a workspace for the Spring library, and all the source files tagged. To use this tag database in our project, well link an auto-updated tag database to it. Reopen the main project (java_spring), and follow these steps:

1. 2. 3. 4. 5. 6. 7.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the Auto-Updated Tag Files category. Click Add Tag File. SlickEdit displays the Add Tags Database dialog. Navigate to the location of the tag file for the Spring framework workspace (C:\lib\springframework-2.0.2). Select the tag database (spring-framework-2.0.2.vtg). Click OK. SlickEdit creates the auto-updated tag database and updates it with the source files from the shared tag database. Click Done.

At this point you have the library tagged in your project via an auto-updated tag database. You can confirm that its working by opening the Preview tool window when your cursor is on a symbol from the Spring library, such as JdbcTemplate.

101

Part II: Using SlickEdit


The auto-updated tag database is specific to the workspace. You can create different auto-updated tag databases in different workspaces, linking to different versions of libraries.

Creating a Tag Database Directly


As in the C++ example, you might prefer a shorter way to create the tag database for the Spring source files, if youre not interested in opening Spring as a workspace in its own right. You can use the maketags command as we did for the C++ example. To do this for the Spring framework, first remove the workspace files (*.vpj, *.vpw, *.vpwhist, and *.vtg). Then follow these steps:

1. 2.

Change the directory to the location of the framework distribution (C:\lib\spring-framework-2.0.2).

Enter this command on the SlickEdit command line:

make-tags -t src\*.java o spring-framework-2.0.2.vtg

SlickEdit scans the source files and creates the tag database. When it has finished, it displays a message in the status area giving the full path of the newly created tag database. You can now link an auto-updated tag database in the workspace to this tag database, as described above.

Adding JARs to the Workspace


Sometimes you have a JAR for a runtime library, and the Java source code is not available. As described above, you can tag JARs in a global tag database for some of the benefits of Context Tagging. You can also add JARs to your workspace for similar (limited) benefits. The advantage of adding them to your workspace is that you dont clutter up the global tag databases with lots of different JARs, and also you can tag different versions in different projects. SlickEdit scans for when the files timestamp on disk changes; thus if the file never changes and its modification date doesnt change, SlickEdit doesnt retag it. Therefore, theres no performance penalty in including JARs in your workspace.

Working with Different JDK Versions


SlickEdit (as of 12.0.2) supports multiple Java compiler definitions, as it does for C/C++. There is a global tag database per compiler definition. Refer to the C/C++ information above for configuring multiple compilers.

Tagging .NET Runtime Libraries


The .NET considerations are mostly the same as for Java. The standard library is supplied as a set of assemblies, for example, mscorlib.dll. SlickEdit tags the DLLs to form the tag database. Many of the metadata required for tagging are present in .NET DLLs.

102

Chapter 5: Context Tagging


SlickEdit can also parse the documentation XML files provided with the assemblies and use the comments from the documentation to provide help on classes and members.

Creating a Global Tag Database with DLL Assemblies


Lets work through an example of a global database using a .NET DLL assembly. For this example, well use the .NET variation of the Spring Framework, found at http://www.springframework.net. Download the distribution, and unzip it in a suitable location. On my system, it is in C:\lib\Spring .NET-1.1.0 Preview 3. To set up a global tag database for the Spring.NET DLL, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the C# category. Click Add Tag File. SlickEdit displays the Add Tag File dialog. Ensure that C# is selected. Click OK. SlickEdit displays the Add Tags Database dialog. Enter springnet for the File name. Click OK. Spring displays the Add Tree dialog. Enter *.dll for the File types. Navigate to the location of the Spring.NET DLLs appropriate for your .NET version in the distribution directory (e.g., C:\lib\Spring.NET-1.1.0 Preview 3\bin\net\1.1\release). Click OK. SlickEdit scans the DLLs and creates the tag database. Click Done.

The global tag database is now created. You can verify that it is working by typing this code into an empty C# file:
class Tryme { void foo() { AdoTemplate template; template. } }

Open the Preview tool window with the cursor on AdoTemplate. You should see some class and method names in the top-left pane, but no other information. As with Java JAR files, DLL assemblies provide only a limited amount of symbol information for Context Tagging. However, if you also add *.xml (assuming there are xmldoc documentation files), SlickEdit will also scan those and correlate the definitions in the DLL with the documentation in the XML. It will then be able to display documentation comments in List Members and the Preview window. Alternatively, to get better support, you can tag the source files themselves.

103

Part II: Using SlickEdit


Creating a Global Tag Database with C# Source Files
Lets replace the Spring DLLs in the global tag database with the Spring framework C# source files. For Spring.NET on my system, the source code is in C:\lib\Spring.NET-1.1.0 Preview 3\src. To change the global tag database to use the source files, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select the springnet.vtg tag database in the C# category. Select the DLL files in the right-hand pane. Click Remove Src File. SlickEdit prompts you to confirm that you wish to remove the selected files from the tag database. Click Yes. SlickEdit removes the source file. Click Add Tree. SlickEdit displays the Add Tree dialog. Ensure that the File types is *.cs. Navigate to the src directory in the Spring.NET distribution. Click OK. SlickEdit adds the source files and tags them in the tag database. Click Done.

You can verify that Context Tagging is working for the Spring.NET library now by opening the Preview tool window when your cursor is on a symbol from the library, such as AdoTemplate.

The C/C++ Preprocessor


C/C++ suffers from considerable extra complexity in tagging because of the preprocessor. The language is designed for the preprocessor to translate the source file before compilation, and the possible effects of translation are virtually unlimited. SlickEdit needs to parse the code as closely as possible to how the compiler parses it, in order to generate accurate tagging information. Here are some examples of common preprocessing constructs that can all prevent tagging from working correctly:
class MYDLLEXPORT MyClass { ... } void funcName PROTO(args); BEGIN_MY_NAMESPACE USING_MY_NAMESPACE(my.ns) MY_STD_CLASS_FUNCTIONS(MyClass)

104

Chapter 5: Context Tagging


You can help SlickEdit parse source files accurately by specifying some preprocessor information. To access C/C++ Preprocessing options, follow these steps:

1. 2. 3. 4. 5.

Open the Extension Options dialog (Tools Options File Extension Setup). Select extension cpp. Click C/C++ Options. SlickEdit shows the C/C++ Formatting Options dialog. Click the Other tab. Click C/C++ Preprocessing. SlickEdit displays the C/C++ Preprocessing dialog.

For more information about C/C++ Preprocessing setup, see the online Help.

Troubleshooting Tagging
The many tagging-related features presented in this chapter all depend on an accurate tag database in order to work correctly. Several conditions can result in the tag database being inaccurate, from invalid code to incorrect configuration. This section contains a checklist with some tips you can use when trying to diagnose tagging problems. These tips are adapted from a troubleshooting checklist provided by Dennis Brueni of SlickEdit.

Go to Definition Doesnt Work


Use these tips if the push-tag (Ctrl+dot) command doesnt work. There are two basic cases: An unqualified symbol x. A qualified symbol expr.x, expr->x, or expr::x.

Case 1: An Unqualified Symbol


Suppose you have an unqualified symbol x, and Go to Definition (push-tag, Ctrl+dot) doesnt work for it.

1.

Where is x defined or declared? Is it a local variable or function parameter? Does it show up if you invoke list-symbols (Alt+dot)? If not, look at its definition. Is it correct (would the code compile)? In C/C++, is it declared using preprocessing? If yes, see Solution A below. Is it in the same file? Does the symbol show up in the Defs tool window? (You may have to turn off filtering options.) Is the symbol information correct? (Check the symbols name, class scope, and protection flags.) If not, look at its definition. Is it correct? (Would the code compile?) In C/C++, is it declared using preprocessing? If yes, see Solution A below. Is it in a different file? Is that file tagged? Is it in your workspace? Is it in an extensionspecific tag file? If not, see Solution B below.

105

Part II: Using SlickEdit


2.
Go to the file and line where x is defined or declared. Does the source file come up in the correct source language mode? Is this an extensionless C/C++ header file? If yes, see Solution C below. Does this file have an unrecognized file extension (like .hhh)? If yes, see Solution D below. Does x show up in the Defs tool window? (You may have to turn off filtering options.) Is the symbol information correct? (Check the symbols name, class scope, and protection flags.) If not, look at its definition. Is it correct? (Would the code compile?) In C/C++, is it declared using preprocessing? If yes, see Solution A below. Should the symbol be visible from the scope you were in? (Maybe the symbol is private, or needs to be imported?) If x shows up correctly in the Defs tool window, but Go to Definition was failing, make sure the tag file is up to date. See Solution E below.

Case 2: A Qualified Symbol


Suppose you have a qualified symbol such as expr.x, expr->x, or expr::x, and Go to Definition (push-tag, Ctrl+dot) doesnt work for it.

1. 2.

Try list-symbols (Alt+dot). Does a list of items show up? Is it the correct list of items? Is it the correct class? Is x in the list? If not, do you get an error message in the message bar? Does the error message help you figure out the problem? Move your cursor to the left of the member access operator, and invoke push-tag (Ctrl+dot) to go to the definition. Does it take you to the correct symbol? Is the symbol tagged correctly? (Check the symbols name, class scope, and protection flags.) If not, follow the guidelines for Go to Definition to determine why you cant jump to the last symbol in expr. If yes, then look at the type of the symbol. Try to jump to the definition of the symbols type using push-tag (Ctrl+dot). Does it take you to the correct symbol? Is the symbol tagged correctly? (Check the symbols name, class scope, and protection flags.) Is the type name a typedef? Can you navigate to the typedefd type?

3.

Evaluate expr to determine if it is recognized correctly. For a simple example: Assume expr is a local variable of type MyClass. Follow the guidelines for Go to Definition to determine if expr is correctly tagged. Follow the guidelines again to determine if MyClass is correctly tagged. For longer prefix expressions such as a[i].getIterator()->currentItem()->x, you may need to follow this procedure iteratively to determine where the missing link is.

4.

Assuming that youve found the actual type of expr by now: Is x correctly seen as a member of the type? Follow the procedure in Case 1, Step 2 to verify if the symbol is tagged correctly.

106

Chapter 5: Context Tagging

Go to Reference Doesnt Work


Use these steps if the push-ref (Ctrl+slash) command doesnt work.

1. 2.

Does Go to Definition (Ctrl+dot) work? Follow the Go to Definition procedure to determine that the symbol you are searching for references to is correctly tagged itself. Are references missing? Are all the files you are expecting to find references in tagged correctly? (See above.) Is the tag file they are in built with cross-referencing enabled? Put your cursor on a reference that is skipped. Go to Definition (push-tag) should take you to the definition of the symbol you are looking for. If not, this is why the reference was skipped. Follow the Go to Definition debugging procedure.

3.

Are there too many references found? Are the references displayed with a ? icon? This indicates that SlickEdit was unsure about the reference. Put your cursor on an extra reference. Follow the Go to Definition debugging procedure. When symbol information is incomplete, References falls back on a philosophy that it is better to show too many items than miss items. This means that it will only eliminate an occurrence of the symbol if it can prove that it is another symbol. Otherwise, it is regarded as a correct reference or a miscellaneous reference.

Auto-List Members Doesnt Work


Use these steps if the list-symbols (Alt+dot) command doesnt work. See Case 2 of the Go to Definition debugging procedure in order to determine if the prefix expression (the expression before the member access operator) is correctly recognized.

Auto-Parameter Information Doesnt Work


Use these steps if the function-argument-help (Alt+comma) doesnt work.

1. 2.

Does Go to Definition (push-tag, Ctrl+dot) work on the function name? Follow the Go to Definition procedure to determine that the function about which you are looking for parameter information is correctly tagged itself. Is the incorrect prototype displayed? Try hitting Alt+comma again to cycle to the next prototype. If there is only one prototype, make sure your tag file is up to date. See Solution E below.

Solution A: Define C/C++ Preprocessing


The symbol needs C/C++ preprocessing to define it correctly. Add the preprocessing definitions:

1. 2.

Open the Extension Options dialog (Tools Options File Extension Setup). Select extension cpp.

107

Part II: Using SlickEdit


3. 4. 5. 6. 7. 8. 9.
Click C/C++ Options. SlickEdit shows the C/C++ Formatting Options dialog. Click the Other tab. Click C/C++ Preprocessing. SlickEdit displays the C/C++ Preprocessing dialog. Add your #define using this dialog. Let SlickEdit rebuild your workspace tag file when you are done. Click OK to close the C/C++ Preprocessing dialog. Click OK to close the C/C++ Formatting Options dialog. Click OK to close the Extension Options dialog.

For more information about C/C++ Preprocessing setup, see the online Help.

Solution B: Add Symbol to Tag File


The symbol is not in the tag database. Add the file where the symbol is defined to the workspace:

1. 2. 3. 4.

Invoke project-edit (Project Project Properties). SlickEdit displays the Project Properties dialog. Select the Files tab. Use Add Files, Add Tree, or Add Wildcard as appropriate to add the file to the workspace. Click OK when done to close the Project Properties dialog.

If the file is part of a third-party library of files, you might want to create a library project for them and add that to your workspace. If the file is part of a large library of files that you use in all your projects, you may want to create a global tag file.

Solution C: Configure C/C++ Extensionless Header Files


The symbol is defined in an extensionless header file, and SlickEdit didnt recognize or treat the file correctly. Configure the names of the extensionless header files in your libraries:

1. 2. 3. 4. 5. 6. 7. 8. 108

Open the Extension Options dialog (Tools Options File Extension Setup). Select extension cpp. Click C/C++ Options. SlickEdit shows the C/C++ Formatting Options dialog. Click the Other tab. Verify the Extensionless C++ File Path Regular Expression. The file/path where your files are needs to match this expression. Click Extensionless C++ Files. SlickEdit displays the Extensionless C++ Files dialog. Add the names of your extensionless header files. Click OK to close the Extensionless C++ Files dialog.

Chapter 5: Context Tagging


9. 10.
Click OK to close the C/C++ Formatting Options dialog. Click OK to close the Extension Options dialog.

See Chapter 9 and the online Help for more information about extensionless header files. Close and reopen the file, and it should come up as C/C++ now. You may have to rebuild your tag file after doing this step.

Solution D: Create a File Extension Alias


The file extension is not recognized for the correct language. Add a new extension for the language:

1. 2. 3. 4. 5. 6.

Open the Extension Options dialog (Tools Options File Extension Setup). Click New. SlickEdit displays the New Extension dialog. Enter the file extension of the file you need to add (without the dot). Select the language/extension to refer to (e.g., cpp). Click OK to close the New Extension dialog. Click OK to close the Extension Options dialog.

Close and reopen the file, and it should come up in the correct language mode now. You may have to rebuild your tag file after doing this step.

Solution E: Rebuild Your Tag File(s)


The tag database is out of date. Rebuild the workspace tag file:

1. 2. 3. 4. 5. 6.

Invoke gui-make-tags (Tools Tag Files). SlickEdit displays the Context Tagging Tag Files dialog. Select your workspace tag file. Click Rebuild Tag File. SlickEdit displays the Rebuild Tag File confirmation dialog. Turn off Retag modified files only. Click OK. SlickEdit rebuilds the tag file. Click Done to close the Context Tagging Tag Files dialog.

Performance Tuning
The Context Tagging engine is designed to work as well as possible for typical projects. As with all things in SlickEdit, it is highly configurable, and if you find that tagging features are not working for your project, or arent working fast enough, you can fine-tune several parameters to improve performance. In this section, we give an overview of some common performance tuning options. However, unless your projects are exceptionally large or unusual, you probably wont need to do any performance tuning. SlickEdits default configuration works just fine for most projects, even some of a substantial size.

109

Part II: Using SlickEdit


If you do need to do some tuning, the tips here might help. Otherwise, you may need to contact SlickEdit support for specific suggestions relating to your environment. Some of the things that can affect the performance of Context Tagging are: Very large projects The more symbols you have, the more work for the tagging engine. Weve seen in this chapter some approaches you can use to tag files that dont change frequently offline, so that they dont slow down the editor while you are working with it. Depending on the size of the active files in your projects, you may need to adjust the amount of memory SlickEdit uses for tagging them. Many symbols sharing the same name SlickEdit indexes the tag database with the symbols name. In order to find a particular symbol, SlickEdit needs to scan through all the symbols with the same name. For some operations, this can be prohibitive if you have many symbols with the same name. For example, in some C++ projects, every class has an init() method. In Java projects, many classes may provide an override of toString(). If you are working with symbols for which there are many occurrences with the same name, you may want to tweak the way SlickEdit treats these.

You can configure the Context Tagging engine in the Context Tagging Options dialog (Tools Options Tagging Options). The dialog is shown in Figure 5-28.

Figure 5-28

Tuning Maximums
The Maximums section lists the maximum number of items found or listed in different categories. Most well-designed programs should not have more than 1,000 members in a single class or structure. However, if you are working with a complex library with a deep inheritance structure, for example, you may find that some subclasses do, in fact, exceed this limit. When this happens, you will not see all members listed in tool windows. To fix this, you can increase these parameters as needed.

110

Chapter 5: Context Tagging

Tag Cache Size


The Tag file cache size determines how much tagging information SlickEdit can hold in memory. The default is currently 64 MB, and this default has been changed several times over the years, as the typical developers machine has grown in capacity. Depending on your project size and the RAM in your machine, you may want to fine-tune this parameter. If you have 2 GB and dont run many applications other than SlickEdit, you may be happy to set this value to 256 MB or 512 MB. If you have less RAM or need to run many applications besides SlickEdit, you need to be careful not to make the setting too high. Otherwise, it may make SlickEdits memory footprint too large and cause memory swapping, which will slow down your system rather than speed it up. You can use the Task Manager in Windows to get an idea of the memory used by different applications and whether you can afford to have SlickEdit use more. You can get an idea of how large your tag cache should be to fit your tag database in memory by looking at the size of the tag file itself. For example, the GNU/Linux kernel source (version 2.6.20) includes about 9,000 .c files totaling 5.7 million lines and 8,500 .h files totaling 1.3 million lines. A tag database for it is about 120 MB.

References
If you are working on a project in which you have many symbols sharing the same name, you may find that the performance of push-ref and the References tool window are not acceptable. You can change a couple of parameters to improve the performance of References. Normally, when you use the References tool window to find references for a symbol, SlickEdit updates the window in two steps: First it uses the tag database to find all files that contain a symbol with the given name. Then it scans each file to determine whether the file truly contains references to that particular symbol, or merely to another synonymous symbol. For example, many C++ classes may contain a method named init(), but References should refer only to occurrences in one specific class (and its subclasses). With this default behavior, files not containing true references are removed from the list after they are scanned, and the remaining files are expanded to show the references. If you check the Find references incrementally option, SlickEdit displays files without expanding them and defers scanning until you expand the node for a file. The advantage of this is that there is far less file scanning required to initialize the window. The down side is that you may get files that dont really contain the symbol youre looking for.

Complex Code
Some kinds of code make a lot of work for the tagging engine. If you have a large (or extremely difficult) code base and are experiencing delays like this, you can try turning off the following items in the Context Tagging tab of the Extension Options dialog: Auto-list compatible values. Auto-list compatible parameters.

In this case, SlickEdit is trying to use the tag database information to obtain context-sensitive static-type information about the current object in your source code. This can be difficult in code that makes heavy

111

Part II: Using SlickEdit


use of templates, especially template metaprogramming, or makes heavy use of overloading and/or namespace/package scoping. These two auto-list compatible... features are trying to determine for each variable in the immediate scope whether or not it is (at least loosely) assignment-compatible in the current context. The harder the type compatibility is to calculate, the longer it takes. Turning off the auto versions of these features does not take away the features. You can still invoke them on demand as described above in this chapter. For C#, there is a special consideration. If you turn off Show Comments, you might see some performance improvements, because it will allow SlickEdit to avoid loading the large XML files in which Microsoft packages their .NET library documentation.

Summar y
Context Tagging is vital for many of SlickEdits advanced features. Particularly for languages with statictype information, Context Tagging provides information that SlickEdit can use to help you browse, navigate, and edit your code effectively. Tagging your own source files is easy Just make sure you have a workspace and that all your source files are included in the workspace, either by adding them individually or using appropriate wildcards. Tagging runtime libraries is also important, because it extends SlickEdits features to work with them as well as with your own source code. Depending on whether you want your runtime libraries tagged globally or per project, there are various approaches possible. We reviewed several methods you can use for tagging C/C++, Java, .NET, and dynamic languages. Occasionally you may need to troubleshoot tagging, or tune the performance, although this should only happen if you have a very large or exotic project. Because problems and performance vary enormously between scenarios, a complete description of all options is beyond the scope of this book. Weve provided a few common tips. Tagging enables many of SlickEdits navigational features. For strongly typed languages, you may not need much else in the way of navigation tools, because you can use push-tag and push-ref to navigate around your code a lot of the time. For other kinds of files, such as dynamic languages, SQL, data files, and others, you need more general-purpose navigation tools. In the next chapter, we cover these other navigation tools.

112

Navigation
Large software projects contain thousands of source files. Often those source files are spread over dozens or even hundreds of directories. And those files can contain thousands of lines. You need to be able to open the file you want as quickly as possible. Once you are in the file, you need to be able to navigate quickly to any place in that file. You need to be able to jump from one place to another, then back, perhaps several times. In Chapter 5, we saw how Context Tagging enables several powerful navigation features, along with other things. In particular, push-tag and push-ref are the preferred way to navigate a large base of source code in SlickEdit. There are also other ways of opening files in SlickEdit. Depending on the nature of your project and the way you prefer to work, some methods will suit you better than others. Some methods are obvious, such as File Open. Others are not so obvious but can be far more effective. SlickEdit allows you to open many different files at once. When you have only one or two files open, you can switch between them easily. If you have a dozen or more files open, SlickEdit offers several nice ways to get quickly to the one you want. Most editors support a standard set of navigation commands for getting around inside a file. You have the arrow keys for moving a character or a line at a time. You have keystrokes for moving a word or a page at a time. SlickEdit has a rich set of commands for navigating around the buffer. Its well worth becoming familiar with these commands, because they can save you a lot of time and keystrokes. If you find yourself returning to the same location in a file frequently, a bookmark can save a lot of time. Bookmarks also let you return quickly to where you were editing after jumping to a definition or a reference.

Part II: Using SlickEdit

F inding and Opening F iles


Before you can navigate in a file, you have to open one. When you first use SlickEdit, you may be inclined to use the gui-open command (File Open) to open files. For some situations, this is the most effective way to open a file. But other times, particularly on large projects with many directories, other methods are faster.

Using File Open


Figure 6-1 shows the default Open dialog on Windows.

Figure 6-1

On GNU/Linux, UNIX, and Mac, a different Open dialog is used. Figure 6-2 shows this dialog on GNU/Linux. The dialog is shown with the Advanced button clicked, to show the additional advanced options. Windows users can optionally use a dialog similar to the dialog used on other platforms. On Windows, it is called the Fast Open Dialog, or the Windows 3.1 Style Open Dialog. Figure 6-3 shows this dialog on Windows. As before, the dialog is shown with the Advanced button clicked, so that all the advanced options are shown. Windows users can configure SlickEdit to use the fast Open dialog by selecting the Windows 3.1 style open dialog in the More tab of the General Options dialog (Tools Options General) or by setting the macro variable def_fast_open to 1.

114

Chapter 6: Navigation

Figure 6-2

Figure 6-3

The fast Open dialog can be more effective than the default Windows dialog, because it supports some additional features. The file name combo box lists files recently opened in SlickEdit. Also, you can type a pattern and press Enter to filter the list displayed. This is very useful if you wish to open a set of files

115

Part II: Using SlickEdit


having some pattern in common. You type the pattern, press Enter, and then select the ones you want from the resulting list. You can also use select-all (Ctrl+A) in the list to select all the filtered files. On the other hand, the fast Open dialog on Windows does not allow you to specify the encoding when opening a file, something you can do with the standard Open dialog on Windows. The choice of Open dialog on Windows is mostly a matter of personal preference and depends on your preferred layout for navigating file and directory lists. The main problem with the fast Open dialog on Windows, as shipped with SlickEdit, is that it is too small. The file and directory lists do not show enough entries, and they are not wide enough. Fortunately, SlickEdit allows you to change any supplied dialog, as well as create your own. Chapter 17 shows how to change the fast Open dialog to be larger, as shown in Figure 6-4.

Figure 6-4

Using File and Directory Aliases


File and directory aliases are a great combination with the Open dialog, for files and directories you open frequently. Basically, a file or directory alias is shorthand for a frequently used file or directory. Instead of manually navigating the file tree or typing the full pathname of the file or directory, you type the alias and expand it. Its a very fast way to navigate to a directory or open a given file.

116

Chapter 6: Navigation
Aliases are particularly useful for frequently edited files that are not necessarily part of any project. Examples of such files are: System Configuration Files such as /etc/hosts. On Windows, the hosts file is in C:\WINDOWS\system32\drivers\etc\hosts. You might alias this to hosts. Product Configuration Files such as C:\oraclexe\app\oracle\product\10.2.0\ server\NETWORK\ADMIN\tnsnames.ora. You might alias this to tnsnames. User Configuration Files such as ~/.bashrc. On Windows, the home directory is longer than on UNIX, something like C:\Documents and Settings\jhurst. You might alias your home directory.

You can use a file or directory alias anywhere in SlickEdit where a filename can be entered. See Chapter 11 for more details on file and directory aliases.

Using the edit Command


Sometimes opening a file from the command line can be quicker than invoking the Open dialog. If you know the name of the file and the file is in the working directory, or can be quickly reached by a file or directory alias, you can open it with the command line with very few keystrokes. The edit command (with shorthand just e) is used to open a file from the command line. Because SlickEdit knows that edit expects a filename as a parameter, it can prompt you with completions from matching files in the working directory. Another time you might want to use the edit command is in macros. Your macros can open, navigate, and edit files programmatically using the edit command. The edit command has many options available when called from a macro. See the online Help for more details.

Using Tool Windows


Several of SlickEdits tool windows can be used to open files. The Project tool window allows you to navigate your project structure and open files. This is occasionally useful for browsing and discovering files, such as when you open someone elses project. For your own code, it is not usually a fast way to open files, because it requires too much navigation of different folders. For large projects, its just too hard to arrange and navigate a tree quickly to any file. The Open tool window shows the file tree and lists files in the selected directory. Again, for large projects, this requires too much navigation to be really effective. The Files tool window is a very effective way of opening any file in your project or workspace. The two big advantages of using the Files tool window are: You dont have to navigate directories at all. You can type any part of the files name. You dont have to begin at the start.

117

Part II: Using SlickEdit


To open a file in your project using the Files tool window:

1. 2. 3.

Invoke activate-files-project [Project Open Files from Project or Alt+T, P (WROX)]. The Files tool window appears with the View Files in the Current Project button selected. Type part of the file name. The list of files is filtered to match what you type. You can use * as a wildcard in the name. Use the arrow keys to select a file from the list, and press Enter to open the file.

Figure 6-5 shows the Files tool window in action.

Figure 6-5

You can use * as a wildcard in the Files tool window, but you often dont have to. As shown in Figure 6-5, you can type any part of the name of the file, and all files containing that string in their names are shown. Suppose you have a lot of SQL DDL scripts, where each script is named according to the definition it performs. The scripts might be called:
create_table_account.sql create_table_customer.sql create_table_order.sql (etc) create_view_customer_orders.sql (etc) create_package_customer.sql (etc)

By typing in cust*sql in the Files tool window, you can see all SQL files relating to customers. This is a very effective way to search for and open files in large projects. The View Files in Current Project is the option you will use most often to open files in your project. The Files tool window can also be used with View Files in Current Workspace to expand the search to include all projects in the workspace. You can switch among modes using the buttons at the top of the tool window. Alternatively, if you know what you are after and prefer to use the keyboard, invoke the tool window in workspace mode using activate-files-workspace [Project Open Files from Workspace or Alt+T, W (WROX)].

118

Chapter 6: Navigation
The main limitation of the Files tool window is that you can only use it to open files that are in your project or workspace. You cant use it to open arbitrary files. But when you are working on a project that has been set up properly, the Files tool window is usually the fastest way to open a file.

Using the File Manager


SlickEdits built-in File Manager provides another way to navigate directories and open files. See Chapter 15 for more information on using the File Manager.

Navigating to Header Files


C and C++ header files are a very familiar part of the life of programmers working in those languages. The top of virtually every source file contains several #include directives. Navigating to those header files is so common that SlickEdit provides a command to do just that. To navigate to a header file for which you have an #include directive:

1. 2.

Place the cursor anywhere on the line containing the #include directive. Invoke cursor-error (Alt+1). SlickEdit opens the file.

As you might guess from the name of this command, its use is not restricted to opening header files, although it is particularly good at that. The same command is used to jump to compiler errors. You can also use the cursor-error command to open files whose names are in your source files for other reasons. For example, you might have a master database script, which calls separate other scripts for creating each table and index. It might look like this:
START create_table_account.sql; START create_table_customer.sql; START create_table_order.sql; -- (etc) START create_view_customer_orders.sql; -- (etc) START create_package_customer.sql; -- (etc)

If you have this script loaded into your editor and the other scripts are in the working directory, you can open them by placing the cursor on the appropriate line and invoking cursor-error.

Moving Around
SlickEdit provides many basic commands for moving around. By mastering these commands and their key bindings, you can get to where you want to be quickly and with the least number of keystrokes.

119

Part II: Using SlickEdit

Navigating in the buffer


You can use several commands for moving around the buffer. Table 6-1 shows the basic navigation commands. We include basic arrow key commands like cursor-up in the table because although you usually invoke them by pressing the arrow keys, you can use the commands by name in macros.

Table 6-1
Command
cursor-up cursor-down cursor-left cursor-right prev-word next-word wrox-prev-word

Key Up arrow Down arrow Left arrow Right arrow Alt+Left (WROX) Alt+Right (WROX) Ctrl+Left (WROX)

Description Move the cursor up. Move the cursor down. Move the cursor left. Move the cursor right. Move the cursor left one word. Move the cursor right one word. Move the cursor left one word (alternative). Move the cursor right one word (alternative). Move to previous function or class definition. Move to next function or class definition. Move up one page. Move down one page. Move the cursor to the top of the window. Move the cursor to the bottom of the window. Move the cursor to the top of the buffer. Move the cursor to the bottom of the buffer. Move the cursor to the matching brace, parenthesis, etc. Move to next higher-level block or definition.

wrox-next-word

Ctrl+Right (WROX)

prev-tag

Ctrl+Up

next-tag page-up page-down top-of-window bottom-of-window top-of-buffer bottom-of-buffer find-matching-paren

Ctrl+Down PgUp PgDn Ctrl+PgUp Ctrl+PgDn Ctrl+Home Ctrl+End Ctrl+]

goto-parent

(none)

120

Chapter 6: Navigation
Several of these commands deserve further explanation. By default, the top-of-buffer command moves the cursor to the first column of the first line, and the bottom-of-buffer command moves it to the last position of the last line. You can change this behavior to preserve the column on the top and bottom by selecting Preserve column on top/bottom on the More tab of the General Options dialog (Tools Options General), or by setting the macro variable def_top_bottom_style to 1. Often you might use top-of-buffer to jump to the top of a file to check a definition. Then you can use undo to return to the point where you were editing. Sometimes you might change something at the top of the file, such as a header comment, an #include directive, or a Java import statement. In such a case, you cannot use undo to go back to where you were without undoing your changes. For this reason, as of SlickEdit 2007, there is an optional behavior for top-of-buffer and bottom-of-buffer to make them push a bookmark before moving the cursor. Then, you can pop the bookmark to return, even if you have done edits in between. This behavior can be turned on by setting the macro variable def_top_bottom_ push_bookmark to 1. Pushing and popping bookmarks is discussed further below in this chapter. You might have noticed that there are two sets of commands in Table 6-1 for moving to the previous or next word: prev-word/next-word and wrox-prev-word/wrox-next-word. There is a reason for this. The SlickEdit default commands prev-word and next-word navigate by words as defined by the current source language. Also, prev-word moves to the beginning of the previous word, while next-word by default navigates to the end of the next word. If you prefer, you can change the behavior of next-word by choosing Next word style as Begin or End on the More tab of the General Options dialog (Tools Options General), or by setting the macro variable def_next_word_style to B for Begin and E for End. However, it turns out to be useful to have it set to End, the default setting. The WROX commands wrox-prev-word and wrox-next-word work slightly differently. Firstly, they move between words that are delimited by white space. Their definition of a word has nothing to do with the source language of the file only white space matters. Secondly, they always move to the beginnings of words, whether moving backward or forward. The wrox-prev-word and wrox-next-word commands behave more like Ctrl+Left and Ctrl+Right in most word processing programs. Suppose you have some code like this:
for (i=0; i<size-1; i++) { sum += arr[i]; }

If we start with the cursor on for and invoke next-word repeatedly, the cursor will move through the positions shown in Figure 6-6.
1 2 3 4 5 6 7

9 10

Figure 6-6

121

Part II: Using SlickEdit


If we use wrox-next-word instead, the cursor will move through the positions shown in Figure 6-7.
1 2 3 4

6 7

Figure 6-7

The point is that both of these schemes are useful at different times. SlickEdits next-word is good for getting to specific identifiers inside expressions with no spaces in them, such as i<size-1. The End style for next-word is useful for recording and playing back macros because with it you have a reliable way of getting to the beginning or the ending of an identifier something that is frequently needed when recording a macro. On the other hand, wrox-next-word is quicker when you want to skip over expressions such as i<size-1, and additionally is useful if you do want to get to punctuation characters such as { and operators such as += in the example above. I find that I use wrox-next-word most often, but also use SlickEdits next-word a lot too. The following listing shows the source code for wrox-prev-word and wrox-next-word:
/** * Moves to beginning of next whitespace-delimited word. * This command is an alternative to SlickEdits next_word command. * Its useful to have them both mapped, since they work * differently but are both useful. * * @return typeless */ _command void wrox_next_whitespace_word() name_info(,VSARG2_READ_ONLY|VSARG2_TEXT_BOX|VSARG2_REQUIRES_EDITORCTL) { init_command_op(); _str current_char = get_text(); if (current_char != && current_char != \t && current_char != \n) { search([ \t\n]|$, @U<); } search([^ \t\n], @U<); retrieve_command_results(); } /** * Moves to beginning of previous whitespace-delimited word. * This command is an alternative to SlickEdits prev_word command. * Its useful to have them both mapped, since they work * differently but are both useful. * * @return typeless */ _command void wrox_prev_whitespace_word() name_info(,VSARG2_READ_ONLY|VSARG2_TEXT_BOX|VSARG2_REQUIRES_EDITORCTL) { init_command_op(); if (p_col > 1) { left();

122

Chapter 6: Navigation
} else { up(); end_line(); } _str current_char = get_text(); if (current_char == || current_char == \t || p_col == 1) { search([^ \t\n], -@U<); } search([ \t\n]|^, -@U>); retrieve_command_results(); } // remap the standard SlickEdit prev-word/next-word to Alt-Left/Alt-Right, // and the WROX ones to Ctrl-Left/Ctrl-Right. defeventtab default_keys def C-RIGHT= wrox_next_word def A-RIGHT= next_word def C-LEFT= wrox_prev_word def A-LEFT= prev_word

Positioning the Window


Often you have the cursor where you want it, but you cannot see everything you want to see on the screen. Some important information may be just off the top or the bottom of the screen. Or, you may have lines that are too long for the screen, and you want to see some data to the left or the right. In these cases, you could move the cursor to cause the window to reposition, but its often more convenient to cause the window to move while leaving the cursor where it is. Table 6-2 shows several commands that reposition the window.

Table 6-2
Command
line-to-top

Key Alt+PgUp (WROX)

Description Reposition the window so that the current line is at top. Reposition the window so that the current line is at bottom. Reposition the window so that the current line is in the middle. Scroll buffer up one line. Scroll buffer down one line. Scroll buffer left one character. Scroll buffer right one character.

line-to-bottom

Alt+PgDn (WROX)

center-line

Alt+Home (WROX)

scroll-up scroll-down scroll-left scroll-right

Shift+F1 (WROX) Shift+F2 (WROX) Shift+F3 (WROX) Shift+F4 (WROX)

None of these commands has key bindings in the CUA emulation; thus its easy to miss them.

123

Part II: Using SlickEdit

Navigating to a Line, Column, or Byte Offset


You can use commands on the command line to navigate to an absolute or relative position in the file. You can navigate to a precise line, column or byte offset. Table 6-3 shows the commands for precise navigation.

Table 6-3
Command
goto-line n n cursor-up n -n cursor-down n +n goto-col n cursor-left n cursor-right n seek n seek n seek +n

Description Go to line n. Go to line n (shorthand form). Go up n lines. Go up n lines (shorthand form). Go down n lines. Go down n lines (shorthand form). Go to column n. Go left n columns. Go right n columns. Go to character n in file. Go backward n characters. Go forward n characters.

You can also use the seek command with no arguments to show the current character offset in the file in the message line. An example of this is shown in Figure 6-8, where the cursor is at character 270 in the file (hex 0x10E).

Figure 6-8

The seek command works with characters, not bytes. The behavior for some files depends on the encoding used to open the file. For an ASCII file, each character corresponds exactly to a byte. For a Unicode file, a character can correspond to more than one byte. Also, there may be a byte order mark (BOM) of two or more bytes at the beginning of the file. If a Unicode file is opened with the correct encoding, seek works with Unicode characters. If a Unicode file is opened with a binary encoding, seek effectively works with bytes. We cover more details about file encodings in Chapter 12.

124

Chapter 6: Navigation

Navigating among Buffers


When you have more than one file loaded, you need to be able to switch between them effectively. The most obvious way to move among files is to click them in the File Tabs tool window. But that breaks our number one rule of using SlickEdit: Avoid the Mouse! Clicking tabs is a very slow way to switch among buffers. If there are only two or three files loaded, it can be sufficient to cycle through them in turn with a keyboard command. If there are more than two or three files, you need a faster way to get to the buffer you want. Table 6-4 shows commands for switching among buffers.

Table 6-4
Command
next-buffer prev-buffer next-buff-tab prev-buff-tab next-window prev-window list-buffers

Key Ctrl+N Ctrl+P (none) (none) Ctrl+Tab, Ctrl+F6 Ctrl+Shift+Tab, Ctrl+Shift+F6 Ctrl+Shift+B

Description Move to the next buffer. Move to the previous buffer. Move to the next buffer tab. Move to the previous buffer tab. Move to the next window. Move to the previous window. List the buffers so you can choose.

Recall from Chapter 3 that buffers are not the same as windows, and relationships among them are controlled by configuration settings. Thus, whats the difference between all of these commands? It has to do with the order in which the buffers or windows are traversed. The next-buff-tab command simply traverses the buffers in alphabetical order. That is the same order in which the buffers appear in the File Tabs tool window. The prev-buff-tab command traverses the buffers in the reverse order. These commands are not particularly useful normally. The next-buffer command follows the order of the buffer ring. When you load files into buffers, the buffers form a ring. The buffers have a fixed order in the ring. When you invoke next-buffer, you go to the next buffer in the ring. When you reach the last buffer in the ring, the command cycles back to the first buffer. Similarly, prev-buffer takes you to the previous buffer in the ring, until you get to the first buffer, after which it cycles to the last buffer. The order of the buffers in the ring is determined by how files are loaded. When you load a file, it is inserted into the ring after the current buffer. This can be illustrated by an example:

1. 2.

We edit file A. The ring now contains only file A, and prev-buffer and next-buffer do nothing. We edit file C. The ring is now A, C.

125

Part II: Using SlickEdit


3. 4. 5. 6. 7.
We edit file E. The ring is now A, C, E. We invoke next-buffer. This takes us to buffer A. We edit file B. The ring is now A, B, C, E because we opened B while A was the current buffer. We invoke next-buffer. This takes us to buffer C. We edit file D. The ring is now A, B, C, D, E.

In this example, I deliberately loaded the files in such a way as to result with them in the ring in alphabetical order. Its important to realize that the ring itself does not sort them alphabetically, but by which position in the ring each file is loaded into. The prev-buffer and next-buffer commands are nice for getting around your files in a fixed order. If you take care in the order you load files, you can keep track of where they are in the ring and navigate to them quickly using prev-buffer and next-buffer. However, its often inconvenient to have to keep track of the order of the files as they are loaded, especially if you are working with a lot of different files, and opening and closing them a lot. In these cases, the window commands work better. With the default configuration, the next-window command takes you through the windows in the order of most recent use. The command is bound to Ctrl+Tab in CUA, and behaves like Ctrl+Tab in many other Windows applications. Its also similar to the way Alt+Tab works to switch among applications in Windows and other operating systems. Similarly, prev-window goes through windows in the order of least recent use. The next-window command is very convenient if you have a lot of files open and are switching among just two or three of them. You can toggle between two windows with Ctrl+Tab, and toggle among more windows by holding Ctrl and pressing Tab more than once. The behavior of next-window and prev-window is controlled by a configuration setting found on the More tab of the General Options dialog (Tools Options General). There is an unlabeled combo box containing these options: No window reordering. Smart next window. Reorder windows.

(These configuration settings do not have a corresponding macro variable.) The default setting is Smart next window, which is the behavior just described. With the No window reordering setting, the next-window command cycles through the windows in the reverse of the order in which they are created. This is similar to, but not the same as, the order of buffers in the ring. With the Reorder windows setting, when you activate a window, SlickEdit places it after the current window in the window list. The prev-window and next-window commands do not reorder the window list.

126

Chapter 6: Navigation
You can also select among windows using the Window menu. The Window menu displays the windows in window order. The list-buffers command invokes the Files tool window, in the View Open Files mode. This is the same tool window you can use to open files from the project or workspace. When used in View Open Files mode, it allows you to navigate to, close, or save open files. The list-buffers command is bound to Ctrl+Shift+B in CUA. Alternatively, you can use the activate-files-files command, which is bound to the Alt+T, L sequence in the WROX extension. (The Files tool window is new in SlickEdit 2007 and replaces the old List Buffers dialog. The CUA emulation doesnt include key bindings for activating tool windows.) The Files tool window is useful if you have many files open, because it allows you to navigate to a particular one relatively quickly. Its also a handy way to review just what files you actually do have open, because the File Tabs tool window cannot show a large number of files effectively.

Bookmar ks
SlickEdits bookmarks are a powerful way of returning to a previous location in a source file. There are two types of bookmarks. We have already seen pushed bookmarks in Chapter 5, where we used them with push-tag and push-ref. The other kind of bookmark is the named bookmark.

Pushed Bookmarks
Pushed bookmarks are invaluable for jumping to and returning from definitions and references. They can also be useful in other situations. Sometimes you may want to push a bookmark yourself before jumping to another location. To push a bookmark explicitly, use push-bookmark (WROX: Ctrl+semicolon). Table 6-5 lists the important commands for working with pushed bookmarks.

Table 6-5
Command
push-bookmark push-tag push-ref pop-bookmark pop-all-bookmarks

Key Ctrl+semicolon (WROX) Ctrl+dot Ctrl+slash Ctrl+comma (none)

Description Push a bookmark explicitly. Push a bookmark and go to definition. Push a bookmark and go to reference. Pop last bookmark. Pop all bookmarks.

Note that when you push a bookmark using push-bookmark, it uses the same bookmark stack as push-tag and push-ref.

127

Part II: Using SlickEdit


Pushed bookmarks are also quite useful in macros. If you want a macro to be able to navigate around the file and do something, then return to where the user was editing, use a pushed bookmark. An example might be a macro that adds a header to a file. Be careful to ensure that your macro pops all the bookmarks that it pushes, regardless of how it returns.

Named Bookmarks
Pushed bookmarks are use once. Once you pop the bookmark, its gone. If you want to be able to return to a location many times, use a named bookmark instead. Named bookmarks are also referred to as set bookmarks. Table 6-6 shows some commands that work with named bookmarks.

Table 6-6
Command
set-bookmark delete-bookmark goto-bookmark toggle-bookmark

Menu or Key Search Set bookmark (none) Search Go to bookmark Search Toggle bookmark or Ctrl+Shift+J Search Bookmarks or Ctrl+Shift+N Search Next bookmark Search Previous bookmark Ctrl+Shift+number key (WROX) Ctrl+number key (WROX) (none)

Description Sets a named bookmark. Deletes current or named bookmark. Go to a named bookmark. Toggle a named bookmark on the current line. Show the Bookmarks tool window.

activate-bookmarks

next-bookmark prev-bookmark alt-bookmark

Go to next named bookmark. Go to previous named bookmark. Set a quick bookmark.

alt-gtbookmark clear-bookmarks

Go to a quick bookmark. Clear named bookmarks.

There are three ways to use named bookmarks: You can give a bookmark a meaningful name that you choose, using set-bookmark. This is the most effective option for bookmarks you want to use for a long time. You can have an automatically generated name, when you use toggle-bookmark. SlickEdit generates a name using the file or symbol name and the line number. You can use a key binding for a name, when you use alt-bookmark. The bookmark is given the name of the key used to set it. See below.

128

Chapter 6: Navigation
You can delete the named bookmark on the current line with the delete-bookmark command. Alternatively, you can use delete-bookmark with a name argument to delete a specific named bookmark. The alt-bookmark command is used to create a quick temporary bookmark with a keyboard shortcut. In the CUA emulation, the alt-bookmark command is bound to Ctrl+0 through Ctrl+9, and the alt-gtbookmark command is bound to Ctrl+Shift+0 through Ctrl+Shift+9. Because jumping to a bookmark is usually done more often than setting a bookmark, the WROX emulation reverses the key bindings, to make it easier to jump to bookmarks.

Configuring Bookmarks
There are several configuration options controlling bookmarks. They can be found in the Search tab of the General Options dialog (Tools Options General), in the group titled Bookmarks. The search configuration dialog is shown in Figure 6-9, with the default settings for bookmarks.

Figure 6-9

Select Use workspace bookmarks to make named bookmarks local to your workspace, rather than global. When Show set bookmarks is checked, named bookmarks show as a green icon in the margin. When Show pushed bookmarks is checked, pushed bookmarks show as a blue icon in the margin. The Close deletes pushed bookmarks setting causes pushed bookmarks to be dropped when you close the files containing them. This can be a helpful setting if you like to return from a reference lookup by

129

Part II: Using SlickEdit


closing the file. Alternatively, if you have turned on Automatically close visited files in the General tab of the General Options dialog (Tools Options General), a visited file will be closed when you use pop-bookmark to return from a reference. Finally, the Max stack depth setting controls how many pushed bookmarks SlickEdit remembers.

Summar y
In this chapter, we tried to do justice to SlickEdits great set of features for navigation. We saw several ways to open files with a minimum of navigation and typing required. We covered many of SlickEdits commands and their key bindings for moving around in the buffer, and we saw effective ways to switch buffers quickly, even if many files are open. We looked at bookmarks, another powerful navigation tool. In the next chapter, we continue the theme of navigation by looking in detail at SlickEdits search-andreplace capabilities.

130

Search and Replace


A particularly important tool for navigation is searching. SlickEdit has a rich set of searching features. These range from a simple search for a string, up through sophisticated searches using regular expressions and context-sensitive criteria. You can use selective display to filter which lines of the buffer are displayed on the screen, based on search conditions. You can selectively hide sections such as comments or arbitrary code blocks. You can also search across many files. Along with searching, SlickEdit also supports replacing, with virtually the same set of features. Regular expression replacements are a particularly powerful way to edit files.

Keyboard Searching
Table 7-1 is a summary of search and replace commands with keyboard shortcuts. We cover command-line searching below in this chapter.

Table 7-1
Command
quick-search

Menu or Key Ctrl+F3 (WROX)

Description Quick search for selection or word at cursor. Quick search backward for selection or word at cursor. Incremental search forward. Incremental search backward. continued

quick-reverse-search

Ctrl+Shift+F3 (WROX)

i-search reverse-i-search

Ctrl+I Ctrl+Shift+I

Part II: Using SlickEdit


Table 7-1 (continued)
Command
gui-find find-in-files gui-replace replace-in-files find-next find-prev

Menu or Key Ctrl+F Ctrl+Shift+F Ctrl+R Ctrl+Shift+R Ctrl+G Ctrl+Shift+G

Description Show Find dialog. Show Find in Files dialog. Show Replace dialog. Show Replace in Files dialog. Find next match. Find previous match.

Terminating a Long Search


Sometimes you start a search in a long file and realize its going to hang your machine for a while. To terminate a long search in SlickEdit, press Ctrl+Alt+Shift.

Quick Search
The fastest way to search for the word at the cursor is to use quick-search (WROX: Ctrl+F3). If you have a normal character selection, that is used for the search. Otherwise, the entire word at the cursor is used. You can also search backward with quick-reverse-search (WROX: Ctrl+Shift+F3). You can use find-next (Ctrl+G) and find-prev (Ctrl+Shift+G) to repeat your quick search after the first match. The find-next and find-prev commands can be used to repeat searches started in different ways. When you invoke them, they display the current search conditions in the message area.

Incremental Search
Incremental search is a quick way to search without having to type too much. To use incremental search:

1.

Invoke i-search (Ctrl+I). SlickEdit prompts you in the command-line area with Exact I-Search, as shown in Figure 7-1.

Figure 7-1

2. 3. 4.

Type the first character of your search expression. SlickEdit advances the cursor to the next match for that character. Type more characters to narrow the search. SlickEdit advances to matching text in the buffer. Use backspace to back up if you make a mistake.

132

Chapter 7: Search and Replace


5. 6.
Use find-next (Ctrl+G) to skip to the next match, if desired, or find-prev (Ctrl+Shift+G) to search backward. Use Escape or a cursor movement key to terminate the search.

The procedure for using reverse-i-search is the same (except you press a different key to start it). SlickEdit remembers your search string until your next search, thus you can continue to use find-next and find-prev after you have terminated the incremental search. In this example, the incremental search was exact, which meant a literal case-sensitive search. Incremental search uses default search options from the Search tab of the General Options dialog (Tools Options General). You can change default options there. You can also change search options and behavior during incremental search by pressing the keys shown in Table 7-2.

Table 7-2
Key Ctrl+C Description Toggles case sensitivity. The key bound to the BRIEF emulation command case_toggle will also toggle the case sensitivity. Toggles searching within mark. Toggles incremental search mode. Quotes the next character typed. Searches in reverse for the next occurrence of the search string. Searches forward for the next occurrence of the search string. Toggles regular expression pattern matching on/off. The key bound to the BRIEF emulation command re_toggle will also toggle regular expression pattern matching. Toggles word searching on/off.

Ctrl+M Ctrl+O Ctrl+Q Ctrl+R Ctrl+S Ctrl+T

Ctrl+W

The F ind and Replace Tool Window


Quick Search and Incremental Search are nice for simple searches. For complex, repeatable searches, use the find command. We will begin by looking at the Find and Replace tool window, and then examine the command-line version of find. The four commands gui-find, find-in-files, gui-replace, and replace-in-files all bring up similar GUI dialogs. Each is actually a separate tab in the Find and Replace tool window. When the tool window is open, you can click the tabs to switch from one function to another.

133

Part II: Using SlickEdit

Using Find
Figure 7-2 shows the Find and Replace tool window, with the Find tab selected.

Figure 7-2

There are many options, but most of them are self-explanatory. We discuss some of the more complex options in the sections below. As always, full details are in the online Help. Enter your search string into the Search for combo box. The combo box remembers previous searches. These can be recalled using the down arrow key. The arrow button to the right of the Search for combo is a helper for building regular expressions. Use the Look in selection box to define the scope of your search. The options are: Current Buffer Searches to the end (or beginning) of the buffer. Current Selection Searches to the end (or beginning) of the selection. Current Procedure Searches to the end (or beginning) of the current procedure. This option is available only in modes where SlickEdit can recognize procedures or functions. All Buffers Searches all open buffers.

Use the Match case and Match whole word options to control the precision of the match. Use one of the regular expression types to specify a search pattern rather than an exact string. Regular expression searches are explained below. Use the Color button to specify a color-syntax scope for your search. The Color Coding Search Options dialog is shown in Figure 7-3. These options correspond to the syntax elements defined by SlickEdits programming language lexers. Lexers are explained further in Chapter 9, and also in Chapter 17. The checkboxes are three-valued, with the three values having these meanings: Checked means Restrict the search to include this element. Unchecked means Exclude this element. Neither checked nor unchecked means This element does not affect the search.

134

Chapter 7: Search and Replace

Figure 7-3

To clarify this a little, consider two typical cases: To search only in comments, check the Comment box, and leave the others in the middle (neither checked nor unchecked) state. To search everywhere except comments, uncheck the Comment box, and leave the others in the middle state.

We give some more examples of color syntax searching when we cover command-line searching below. We also cover regular expression searching and replacing in more detail below.

Using Find in Files


When you want to search in multiple files, invoke find-in-files. This opens the Find in Files tab of the Find and Replace tool window, shown in Figure 7-4.

Figure 7-4

135

Part II: Using SlickEdit


Many of the options in Find in Files are the same as in the regular Find tab. The different options concern which files to search in, and what to do with the results. When you use the Find tab to search within a buffer, SlickEdit navigates in the buffer for each match. Using Find in Files, there are generally many matches in many different files. Therefore, the options from the Find tab concerning cursor positioning and match highlighting do not apply for Find in Files. SlickEdit usually shows Find in Files results in the Search Results tool window, where you can preview them and open selected results as you choose. If you prefer, you can output the results to an editor window by selecting Output to editor window. In this case, a new editor window is created for the search output. The window uses a special mode called grep to provide the same features as the Search Results tool window. Figure 7-5 shows the Search Results tool window, with the output of the search for Auto-Complete.

Figure 7-5

The Search Results buffer is a special kind of editor buffer that supports commands and actions to review the search results and navigate to them. You can press Enter or double-click a file to open that file, or a match to open the file at that line. Its interesting to note that while you cannot invoke command-line commands or the Find tool window on the Search Results buffer itself, you can use incremental search while the focus is in Search Results. The + and bitmaps indicate regions that can be expanded or collapsed. You can click the and + buttons, or invoke plusminus (Ctrl+backslash) to expand or collapse results from particular files. When you do multiple searches with Find in Files, the default behavior is to replace the Search<0> buffer in the Search Results tool window with the new results each time. You can change this by selecting from the choices under the Search Results window. The choices include: Search<0> Search<n> The buffers are already created. <New> Creates a new buffer. <Auto Increment> Cycles through existing search buffers.

These choices allow you to keep results from a given search for as long as you need them. Multiple search results appear as different tabs in the Search Results tool window.

136

Chapter 7: Search and Replace

Using Replace and Replace in Files


The Replace and Replace in Files tabs of the File and Replace tool window are very similar to the Find and Find in Files tabs, and their usage is obvious.

Regular Expressions
One of the more powerful ways of searching or replacing with SlickEdit is to use regular expressions. A regular expression specifies a pattern of text to search for, rather than the exact text. You can use patterns in a conventional way as you might use a search tool such as the UNIX grep command. You can also use them in combination with SlickEdits other search options, such as the ability to limit searches to comments or keywords. Because most programmers are probably familiar with regular expressions, we dont present an entire tutorial on them in this book. Besides, they are a book-sized subject in their own right! If you would like to learn more about regular expressions, a definitive treatment is given in Mastering Regular Expressions by Jeffrey Friedl (3rd edition, 2006, OReilly). SlickEdit supports three variants of regular expressions, described below: UNIX Regular Expressions These are closest to UNIX tools like egrep. SlickEdit Regular Expressions These are unique to SlickEdit and are designed to be more concise for some patterns. Brief Regular Expressions These are based on those in the Brief editor, popular in the DOS days.

These three regular expression languages offer almost exactly the same set of features. Choose the language that suits your background and preference. Table 7-3 lists common regular expression features. Appendix B contains a complete listing of regular expression features for each variant.

Table 7-3
Definition Match beginning of line. Match end of line. Match any character except newline. Maximal match of zero or more occurrences of X. Maximal match of one or more occurrences of X. UNIX
^

SlickEdit
^

Brief
% < $ > ? X\:@ X\:+

. X* X+

? X@ X#

continued

137

Part II: Using SlickEdit


Table 7-3 (continued)
Definition Maximal match of zero or one occurrences of X. Match exactly n1 occurrences of X. Maximal match of at least n1 occurrences of X. Maximal match of at least 0 occurrence but not more than n2 occurrences of X. Maximal match of at least n1 occurrence but not more than n2 occurrences of X. Search fails if expression X is matched. Matches X or Y. Matches subexpression X and specifies a new tagged expression. No more tagged expressions are defined once an explicit tagged expression number is specified as shown below. Matches any one of the characters specified by charset. A hyphen (-) character may be used to specify ranges. Matches any character not specified by charset. A hyphen (-) character may be used to specify ranges. Matches hexadecimal character hh, where 0 hh 0xff. Matches decimal character nnn, where 0 nnn 255. Defines a back reference to tagged expression number d. Specifies cursor position if match is found. Matches newline character sequence. Useful for matching multiline search strings. What this matches depends on whether the buffer is a DOS (ASCII 13,10 or just ASCII 10), UNIX (ASCII 10), Macintosh (ASCII 13), or user-defined ASCII file. Matches carriage return (ASCII 13). Matches tab character. UNIX
X? X{n1} X{n1}? X{n1,} X{,n2}

SlickEdit
X:0,1 X:n1

Brief
X\:0,1 X\:n1 X\:n1? X\:n1, X\:,n2

X:n1, X:0,n2

X{n1,n2}

X:n1,n2

X\:n1,n2

(?!X) X|Y (X)

~X X|Y {X} X|Y {X}

[charset]

[charset]

[charset]

[^charset]

[~charset] [^charset] \xhh

[~charset]

\xhh

\xhh

\dnnn \d

\nnn \gd

\dnnn \d

\c \n

\c \n

\c \n

\r \t

\r \t

\r \t

138

Chapter 7: Search and Replace


Table 7-3 (continued)
Definition Turns on multiline matching. This enhances the match character set, or match any character primitives to support matching end of line characters. For example, \om.+ matches the rest of the buffer. Turns off multiline matching (default). You can still use \n to create regular expressions that match one or more lines. However, expressions like .+ will not match multiple lines. This is much safer and usually faster than using the \om option. Declares character after slash to be literal. Matches predefined expression corresponding to char. See Table 7-4. UNIX
\om

SlickEdit
\om

Brief
\om

\ol

\ol

\ol

\char \:char

\char :char

\char \:char

The \c regular expression feature is particularly useful, and is specific to the context of a text editor. It allows you to control the position of the cursor after a match is found. You may find this option a reason to use a regular expression search, even if you are not otherwise searching for a pattern. The last feature (\:char) in Table 7-3 provides a shorthand for a set of common patterns. The patterns are more fully documented in the online Help, but are summarized in Table 7-4. The \:f and \:p patterns, for searching for a filename part and a path, respectively, are operating-system-specific. Thus if you are running on Windows, \:f will match a Windows-style filename part. Its worth noting that \:f and \:p also match anything that can be a part of a filename. But they dont do paths or files that contain spaces. Many regular expression features use the backslash (\) character. If you type regular expressions into the Find dialog or use them on the command line, you can use the backslash normally. If you use regular expressions with the search() function in a macro, you need to keep in mind that backslashes are interpreted specially in double-quoted strings in Slick-C. Usually, this means you need to escape the backslashes in your Slick-C expressions. For example, the following UNIX-style regular expression matches an ISO date (yyyy-mm-dd):
\:d{4}-\:d{2}-\:d{2}

You can use that expression in the Find dialog. If you are programming a macro and using the search() function, you need to escape the backslashes, like this:
search(\\:d{4}-\\:d{2}-\\:d{2}, U);

Alternatively, use a single-quoted string, like this:


search(\:d{4}-\:d{2}-\:d{2}, U);

We explain more about Slick-C strings in Chapter 16.

139

Part II: Using SlickEdit


Table 7-4
Character
A B C D F H I N P Q V W

Description Matches an alphanumeric character. Matches blanks. Matches an alphabetic character. Matches a digit. Matches a filename part. Matches a hex number. Matches an integer. Matches a floating number. Matches a path. Matches a quoted string. Matches a C variable. Matches a word.

Tagged Expressions
Regular expressions can specify tagged expressions, which can be used to replace or extract parts of the match. For example, using UNIX-style regular expressions again, we could give the above expression as:
(\:d{4})-(\:d{2})-(\:d{2})

In UNIX-style regular expressions, parentheses are used for forming tagged expressions. In this regular expression, there are three tagged expressions, one each for the year, month, and day parts of the ISOformatted date. In replacement strings, matches to tagged expressions are given as a backslash followed by the number of the tagged expression. Thus for this regular expression, the year part would be specifed by \1 in a replacement string, and so on. A replacement string that converts the given ISO-formatted date into USA format (mm/dd/yyyy) would look like this:
\2/\3/\1

In this replacement string, the ordinary slashes are date separators, and the backslashes are for identifying tagged expressions. Tagged expressions are also referred to as match groups or capturing groups.

140

Chapter 7: Search and Replace

Regular Expression Examples


Table 7-5 contains some examples of regular expressions. The examples use the UNIX variant.

Table 7-5
Expression
\:d{4}-\:d{2}-\:d{2} \:d{1,2}/\:d{1,2}/\:d{4}

Description Match an ISO date (yyyy-mm-dd). Match a USA date (mm/dd/yyyy), with months and days being one or two digits. Match a USA date, with grouping expressions to capture the resulting fields. Search for an #include directive using quotes, with a group to capture the #included file. HTML/XML start or end tag, with attributes.

(\:d{1,2})/(\:d{1,2})/(\:d{4})

#include\:b+([^]+)

<(/?(\:c|[0-9]|-|_|:)+)([^>]*)>

Command-Line Search and Replace


The Find tool window provides a powerful and flexible environment for searching and is particularly well suited to complex searches and searches across multiple files and directories. For searching within the current buffer, the find command is just as powerful and often faster. The command-line find supports some options that are not supported by gui-find, and also it sometimes works in a more effective way. Table 7-6 shows the variants of the command-line search, replace, and selective display commands.

Table 7-6
Command
find/expr[/options] /expr[/options] l/expr[/options] replace/exp1/exp2[/options] c/exp1/exp2[/options] all/expr[/options] allnot/expr[/options] show-all

Description Find command. Find command (shorthand form). Find command (alternative shorthand form). Replace command. Replace command (shorthand form). Selective display show matches. Selective display hide matches. Cancel selective display.

141

Part II: Using SlickEdit


The syntax of the command-line find is
find/expr[/options]

where
expr is the string or pattern to search for; and options are the search options.

The command can be shortened to just a slash, and the closing slash is not required if there are no options. The short form of the find command looks like this:
/expr

If you are searching for a string that contains slashes, you can escape them with a backslash. Alternatively, you can use the find command or the shorthand l (letter L, for locate) command with a different delimiter. For example, to search for the date 3/9/2007, we could use either of these commands:
/3\/9\/2007 l|3/9/2007

The second one is easier to understand. The syntax of the command-line replace is:
change /exp1/exp2[/options]

where:
exp1 is the string or pattern to search for; exp2 is the replacement string; and options are the search and replace options.

Once again, the command can be shortened to just c, and the closing slash is not required if there are no options. Thus the short form of the change command looks like this:
c/exp1/exp2[/options]

Just as with the find command, you can use different delimiters with the change command. For example, to change the literal date 3/9/2007 to 2007-03-09, we could use the command:
c|3/9/2007|2007-03-09

142

Chapter 7: Search and Replace

Command-Line Options
The command-line find and change commands have many options. Table 7-7, showing the options, is taken directly from the online documentation. The options are not case-sensitive. Consult the online documentation for more details about these options.

Table 7-7
Option
E I + M < > R U B & @ H # N P W W:P W:PS

Description Exact case. Ignore case. Forward search. Reverse search. Limit search to marked area. If found, place cursor at beginning of word. If found, place cursor at end of word. Interpret search string as a SlickEdit regular expression. Interpret search string as a UNIX regular expression. Interpret string as a Brief regular expression. Interpret string as a wildcard regular expression. No error message if string not found. Search through hidden lines. Highlight matched occurrences with highlight color. Do not interpret the string as a regular expression. Wrap to beginning/end when string not found. Limits search to whole words. Limits search to word prefix. Limits search to strict word prefix. continued

143

Part II: Using SlickEdit


Table 7-7 (continued)
Option
W:S W:SS Y , Cletters

Description Limits search to word suffix. Limits search to strict word suffix. Binary search. Delimiter to separate ambiguous options. Requires the first character of the match to be one of the color coding elements specified by letters. Requires the first character of the match to be not one of the color coding elements specified by letters. Preserve case. Highlight replaced text with modified line color.

Xletters

V $

Some of these options are particularly useful in macro programming. Its often important to specify options explicitly in macros so that the macros operation is not confounded by an unexpected user setting. The < and > options, for example, allow you precise control over cursor placement during a macro execution, regardless of the users default search options. The C and X options specify color coding elements. Table 7-8 shows the letters that can be used.

Table 7-8
Letter
O K N S C P L 1 2

Color Coding Element Other Keyword Number String Comment Preprocessing Line number Symbol 1 Symbol 2

144

Chapter 7: Search and Replace


Table 7-8 (continued)
Letter
3 4 F V

Color Coding Element Symbol 3 Symbol 4 Function color No save line

Command-Line Search Examples


Table 7-9 contains several examples of Search commands using the command line.

Table 7-9
Command
/ERROR/e all/ERROR/e allnot/DEBUG/e /def_ /def_//def_/xc all/def_/xc /_command/ck l|\:d{1,2}/\:d{1,2}/\:d{4 }|u l|\:d{1,2}/\:d{1,2}/\:d{4 }|u> l|\:d{1,2}/\:d{1,2}/\c\:d {4}|u c|(\:d{2})/(\:d{2})/(\:d{ 4})|\3-\1-\2|u

Description Search for ERROR, matching exact case. Show only lines containing ERROR, exact case. Show only lines not containing DEBUG, exact case. Search for next occurrence of def_. Search for previous occurrence of def_. Search for next occurrence of def_, outside comments. Show only lines containing def_, outside comments. Search for _command as a keyword. Search for US style date (mm/dd/yyyy). Search for US style date, place cursor at end. Search for US style date, place cursor at beginning of year. Change US style date to ISO (yyyy-mm-dd) (doesnt handle single-digit days or months). continued

145

Part II: Using SlickEdit


Table 7-9 (continued)
Command
c|;$|\n/|uxc*

Description Change SQL semicolon terminator to a slash on its own line (excludes commented lines). Change line endings DOS to UNIX (includes hidden lines). Change line endings UNIX to DOS (includes hidden lines).

c/\x0d\x0a/\x0a/uh* c/\x0a/\x0d\x0a/uh*

Selective Display
SlickEdits selective display feature is like having grep built into the editor. It allows you to show only certain lines, or to omit certain lines. In some situations, this can make it much easier to focus on what you want to see and edit.

Predefined Selective Display


There are several ways to use selective display. The most straightforward is to use the predefined selective display commands, also available from the View menu. The predefined selective display commands are listed in Table 7-10.

Table 7-10
Command
hide-all-comments hide-code-block hide-selection hide-dotnet-regions show-procs toggle-all-outlining

Menu View Hide All Comments View Hide Code Block View Hide Selection View Hide #region Blocks View Function Headings (none) View Expand/Collapse Block (Ctrl+backslash) View Copy Visible View Show All

Description Hides all comments. Hides block containing cursor. Hides lines containing selected text. Hides .NET #region blocks. Shows only function headings. Toggles selective display of function bodies and comments. Expand or collapse a hidden block.

plusminus

copy-selective-display

Copies visible part of selection to clipboard. Cancels selective display.

show-all

146

Chapter 7: Search and Replace


Most of these are self-explanatory. In some cases, its necessary to invoke more than one command in order to achieve the desired result. For example, show-procs shows JavaDoc comments. Thus, if you really want to see just the function headings, with no comments, you need to invoke show-procs and then hide-all-comments. Most of the commands cannot be combined in this way, however. If you need combinations of selective display, you can use Custom Selective Display, explained below. The toggle-all-outlining command also works well for hiding both comments and function bodies. Figure 7-6 shows selective display after invoking show-procs and hide-all-comments. The + and bitmaps indicate regions you can expand or collapse. As with the Search Results tool window, you can click the and + buttons, or invoke plusminus (Ctrl+backslash) to expand or collapse selective display sections.

Figure 7-6

When you are finished with selective display and wish to see the entire buffer again, invoke show-all. If you wish to copy only the visible lines to the clipboard, you can use copy-selective-display:

1. 2.

Make a selection that includes the lines you wish to copy. Invoke copy-selective-display (View Copy Visible). The visible lines in the selection are copied to the clipboard.

The hide-dotnet-regions command is intended for .NET programming, where Visual Studio inserts foldable regions into the code. There are region markers defined in SlickEdit for the standard Visual Studio comment markers for these regions, depending on the language of the source file. The region markers are shown in Table 7-11. The #region and #endregion markers also work in Slick-C files.

147

Part II: Using SlickEdit


Table 7-11
Language C# C++ C++ VB.NET Start Region
#region #pragma region #region #Region

End Region
#endregion #pragma endregion #endregion #End Region

Custom Selective Display


The predefined selective display features on the View menu are useful for various common cases. Very often, though, youll want to use selective display with your own search criteria. This is easily done using either the command line or the Selective Display dialog. You can open the Selective Display dialog with the selective-display command (View Selective Display). Each of these has different strengths and capabilities. Weve shown some examples of the command-line versions all and allnot above. The Selective Display dialog is shown in Figure 7-7.

Figure 7-7

The Selective Display dialog operates in several different modes, selected by the radio buttons near the top. The default is Search text, which you use to specify your own search criteria. Using Function definitions is an alternative way to invoke selective display to make all your function definitions expandable and collapsible. The Preprocessor directives mode lets you use selective display to filter your source file according to preprocessor conditional directives such as #ifdef. You can use this to see which lines of your source file are actually seen by the compiler.

148

Chapter 7: Search and Replace


The Multi-level mode makes all the control structures in your source file expandable and collapsible. This is one way you can filter out parts of the code youre not interested in and concentrate on the parts you are interested in. Figure 7-8 shows selective display displaying only those lines containing the text _command. In a Slick-C file, this is the most effective way of seeing only the command definitions.

Figure 7-8

The custom selective display capability available with the Selective Display dialog is nice, but it does not allow you to use some of the features available for searching in general with selective display. For example, it does not support searching in color syntax regions as the Find and Replace tool window does. Command-line selective display is faster to use and sometimes more powerful than the GUI interface. Its also very simple.

Configuring Default Search Options


You can configure several default search options in the Search tab of the General Options configuration dialog: Tools Options General. The dialog, shown already in Chapter 6, is repeated in Figure 7-9. The Default search options provides defaults. Command-line find uses these defaults for any options that are not specified explicitly in the command. These defaults are pre-populated into the GUI Find dialog when it is activated, if Initialize with default options is checked. If Initialize with default options is not checked, the Find dialog remembers the options you used last time. The Leave selected option, on by default, causes search matches to be selected automatically. Sometimes this is not desired, particularly if you are searching within a selection. Uncheck this option to make the search commands leave selections alone.

149

Part II: Using SlickEdit

Figure 7-9

Command-line find is smart enough to leave the selection alone when using the m option (Search in selection), even if Leave selected is on. The GUI Find is not, however. (Did you need another reason to prefer the command line?)

Summar y
Search and replace is a fundamental aspect of any text editor. SlickEdit offers a variety of search and replace tools to cover all situations, from the fast and simple to the complex. SlickEdits regular expression support is extensive, including three different syntax variants. Color-coded searching is an enhancement specifically for programming, which can often make searches much more selective than they would be otherwise. Simple search features such as quick-search and i-search are invoked directly using the keyboard for maximum speed. Complex searches can be configured using many options in either the GUI dialogs or a range of commands on the command line. The GUI dialogs are great for learning what options are available and experimenting with them. The command line can be faster for experts, and makes searches more repeatable and programmable. Macro programming often invokes searches similarly to the commandline searches. In the next chapter, we start looking at advanced features and techniques with SlickEdit for actually editing text.

150

Editing Text
While Ive spent a lot of time writing code throughout my programming career, it seems that I spend just as much time in the editor working with other kinds of files. Some examples are: Scripts or sets of commands. Test data (and sometimes production data too!). Log files. Configuration files. Stack traces. Dumps. Notes.

Sometimes I am merely searching and browsing. Sometimes I am moving things around and deleting unwanted data to analyze the content of a file. Other times I am actively editing, adding new data. SlickEdits speed and advanced features make it ideal for all of these tasks. Many of SlickEdits features are generic to the job of editing text and are not specific to programming, much less to a particular programming language. This chapter covers some of SlickEdits general-purpose text editing features. The topics are important in any task you are doing with SlickEdit. They include: Using basic editing. Using selections and clipboards to move, copy, and manipulate text. Using word completion to save typing.

Chapter 9 follows this with detailed information specific to editing code. Chapter 10 focuses on data-oriented editing.

Part II: Using SlickEdit

Using Basic Editing


SlickEdit has hundreds of commands, and its hard to know how to get started and how to learn the most important ones for basic editing. Features such as insert and overtype mode and deletion of characters with the Backspace or Delete keys are virtually universal. Here we look at several more specific editing commands.

Undo and Redo


The idea of undo and redo is familiar to most programmers. And for most programmers, its pretty indispensable! SlickEdit supports full undo/redo of changes to a buffer and also two alternative schemes for undoing cursor movement within the buffer. The commands are summarized in Table 8-1.

Table 8-1
Command
undo undo-cursor redo

Key Ctrl+Z; Alt+Backspace Shift+F9; Shift+Backspace Ctrl+Y

Description Undo last change or cursor movement. Undo all cursor movement to last change. Redo last undone change.

The way that cursor movement is undone is controlled by a configuration setting. By default, the undo command undoes all cursor movement back to the last change. With this setting, there is no need for undo-cursor. If you prefer to undo cursor movements individually, you can set the macro variable def_undo_ with_cursor to 1. With this setting, each press of undo undoes just one cursor movement, and undo-cursor undoes all cursor movement to the last change. In many cases, pushed bookmarks are the most effective way to get back to where you were after navigation. They are the standard way to return from push-tag or push-ref. They can be used to return after top-of-buffer or bottom-of-buffer, if def_top_bottom_push_bookmark is set to 1. For arbitrary navigation within the buffer, such as paging up and down or moving around among routines, pushed bookmarks only work if you remember to push them first. For these cases, its advantageous to have def_undo_with_cursor set to 1 so that you have flexibility in undoing cursor movement.

Line Commands
When programming, and in other programming-related tasks, its very common to work with lines of text. SlickEdit provides several useful shortcut commands for common operations on lines. These are summarized in Table 8-2.

152

Chapter 8: Editing Text


Table 8-2
Command
cut-end-line cut-line duplicate-line

Key Ctrl+E Ctrl+Backspace WROX: Alt+quote

Description Delete from cursor to end of line. Delete current line. Duplicate current line.

The cut- commands both place the deleted text into the clipboard. Well see a lot more ways of working with the clipboard, and with lines, in the next section.

Using Selections and Clipboards


Selections are used for the classic clipboard operations: Moving. Copying. Deleting.

They are also used for defining the scope of some operations, for example: Searching and replacing. Formatting and manipulating. Filling with data.

SlickEdit is all about text. As we see in Chapter 9, SlickEdit has quite a lot of understanding of the structure of programs, at least for some programming languages. But there is no Drag n Drop, no WYSIWYG, and there are no hidden fields or symbols when you are working with a file. Everything is text. When you make a selection, you are selecting characters of text. The standard character sequence model of selection works in SlickEdit. But it is designed for word processing and is often not the most effective kind of selection in typical programming work. SlickEdit offers a couple of other selection models that reflect more closely the kind of work programmers do. Several configuration options affect the way selections work. Some of these options are discussed in the Configuring Selection Options section.

Working with the Clipboard


SlickEdit supports the usual clipboard concepts cut, copy, and paste familiar in many GUI environments. SlickEdit also provides several useful clipboard extensions beyond these. Table 8-3 is a summary of SlickEdit clipboard commands. These commands are explained in more detail in the following sections.

153

Part II: Using SlickEdit


Table 8-3
Command
cut copy-to-clipboard paste append-cut append-to-clipboard list-clipboards

Key Ctrl+X Ctrl+C Ctrl+V Ctrl+Shift+X Ctrl+Shift+C Ctrl+Shift+V

Description Delete text and place a copy in the clipboard. Copy text to the clipboard. Paste text from clipboard to buffer. Delete text and append it to the current clipboard. Copy text and append it to the current clipboard. Display multiple clipboards to paste from.

Moving and Copying with the Clipboard


You can use the regular clipboard operations with all selections: Use cut (Ctrl+X) to cut or delete text. Use copy-to-clipboard (Ctrl+C) to copy text to the system clipboard. Use paste (Ctrl+V) to paste text from the system clipboard.

These commands work pretty well for quick edits with small selections of a single word or a few words. Note that you can also use the cut and copy-to-clipboard commands with no selection, in which case they operate on the current line. For larger jobs, SlickEdit has powerful commands that work with locked selections, explained below.

Multiple Clipboards
When you copy text to the clipboard in SlickEdit, the editor actually creates and remembers a set of clipboards. When you wish to paste from the clipboard into SlickEdit, you can select which clipboard to paste from. The default paste command always pastes from the current or most recent clipboard. If you want to paste from another clipboard, use the list-clipboards command (Ctrl+Shift+V) instead. (Although the name of the command is quite different from paste, its function is similar; thus the keyboard shortcut is chosen to make it easy to remember as an enhanced version of paste.) SlickEdit displays the Select Text to Paste dialog, shown in Figure 8-1. The dialog shows you, for each clipboard, the type of selection stored in it and a preview of the selection. You can select a clipboard to paste, or cancel. The number of clipboards SlickEdit remembers is configured in Max clipboards in the More tab of the General Options dialog (Tools Options General), or by setting the def_clipboards macro variable.

154

Chapter 8: Editing Text

Figure 8-1

Appending to a Clipboard
Sometimes you want to collect multiple chunks of text together and move or copy them all to a new location. An example is when you are refactoring a class and moving a selection of its methods to another file. You could move each function separately, one by one. Or, you could cut each function individually to a clipboard, and then paste each of those clipboards in turn into the new file. A better alternative is provided by SlickEdits clipboard append commands: Use append-cut (Ctrl+Shift+X) to cut text and append it to the current clipboard. Use append-to-clipboard (Ctrl+Shift+C) to append text to the current clipboard.

The keyboard shortcuts of these commands are designed to be easy to remember, because they simply add the Shift key to the familiar shortcuts for cut and copy.

Locked Selections
If you make a selection with the mouse, or by holding down Shift and using cursor movement keys, the selection is regular, and behaves like selections in most word processors. You need to copy or cut the text before moving the cursor again, because moving the cursor loses the selection. With SlickEdit, you can also make locked selections. Locked selections are much more flexible than regular selections, because you can move the cursor away, type text, and do many other things without losing the selection. Locked selections can be extended any number of times. Many SlickEdit features are designed to work with locked selections. Table 8-4 is a summary of SlickEdit commands for locked selections. Many of the select- commands are available under the Edit Select cascading menu.

Table 8-4
Command
select-char select-line

Key F8; WROX: Alt+Z Ctrl+L; WROX: Alt+L

Description Start or extend a character selection. Start or extend a line selection. continued

155

Part II: Using SlickEdit


Table 8-4 (continued)
Command
select-block select-word

Key Ctrl+B; WROX: Alt+B (none)

Description Start or extend a block selection. Make a character selection from the cursor to the end of the current word. Make or extend a character selection from the cursor to the end of the current word. Make a character selection for the whole word under the cursor. Make a line selection for the entire buffer. Make a selection for the code at the current scope. Make a line selection for a group of lines bounded at the top and bottom by a blank line. Make a character selection for the next block of code bounded by parentheses, brackets, or braces. Make a line selection for the entire procedure, function, or method the cursor is in. Move the selection to the current cursor position. Copy the selection to the current cursor position. Move to the beginning of the selection. Move to the end of the selection. Turn off existing selection. Convert all words in selection to uppercase. Convert all words in selection to lowercase. Shift text in selection one character to the left.

select-next-word

(none)

select-whole-word

(none)

select-all select-code-block

Ctrl+A (none)

select-paragraph

(none)

select-paren-block

(none)

select-proc

(none)

move-to-cursor

WROX: Alt+M

copy-to-cursor

WROX: Alt+C

begin-select end-select deselect upcase-selection lowcase-selection shift-selection-left

WROX: Alt+Y WROX: Alt+E Ctrl+U, WROX: Alt+U Ctrl+Shift+U Ctrl+Shift+L Shift+F7

156

Chapter 8: Editing Text


Table 8-4 (continued)
Command
shift-selection-right

Key Shift+F8

Description Shift text in selection one character to the right. Remove trailing spaces from lines in selection. Pass selection as input to external command.

remove-trailingspaces filter-command

(none)

(none)

There are some configuration options that affect the behavior of regular selections, but for the most part they behave the same way they do in many other programs; thus we will not go into them in much detail here. Unless otherwise noted, what follows applies to locked selections.

Selection Models
SlickEdit supports three different selection models: Character selection. Line selection. Block selection.

The following sections explain each of these models, and how to make them.

Character Selection
A character selection is defined by a starting character and an ending character. The selection includes the start, end, and all characters between, as shown in Figure 8-2.

Figure 8-2

When a character selection spans more than one line, as does the one in Figure 8-2, SlickEdit displays the number of lines selected in the status line, as shown in Figure 8-3.

Figure 8-3

157

Part II: Using SlickEdit


When you make a character selection within a single line, SlickEdit displays the number of characters selected in the status line, as shown in Figure 8-4.

Figure 8-4

Character selection should be familiar from programs such as Notepad and most word processors. Character selection is the most useful kind of selection when you are working with plain text, such as notes or documentation. Character selection can also be used to select small chunks of characters within a single line. To make a (locked) character selection:

1. 2. 3. 4.

Move the cursor to the first character. Press select-char (F8) to begin the selection. Move the cursor to the character after the last character you wish to select. The selection grows as you move the cursor. Press select-char (F8) to lock the selection.

Once the selection is locked, you can move the cursor to another location. In the WROX emulation, select-char is also bound to Alt+Z.

Line Selection
A line selection is defined by a starting line and an ending line. The selection includes all the characters of the starting line, the ending line, and all lines between, as shown in Figure 8-5.

Figure 8-5

When you make a line selection, SlickEdit displays the number of lines selected in the status line, as shown in Figure 8-6.

Figure 8-6

158

Chapter 8: Editing Text


Lines are usually the fundamental elements of programs. Programs are made up of lines. Typically, each line contains a single statement. Line selection is the most useful kind of selection when you are working with code. When you paste or otherwise copy data from a character selection, the text is pasted in at the cursor position. With a line selection, the text is pasted either above or below the current line. Which it does is determined by your choice of Line insert style on the More tab of the General Options dialog (Tools Options General). To make a line selection:

1. 2. 3. 4.

Move the cursor to anywhere on the first line. Press select-line (Ctrl+L) to begin the selection. Move the cursor to anywhere on the last line. The selection grows as you move the cursor. Press select-line (Ctrl+L) to lock the selection.

Once the selection is locked, you can move the cursor to another line. In the WROX emulation, select-line is also bound to Alt+L.

Block Selection
A block selection is defined by an upper-left position and a lower-right position. The selection includes all the characters in the rectangle bounded by the upper-left and lower-right characters, as shown in Figure 8-7.

Figure 8-7

When you make a block selection, SlickEdit displays the number of rows and columns selected in the status line, as shown in Figure 8-8.

Figure 8-8

Block selection is the most useful kind of selection when you are working with data in columns, such as CSV files, SQL updates, and some XML files.

159

Part II: Using SlickEdit


To make a block selection:

1. 2. 3. 4.

Move the cursor to the top-left character. Press select-block (Ctrl+B) to begin the selection. Move the cursor to the bottom-right character. The selection grows as you move the cursor. Press select-block (Ctrl+B) to lock the selection.

Once the selection is locked, you can move the cursor to another location. In the WROX emulation, select-block is also bound to Alt+B.

Special Selection Commands


SlickEdit provides a few more useful shortcuts for selecting text in common cases. Some of these deal with individual words. Others deal with larger units such as whole functions or classes. All of these commands produce regular, or unlocked, selections. Depending on your configuration settings, you may optionally lock the selection after making it. See the section Configuring Selection Options below. Apart from select-all, these commands are not bound to keyboard shortcuts in the CUA emulation. Some of them are available in the Edit menu, under Edit Select. The others need to be invoked from the command line. If you find yourself using any of these frequently, you can bind them to keyboard shortcuts of your choice.

Selecting Words
There are several commands providing convenient ways to select individual words. These commands work well for variables and other identifiers in programming: Use select-word to make a character selection from the cursor to the end of the current word. The cursor is moved to the end of the selection. Use select-next-word to make or extend a character selection from the cursor to the end of the current word. The cursor is moved to the end of the selection. You can use this command to extend the selection a word at a time. Use select-whole-word to make a character selection for the whole word under the cursor. The cursor is moved to the end of the selection.

Selecting Larger Units


Use select-all (Ctrl+A) to make a line selection for the entire buffer. This command is familiar from other CUA-based programs. Use select-code-block to make a selection for the code at the current scope. If the cursor is on a statement, the entire statement is selected. If it is in a block but outside a statement, the block is selected. Use the command repeatedly to extend the selection to the next higher level, up through functions and classes. The selection begins as a character selection and changes to a line selection as it grows.

160

Chapter 8: Editing Text


Use select-paragraph to make a line selection for a group of lines bounded at the top and bottom by a blank line. Use select-paren-block to make a character selection for the next block of code bounded by parentheses, brackets, or braces. This is useful for selecting expressions. Use select-proc to make a line selection for the entire procedure, function, or method the cursor is in.

Working with Selections


You can do many things with selections. The most common operations are the classic clipboard operations: move, copy, and delete. With SlickEdit, you can do these operations using clipboard copy and paste, or you can use locked selections to do them in more flexible and powerful ways. You can also use locked selections to define the scope of many other operations.

Moving and Copying with Locked Selections


You can use locked selections to move and copy text more quickly, powerfully, and flexibly. There is no need to use the clipboard for simple move and copy operations. Use move-to-cursor (WROX: Alt+M) to move the selection to the current cursor position. Use copy-to-cursor (WROX: Alt-C) to copy the selection to the current cursor position.

These commands are not bound to keys in the default CUA emulation. Note that only one selection may be active at a time, throughout the editor. This means that you cannot have different selections active simultaneously in different buffers. It allows you to use move-to-cursor and copy-to-cursor to move and copy text between buffers unambiguously.

Moving around in Locked Selections


You can move quickly to the top or bottom of the selection using these commands: Use begin-select (WROX: Alt+Y) to move to the beginning of the selection. Use end-select (WROX: Alt+E) to move to the ending of the selection.

These commands are also not bound to keys in the default CUA emulation.

Deselecting
Moving the cursor does not deselect a locked selection. To turn off an existing locked selection, use the deselect command (Ctrl+U). In the WROX emulation, deselect is also bound to Alt+U. Usually you dont have to deselect explicitly. You can also deselect by any of the following: Deleting the selection. Starting a new selection of a different kind. Starting a new selection in a different buffer.

161

Part II: Using SlickEdit


If you start a new selection in a different buffer, the previous selection is deselected. You can restore the previous selection by switching back to its buffer and invoking undo (Ctrl+Z).

Using Selection Scopes


You can also use selections to define the scope of many other operations. In Chapter 10, we see how block selections can be used for many useful techniques when editing data in columns. Character and line selections are also useful in defining the scope of operations. Here are some examples: Use upcase-selection (Ctrl+Shift+U) to convert all words in the selection to uppercase. Use lowcase-selection (Ctrl+Shift+L) to convert all words in the selection to lowercase. Use shift-selection-left (Shift+F7) to move the selected text left. Use shift-selection-right (Shift+F8) to move the selected text right. Use remove-trailing-spaces to remove trailing spaces from selected lines.

These commands can all be found under the Edit Other menu. You can also create your own commands and have those commands operate on selections. We see how to write macros that operate on selections in Chapter 16.

Searching in Selections
An important use of selections is to limit the scope of Find or Search and Replace. This can be particularly useful using block selections, as it allows you to find or replace in a column. To limit a Find or Replace command to the selection, use the m option. For example, to find the next occurrence of the word edit in the selection, use the command:
find /edit/m

or use the shorter command:


/edit/m

To replace tabs with commas in the selection, use the command:


replace /\t/,/um

or use the shorter command:


c/\t/,/um

For more information about searching and replacing, see Chapter 7.

162

Chapter 8: Editing Text


Filtering Selections
You can pass a selection as input to an external program using filter-command (Edit Other Filter Selection). The output of the external program replaces the selected text in the buffer. This enables many techniques familiar to UNIX programmers using editors such as vi.

Saving and Reusing Selections


One of the things I often use SlickEdit for is a kind of super scratchpad for other programs. Most programs provide rather poor editing abilities compared to SlickEdit. Thus I often copy text from another program into SlickEdit, edit it, and then paste it back into the other program. Sometimes I need to do this repetitively. An example is when Im working with a database tool, such as Oracle SQL-Plus. I often edit some SQL commands, enter them in SQL-Plus, then repeat the process. If I have more than one set of commands in my scratchpad, Id like to be able to select the different sets quickly and easily. Bookmarks provide an easy way to navigate to specific lines in a file, and they can be combined with line selections to provide a kind of bookmarked selection. The commands wrox-saveline-sel and wrox-restore-line-sel below show how to do this.
_command void wrox_save_line_sel(_str bookmark = SELECTION) name_info(,VSARG2_REQUIRES_AB_SELECTION) { if (_select_type() != LINE) { message(Line selection required.); return; } delete_bookmark(bookmark _START); delete_bookmark(bookmark _END); push_bookmark(); begin_select(); set_bookmark(bookmark _START); end_select(); set_bookmark(bookmark _END); pop_bookmark(); } _command void wrox_restore_line_sel(_str bookmark = SELECTION) name_info(BOOKMARK_ARG*,VSARG2_REQUIRES_EDITORCTL) { push_bookmark(); goto_bookmark(bookmark _START); _str filename = p_buf_name; goto_bookmark(bookmark _END); if (p_buf_name != filename) { message(Bookmark _END must be in same file as bookmark _START.); pop_bookmark(); return; } deselect(); goto_bookmark(bookmark _START); select_line(); goto_bookmark(bookmark _END); select_line(); pop_bookmark(); }

163

Part II: Using SlickEdit


To save a line selection as two bookmarks, named SET1_START and SET1_END, enter the command:
wrox-save-line-sel SET1

To restore the line selection later, provided the bookmarks have not been cleared, enter the command:
wrox-restore-line-sel SET1

To make these commands handier to use, you may want to rename them to something shorter.

Configuring Selection Options


You can configure various options for selections, according to your preferences. Selection options are configured on the Selections tab of the General Options dialog (Tools Options General), shown in Figure 8-9.

Figure 8-9

Most of these options are self-explanatory or are well explained in the online Help. When Extend selection as cursor moves is checked, the procedure for making a locked selection is as described above, that is:

1. 2. 3. 4.

Move the cursor to the start. Use a selection command (select-char, select-line, or select-block) to start the selection. Move the cursor to the end of the selection. The selection grows as you move the cursor. Use the selection command again to lock the selection.

164

Chapter 8: Editing Text


If Extend selection as cursor moves is not checked, the procedure is slightly different:

1. 2. 3. 4.

Move the cursor to the start. Use a selection command (select-char, select-line, or select-block) to start the selection. Move the cursor to the end of the selection. The selection does not change as you move the cursor. Use the selection command again to extend the selection to the current cursor position and lock the selection.

This approach has some advantages over the default setting: You can move the cursor around wherever you want after starting the selection, before you finish it. The selection is not affected. You can extend the selection again any number of times after locking it, by invoking the selection command again.

In addition, with Extend selection as cursor moves unchecked, the regular selections made by the special selection commands such as select-word and select-code-block can be locked if you choose. This gives them a bit more flexibility. As with most configuration settings, it is a personal preference, but I recommend unchecking the Extend selection as cursor moves option.

Saving Typing with Word Completion


SlickEdit has several features designed to save you typing. Some of these features apply to specific programming languages and are discussed elsewhere in this book. The word completion feature is generic and applies to any text file.

Introduction to Word Completion


Word completion is a feature that has been in SlickEdit since the very earliest days, and it is arguably still the biggest time-saver of all the completion features. If you are using SlickEdit regularly, you owe it to yourself to become familiar with word completion and its various modes of use. The basic premise of word completion is that when youre programming, you very often have to type a word, or sequence of words, that is already in the file somewhere else. Word completion allows you to search quickly for a match to a partially typed word elsewhere in the file and automatically fill in the rest of it. Word completion can also continue to fill in text following the original match, as far as desired. This turns out to be useful very often. The best way to understand word completion is to work through a brief example.

165

Part II: Using SlickEdit


Suppose you are reviewing some log files from the last few days of running a batch job. You have the list of log files in a buffer. At the beginning, the buffer contains the following text:
batch_job_run-20070101.log batch_job_run-20070102.log batch_job_run-20070103.log batch_job_run-20070104.log batch_job_run-20070105.log batch_job_run-20070106.log

You want to review each log file and add a note about it next to the file name in the list of log files. Suppose that the notes you want to add look like this:
batch_job_run-20070101.log batch_job_run-20070102.log batch_job_run-20070103.log batch_job_run-20070104.log batch_job_run-20070105.log batch_job_run-20070106.log passes passes fails: missing fails: missing followup: user fails: missing

data data review required data

We can use word completion to save a lot of typing when entering these notes. First, you add passes as a comment for the first file. Then, move the cursor to the end of the second line. Figure 8-10 shows the data on the screen at this point.

Figure 8-10

Next, type in p. Now invoke the complete-prev command (Ctrl+Shift+comma). SlickEdit finds the previous string in the file beginning with p and completes your current word to match that. Figure 8-11 shows the result. The matched word is selected.

Figure 8-11

Next, we need to add the comment fails: missing data to the third and fourth lines. Type the complete comment on the third line. Then, move the cursor to the comment position on the fourth line. Type the f to start fails. Invoke complete-prev. SlickEdit completes fails, as shown in Figure 8-12.

166

Chapter 8: Editing Text

Figure 8-12

The message line contains the prompt Press Ctrl+Shift+Space for more: : missing data. This is shown in Figure 8-13. The prompt is useful if the match is off the screen.

Figure 8-13

Invoke complete-more (Ctrl+Shift+Space). The next word (missing) is completed. Invoke complete-more once again to get data. The entire matching comment is selected, as shown in Figure 8-14.

Figure 8-14

Next, add the comment followup: user review required to the fifth line. Now, the sixth line needs fails: missing data again. Move the cursor to the comment position on the sixth line. Type the first f of fails. Invoke complete-prev twice. The first time matches f with followup on the line above. The second time continues searching backward, to fails, which is on line 4 of Figure 8-15.

Figure 8-15

Alternatively, instead of typing just f and using complete-prev twice, you could type fa to make the search more precise. You can search forward instead of backward using complete-next (Ctrl+Shift+dot). You can also use complete-next if you accidentally overshoot while searching backward with complete-prev, and vice versa.

167

Part II: Using SlickEdit

Word Completion in Programming


The word completion features are useful for a wide variety of editing scenarios. The examples weve seen so far involve repetitive entry of phrases into a plain text file. Word completion is also useful in programming, whether or not the language supports intelligent syntax completion. Many languages have limited syntax assistance from SlickEdit. These include older lower-level languages such as SQL and shell scripts, as well as modern languages that use dynamic typing. Word completion is a big time-saver with these languages. In SQL, for example, its common to find oneself entering repetitive statements such as the following:
INSERT INTO network_category (id, description, header, active_yn) VALUES (BASIC, Basic, STANDARD, Y); INSERT INTO network_category (id, description, header, active_yn) VALUES (EXTENDED, Extended, STANDARD, Y); INSERT INTO network_category (id, description, header, active_yn) VALUES (CONTINUOUS, Continuous, PARTIAL, Y);

In such a situation, we can use word completion to complete more than half of each statement, after the first statement. That is, the text:
INSERT INTO network_category (id, description, header, active_yn) VALUES

needs to be typed in only once. Following the first time, it can be repeated very quickly. Even with programming languages that have special syntax support, word completion is often the most effective way to save typing. Java, for example, has a lot of syntax support from SlickEdit. But even so, lets see how word completion works for Java in a typical example. This time we are entering the code for the following JUnit test method:
public void testFirstOrChangedToAnyOf() { Condition aaaCondition = aaa.firstOrChangedToAnyOf(a1, a3); Condition bbbCondition = bbb.firstOrChangedToAnyOf(b1, b3); Condition cccCondition = ccc.firstOrChangedToAnyOf(c1, c3); Condition dddCondition = ddd.firstOrChangedToAnyOf(d1, d3); assertTrue(aaaCondition, bbbCondition, cccCondition); assertFalse(dddCondition); next(); assertFalse(aaaCondition, bbbCondition, cccCondition, dddCondition); next(); assertTrue(aaaCondition, bbbCondition, cccCondition); assertFalse(dddCondition); next(); assertFalse(aaaCondition, bbbCondition, cccCondition, dddCondition); next(); assertFalse(aaaCondition, bbbCondition, cccCondition, dddCondition); }

168

Chapter 8: Editing Text


After typing the first line of the method body in full, you can use word completion to complete both Condition and firstOrChangedToAnyOf on the second, third, and fourth lines. On the fifth line of the method body and onward, you can use word completion to complete any of the identifiers aaaCondition, bbbCondition, cccCondition, and dddCondition. Not only that, but notice that these variables occur in sequence on lines 5, 8, 10, 13, and 15. In these cases, complete-more saves a lot of time. After the sixth line of the method, you dont need to type assertTrue or assertFalse again use word completion instead. Figure 8-16 shows the method entered in the editor, with gray rectangles overlaid over the parts that can be completed with word completion.

Figure 8-16

If any of the identifiers Condition, firstOrChangedToAnyOf, assertTrue, or assertFalse already existed in the buffer before starting, the savings would be even more. Because word completion is simple, it is very fast. You may find that because of tagging or other reasons, the advanced expansion features in SlickEdit can suffer from delays. If the editor delays, it interrupts your flow. Word completion almost never suffers from delays; thus it lets you write code quickly and smoothly. Get into the habit of using word completion. Although it is disarmingly simple, you will find it among the most powerful and useful features in any editor.

Options with Word Completion


Word completion offers several options you can use to fine-tune its behavior. These options relate to: How to reverse the search when alternating between searching forward and backward. Whether to include or skip duplicate matches. What matches to include when searching (the scope of the search).

169

Part II: Using SlickEdit


There is no GUI dialog for configuring these options. The options are configured via a combination of two macro variables: def_complete_flags and def_complete_vars. These macro variables are defined in the macro file compword.e. See Chapter 2 for more information about setting macro variables. The macro variable def_complete_flags is a combination of flags: 1 (COMPLETE_REVERSE_AT_CURSOR). 2 (COMPLETE_CHECK_SCOPE). 4 (COMPLETE_ALLOW_DUP_MATCHES). 8 (COMPLETE_LOOK_FOR_ANYTHING).

The default value of def_complete_flags is 5, which corresponds to both COMPLETE_REVERSE_AT_CURSOR and COMPLETE_ALLOW_DUP_MATCHES being set. The meanings of these flags are explained below. The flag COMPLETE_REVERSE_AT_CURSOR controls what happens when you reverse direction while searching. The default is to reverse direction at the current search position. This setting is useful because you can use it to reverse your search if you accidentally overshoot the match you intended. Also, if matches are off screen, you can search alternately backward and forward, observing the matched lines in the message area. If the COMPLETE_REVERSE_AT_CURSOR flag is not included, then reversing a search causes the search location to revert to the current editing location. The flag COMPLETE_CHECK_SCOPE can be used to indicate that the search has extended outside of the current scope. If you include this flag and the search extends out of the current scope, the message line showing the match is prepended with *** Outside current proc *** as a warning. The flag COMPLETE_ALLOW_DUP_MATCHES controls whether duplicate matches are included in searches. If the flag is not included, duplicate matches are skipped. It might appear that duplicate matches are a bad thing, and that this flag should be excluded. If you are searching for a match for just one word, this is true. If you intend to complete more text after the match, however, it often turns out you need to allow duplicates to match so that you can navigate to the correct line. To continue our example above, suppose you need to extend the file commentary like this:
batch_job_run-20070101.log batch_job_run-20070102.log batch_job_run-20070103.log batch_job_run-20070104.log batch_job_run-20070105.log batch_job_run-20070106.log batch_job_run-20070107.log batch_job_run-20070108.log batch_job_run-20070109.log passes passes fails: missing data fails: missing data followup: user review required fails: missing data fails: incorrect dates fails: incorrect dates fails: missing data

170

Chapter 8: Editing Text


If duplicates are not allowed, then its impossible to match to different lines containing the word fails. With duplicates allowed, you can navigate among the different lines. The COMPLETE_LOOK_FOR_ANYTHING flag controls whether word completion includes matches within strings and comments. By default, SlickEdit behaves like this: If you are inside a comment or a string, then complete-prev and complete-next include matches found elsewhere in comments and strings, as well as matches in code. If you are not inside a comment or a string, then complete-prev and complete-next do not include matches in comments and strings.

If the COMPLETE_LOOK_FOR_ANYTHING flag is included, then matches in comments and strings are always included. The behavior concerning comments and strings can be further customized by the def_complete_vars macro variable. This variable contains two values separated by a space. The default value is 1 2. The first of the two values controls whether comments and strings are skipped. This setting actually affects the same behavior as the COMPLETE_LOOK_FOR_ANYTHING flag above: If either the flag is included, or this first value is not set to 1, then comments and strings are not skipped. (This redundancy is a legacy effect of the SlickEdit macro code.) The second of the two values is a number of lines. This is a rather fine point: Comments and strings within this number of lines of the edit position are not skipped. The idea of this setting is that it can be useful to match comments and/or strings in close proximity to where you are currently editing, but generally you dont want to match them further away. How far away is further away is controlled by this macro variable. The default value of the second value in def_complete_vars is 2, meaning that comments and strings within two lines of the edit line are actually included in matches, while comments and strings farther away are not. Having said all this, I have to admit that configuring word completion is currently rather esoteric and is quite likely to be overhauled in a forthcoming release. Besides, because the default configuration works just fine for most users, you may be happy not to mess with it.

Summar y
This chapter introduced several topics around the general needs of editing text. We started with standard editing features, touching on a few useful features beyond the basics found in Notepad. Then we covered SlickEdits support for clipboards and powerful selection models. We use selections in many places in the book, particularly in Chapter 10. Finally, we introduced word completion, a simple but powerful feature that saves a lot of typing. The next chapter goes into more detailed specifics about editing code and shows several features specific to different types of source files.

171

Editing Code
Editing code is SlickEdits primary function. Many features of the editor apply to text editing in general. Some of them apply to editing data. But the most specialized features deal with specific tasks encountered while editing code. In Chapter 5, we cover Context Tagging, which is an important set of features that provide assistance when editing code. In this chapter, we cover a variety of additional features for editing code. The most basic and obvious code-specific feature is color syntax highlighting. SlickEdit has color syntax highlighting for numerous programming languages, and you can easily add support for a new language. SlickEdit also supports a range of other options per programming language, such as indentation preferences and comment formatting. SlickEdit provides syntax assistance for common constructs in various languages. For example, SlickEdit expands control structures automatically. When you type in starting elements in code, SlickEdit often adds the ending elements automatically. This happens with braces and multiline comments, for example. One reason for this is to save you time. Another reason is that it helps keep the file structure valid, and that is very useful because when SlickEdit can parse the file structure correctly, it can provide the best contextual assistance.

F ile Extensions, Modes, and Lexers


For SlickEdit to be able to provide syntax assistance for your file, it must know what language the file is in. SlickEdit does this through associations between file extensions, modes, and lexers. A file extension is simply the extension part of a filename. C programs typically have the file extension c. C++ programs, on the other hand, have different file extensions, such as cpp and cxx. C and C++ programs also have header files, with extensions like h, hpp, and hxx.

Part II: Using SlickEdit


The mode defines the language-specific behaviors for SlickEdit. The default mode is set automatically based on the file extension. You can set the mode manually using the select-mode command (Document Select Mode). There is also a command for each mode to switch to that mode. For example:
c-mode. html-mode. pascal-mode. plsql-mode.

The default mode, for plain text files or files with an unknown extension, is fundamental mode. To switch a buffer to fundamental mode, use the fundamental-mode command. Some of the settings defined in a mode are: Tab or indentation settings. Language-specific key bindings. A lexer name.

To view and edit the settings for a file extension, use Tools Options File Extension Setup. For an example of setting up a new file extension, see Chapter 17. Some of the modes supplied with SlickEdit are: C/C++. Java. Slick-C.

There are many others, more than 70 in total. A file extension defined in SlickEdit either defines a named mode or refers to another file extension and inherits the mode of that extension. For example, the file extensions cpp, cxx, h, hpp, and hxx all refer to the c extension, and are thus all associated with the C/C++ mode. A lexer is a collection of settings that define syntax coloring rules for a programming language. Some of the settings that define a lexer are: The keywords of the programming language. Whether or not the language is case-sensitive. How comments are defined. How strings are delimited.

To view and edit the color settings for a lexer, use Tools Options Color Coding. We cover lexers in more detail in Chapter 17.

174

Chapter 9: Editing Code

Extensionless Files
Most programming source files have an extension, but some dont. UNIX shell scripts, for example, commonly do not have an extension. SlickEdit deals with shell scripts by examining the first line of the file for the UNIX shebang comment like this:
#!/bin/sh

If SlickEdit finds a shebang comment that it recognizes, it applies the appropriate mode. Another group of files that have no extension is the set of header files for the C++ standard library. SlickEdit has special rules to recognize these files when opening them, and applies the correct mode. You can define additional extensionless header files for libraries you are using:

1. 2. 3. 4. 5.

Open the Extensions Options dialog (Tools Options File Extension Setup). Select extension C. Click C/C++ Options to open the C/C++ Options dialog. Click the Other tab. Click Extensionless C++ Files. SlickEdit displays the Extensionless C++ Files dialog, as shown in Figure 9-1. Use this dialog to specify names of extensionless files you want to be opened as C++ files.

Figure 9-1

Syntax Highlighting
SlickEdits color syntax highlighting is powered by its lexers. If a language has a lexer set up for it, SlickEdit can display different program elements in different colors and styles. There are many program elements. Some of them are: Identifiers. Keywords.

175

Part II: Using SlickEdit


Functions. Strings. Numbers. Comments.

In addition to program elements, there are many other screen elements that SlickEdit can color specially to make them more distinctive. Some of these other elements are: The cursor. Hex mode. Selection. Block matching. Search match.

There are more than 30 screen elements in total. You can define the foreground and background color for any screen element, as well as whether to display the element in normal font, bold, italic, or underlined. The settings are done separately for whether the language is the main language of the file or embedded within another language. See Embedded Languages below in this chapter. You can save a collection of color settings in a named color scheme. SlickEdit provides several color schemes, and you can create as many more as you like. The Color Coding Setup dialog (Tools Options Color Coding) is used to define the characteristics of lexers. From that dialog, you can click the Colors button to open the Color Settings dialog, where you can customize the colors of screen elements. Figure 9-2 shows the Color Settings dialog.

Figure 9-2

176

Chapter 9: Editing Code


When customizing colors, keep in mind how they will work with selections. When you make a selection, SlickEdit tries to combine the colors of the elements on screen with the selection color. The editor tries to maintain a good contrast so that all elements are legible. Some color combinations can cause trouble for SlickEdits heuristic.

Indentation and Code Style


Different programmers and programming communities use widely different styles for coding, even in the same language. Some Linux hackers speak of the prophets, Kernighan and Ritchie. (See http:// lxr.linux.no/source/Documentation/CodingStyle.) Other GNU programmers follow the GNU coding style. (See http://www.gnu.org/prep/standards/standards.html#Formatting.) Some coding styles encourage the use of tabs for indentation. Other styles prohibit them. The debates over tabs and brace placement are an ongoing staple of programmer culture and will probably go on for as long as there are programmers. SlickEdit takes no position in the debate, but attempts to support most of the major styles in use. Generic indentation settings are found on the Indent tab of the Extension Options dialog (Tools Options File Extension Setup). This tab is shown in Figure 9-3.

Figure 9-3

This dialog allows you to customize various aspects of tab use and indentation. From the Extension Options dialog, you can click on an Options button to open an options dialog specific to the programming language associated with the selected extension.

177

Part II: Using SlickEdit

C/C++ Options
By far the most options are available for the C/C++ languages. These languages have three tabs of options available, shown in Figures 9-4, 9-5, and 9-6. Figure 9-4 shows the C/C++ style options concerning braces. Note that the function brace style can be set differently from the control structure brace style in C/C++, as many C/C++ coding standards require this.

Figure 9-4

Figure 9-5 shows some additional indentation settings that are specific to C/C++. This tab also allows you to specify your preferred style for declaring pointers.

Figure 9-5

Figure 9-6 shows other settings specific to C/C++. The Main style setting selects a template to use when you define the C/C++ main() function.

178

Chapter 9: Editing Code

Figure 9-6

The C/C++ Preprocessing button opens the C/C++ Preprocessing dialog, which is used to control the preprocessor for C/C++ files. This is important for SlickEdit to be able to parse C/C++ files correctly. The Extensionless C++ Files button opens the dialog of that name, which we have covered above.

Java and C# Options


As weve seen, there are a lot of options specific to C/C++ source files. In contrast, other programming languages have fewer options. For example, Figure 9-7 shows the options specific to Java programs. The options for C# are the same. For these languages, the brace and indentation standards are not as varied or complex as C/C++. Also, these languages have no preprocessor, which greatly simplifies parsing them.

Figure 9-7

179

Part II: Using SlickEdit

HTML Options
HTML options are completely different from those of other programming languages. Figure 9-8 shows the options for HTML. You can specify the case for different HTML elements. You can specify the language for embedded ASP. And you can specify a number of settings that affect how SlickEdit inserts HTML content.

Figure 9-8

Other Languages
SlickEdit has language-specific options for several other programming languages. Click the Options button on the Extension Options dialog to see options specific to the selected extension. The Options button dynamically changes label depending on the language and is enabled only if there are language-specific options available.

Wor king with Control Str uctures


A lot of programming involves control structures and blocks of code. As well as entering structures such as conditionals and loops, programmers often need to modify them. SlickEdit has several features that help greatly with common operations. These features have been developed and refined over many years, and sometimes reflect different ways of doing the same thing. We review some of them here. The ones you use will depend on your own preferences.

180

Chapter 9: Editing Code

Syntax Expansion
When you are typing code, SlickEdit can automatically expand control structures and other statements in the language. For example, suppose you are editing a C file as shown in Figure 9-9.

Figure 9-9

Lets use syntax expansion to insert an if() test for the number of arguments passed in to the program:

1.

Type if and press Space. SlickEdit expands the if control structure as shown in Figure 9-10.

Figure 9-10

2.

Type argc == 0. The screen now appears as in Figure 9-11.

Figure 9-11

3.

Invoke next-hotspot (Ctrl+[) to move the cursor out of the condition and on to the next place where you want to edit. The screen now appears as in Figure 9-12. SlickEdit also prompts you to continue pressing Ctrl+[ to go to the next part of the statement, as shown in Figure 9-13.

Figure 9-12

Figure 9-13

The if() statement has two hotspots: one in the condition, and one after the opening brace. Invoke next-hotspot (Ctrl+[) and prev-hotspot (Ctrl+Shift+[) to cycle through the hotspots. Syntax expansion is triggered by mode-specific key bindings. For example, in C/C++ mode, the Space key invokes the command c-space, which is defined in c.e in the supplied macro source. The logic for

181

Part II: Using SlickEdit


determining what control structure to expand, and the exact text and hotspots to output, is contained in the macros defined in that file. You can examine those macros to see how it works, and you can change the behavior if you wish. For example, the syntax expansion for the _command keyword in Slick-C mode inserts the following template:
_command void () name_info(,) { }

This template is entered verbatim. It does not honor the brace preference settings. One way to fix this would be to edit the Slick-C code in the slick_expand_space() macro function. However, messing with the macros provided with SlickEdit is usually not a good idea. For one thing, you might mess things up! For another, your changes will be lost when you upgrade. Fortunately, there is a much better way to override the templates provided, using extension-specific aliases. We look at aliases in detail in Chapter 11.

Adding a Control Structure


It is pretty common when programming to need to add a control structure around some code thats already there. For example, suppose you have the file shown in Figure 9-14. You need to add a test around the printf() statements.

Figure 9-14

One way you can do this is using the surround-with command. To add the test with surround-with:

1.

Select the lines you want to surround. The screen should appear as shown in Figure 9-15.

Figure 9-15

2.

Invoke surround-with. SlickEdit displays the Surround With dialog, as shown in Figure 9-16. There is no key binding for surround-with in the CUA emulation, but it is available in the context menu. (Open the context menu by right-clicking with the mouse.)

182

Chapter 9: Editing Code

Figure 9-16

3.

Choose if and press Enter. SlickEdit surrounds the selection with an if() statement, as shown in Figure 9-17.

Figure 9-17

4.

Type argc == 0 for the condition.

The surround-with templates are specific for each mode. The templates are implemented by way of extension-specific aliases. In Chapter 11, we look at an example of how to add your own surround-with template.

Dynamic Surround
In SlickEdit 2007, there is a new feature for surrounding code with control structures, called dynamic surround. Dynamic surround does basically the same thing as surround-with, but it is generally quicker and more intuitive. To add the same test as before, but with dynamic surround, start again with the file as shown in Figure 9-14. Then:

1. 2.

Add a new line for the if() statement, above the first printf(). Type if, and press Space. SlickEdit goes into dynamic surround mode, as shown in Figure 9-18. SlickEdit prompts you to surround lines of code using the arrow keys, as shown in Figure 9-19.

Figure 9-18

183

Part II: Using SlickEdit

Figure 9-19

3.

Press the down arrow three times, to surround the three printf() statements. As you extend the surround, the closing brace moves down, and the printf() statements are re-indented to the enclosing block. The screen appears as shown in Figure 9-20.

Figure 9-20

4.

Type argc == 0 for the condition. Dynamic surround mode ends when you start typing code. You can also end dynamic surround by pressing Escape.

Dynamic surround is particularly nice for dealing with heavily nested files such as HTML. You can wrap an element such as a <div> or a <p> around other content quickly and intuitively. Alternatively, you may find that having dynamic surround invoked automatically gets in your way, since it sometimes interrupts normal typing. If thats the case, you can disable it in the Indent tab or the Extension Options dialog (Tools Options File Extension Setup). This setting is per mode; thus you can have dynamic surround run automatically for some file types and not for others.

Deleting a Control Structure


Sometimes you want to do the opposite remove a control structure, without removing the code it surrounds. Lets remove the if() test of the last example. We start with the file as shown in Figure 9-21.

Figure 9-21

1. 2. 3.

Move the cursor to the if() statement. Invoke delete-code-block (Ctrl+Del). SlickEdit displays the Delete Code Block dialog, shown in Figure 9-22. SlickEdit also selects the whole block, as shown in Figure 9-23. If you wish to delete the whole block, including the printf() statements, you can click Delete the entire block. If you wish to remove the if() statement and unsurround the printf() statements, you can click Unsurround the block.

184

Chapter 9: Editing Code

Figure 9-22

Figure 9-23

If you prefer to delete code blocks without prompting, check the Always just delete block checkbox. This setting is also controlled by the def_prompt_for_delete_code_block macro variable. If you turn off prompting for delete-code-block, you cannot use the command for unsurrounding blocks. You can use the unsurround command (Ctrl+Shift+Del) instead. This command also displays a confirmation prompt, as shown in Figure 9-24. You can turn off this prompt too by setting the macro variable def_prompt_for unsurround_block to 0.

Figure 9-24

Avoiding Syntax Assistance


Most of the time, SlickEdits syntax assistance reduces typing and helps you get your work done. Sometimes, though, you may be doing something where you dont want syntax assistance to be invoked. For example, you might be recording a macro for repeated playback. Usually with macros, you dont want syntax assistance to be activated. One way to avoid syntax assistance is to switch to fundamental mode. This is appropriate if you are doing a series of edits for which you dont want assistance. If you want to suppress assistance for one keystroke, use the quote-key command (Ctrl+Q). You can use it before any keystroke that would normally result in syntax assistance, such as Space or {. With quote-key, you just get the character, not the extra assistance.

185

Part II: Using SlickEdit

Unified Completions with Auto-Complete


Weve seen several different completion features: word completion, syntax expansion, list members, and parameter information. These features have evolved over different releases of SlickEdit. At some point it became clear that there were too many completion features for new users to learn them all separately. Thus, the SlickEdit team added the Auto-Complete feature, which unifies all the other completions under one umbrella and provides a common interface combining them all. In some ways, Auto-Complete is more powerful than individual features such as word completion. For one thing, it happens automatically. And it is more modern-looking. On the other hand, it is less direct and maybe not as fast to use for the advanced user. Auto-Complete uses several advanced searches to find possible entries for the current context. The full list of searches is documented in the online Help, but as well as word completion, it includes things like syntax completion, keywords, aliases, and symbols. See Configuring Auto-Complete below for more information.

Introduction to Auto-Complete
In contrast to word completion, which is invoked explicitly, Auto-Complete is usually invoked automatically by SlickEdit when you pause briefly in your typing. The default timeout is 250 milliseconds, but this can be configured, as can many Auto-Complete settings. Lets compare Auto-Complete with word completion for the data-editing job given in Chapter 8. Suppose we start again with the original file, which looks like this:
batch_job_run-20070101.log batch_job_run-20070102.log batch_job_run-20070103.log batch_job_run-20070104.log batch_job_run-20070105.log batch_job_run-20070106.log

First, you add passes as a comment for the first file. Then, move the cursor to the end of the second line. Figure 9-25 shows the data on the screen at this point.

Figure 9-25

Next, type in p. After a short delay, Auto-Complete activates and finds the previous string in the file beginning with p, as shown in Figure 9-26.

186

Chapter 9: Editing Code

Figure 9-26

Move the cursor down to the passes entry (the only entry) in the list. Auto-Complete displays information about the match, as shown in Figure 9-27.

Figure 9-27

Press Enter to accept the match. SlickEdit updates the buffer with the completed word, and the AutoComplete dropdown disappears. Next, we need to add the comment fails: missing data to the third and fourth lines. As with word completion, type the complete comment on the third line. Then, move the cursor to the comment position on the fourth line. Type the f to start fails. After a short delay, Auto-Complete activates and finds the previous word starting with f. Move the cursor down to the fails entry. Auto-Complete indicates on which line the match was found and the text following the match. Figure 9-28 illustrates Auto-Complete, showing the match for fails.

Figure 9-28

Press Enter to accept the match. The message line contains the prompt Press Ctrl+Shift+Space for more: : missing data, just as with word completion. This is shown in Figure 9-29.

Figure 9-29

187

Part II: Using SlickEdit


Invoke complete-more (Ctrl+Shift+Space). The next word (missing) is completed. Invoke completemore once again to get data. The entire matching comment is selected, as shown in Figure 9-30.

Figure 9-30

Next, add the comment followup: user review required to the fifth line. Now, the sixth line needs fails: missing data again. Move the cursor to the comment position on the sixth line. Type the first f of fails. After a short delay, Auto-Complete activates and shows matches for f, as shown in Figure 9-31.

Figure 9-31

At this point, you can use the arrow keys to select the desired match, or type more of the word to narrow the search.

Auto-Complete in Programming
Many Auto-Complete features are specific to programming. In this section, we take a brief look at how Auto-Complete unifies word completion with other features on the programming example we looked at above. The first thing to notice about Auto-Complete is that it can complete things that word completion cannot. For example, word completion cannot complete a word that is not already in the buffer. Auto-Complete, thanks to its advanced searches, can often complete words that are not in the buffer, and it can do it intelligently based on the context. Figure 9-32 shows how Auto-Complete can complete the first word in a Java class definition. The category Syntax Expansion shows which search found the match public for the text pu.

Figure 9-32

188

Chapter 9: Editing Code


As well as showing matches grouped by category, Auto-Complete displays other information it can find about the highlighted match. For symbols with no documentation in the code, Auto-Complete displays just the brief definition of the symbol, as shown in Figure 9-33.

Figure 9-33

If a symbol has some associated documentation such as JavaDoc, Auto-Complete shows that documentation, as shown in Figure 9-34. This is the same information we saw with list members and parameter information.

Figure 9-34

Configuring Auto-Complete
You can configure Auto-Complete for a particular file extension on the Auto Complete tab of the Extension Options dialog (Tools Options File Extension Setup). The tab is shown in Figure 9-35.

Figure 9-35

189

Part II: Using SlickEdit


The Enable auto-completion checkbox controls whether Auto-Complete activates automatically. If you uncheck that box, Auto-Complete does not activate automatically, but you can still activate it with the autocomplete command. There is no key binding for autocomplete in the CUA emulation. The other checkboxes in the group under Enable auto-completion control which searches are used. By default, all searches are used, but you may turn off some of them if you like. The controls in the Options group control how Auto-Complete behaves once it is activated. The controls in the Details group control which visual elements are shown by Auto-Complete. The graphic underneath is updated dynamically when you make changes, so you can see what Auto-Complete will look like with your settings.

Manual Completion or Auto-Complete?


Auto-Complete is an umbrella for other distinct completion features in SlickEdit. Its possible to use those features exclusively through Auto-Complete, to use a mixture of distinct features and Auto-Complete, or not to use Auto-Complete at all. It depends on your needs, experience, and preferences. Auto-Complete can get in the way sometimes, and then it is necessary to press something (usually Escape) to get rid of it. Some features are faster to use without Auto-Complete, once you are familiar with them. For example, if you know where you are going and are familiar with word completion, it is faster to use directly than via Auto-Complete. Its more lightweight, and more intentional. You invoke word completion when you want to complete something, rather than waiting for the editor to decide whether it can help you and choosing from its list. Usually when using word completion, you will know exactly how many times to press complete-prev or complete-next to get to the match you want, and it becomes second nature. That said, a newcomer to SlickEdit might prefer Auto-Complete because its more obvious. Theres less to learn, and less to think about.

Embedded Languages
In some programming environments, it is common to embed one language inside another. There are many examples in web programming, where files frequently contain a mixture of code and formatting. Its also common in UNIX shell scripts and other scripting languages to use here documents to output chunks of code. SlickEdit supports embedded languages very well, providing color syntax highlighting, and often other editing features too, for the embedded code.

Web Programming
There is a huge variety of web programming environments these days. On the one hand, there is serverside web programming such as PHP, ASP, and JSP. On the other hand, many web sites use client-side

190

Chapter 9: Editing Code


JavaScript embedded within HTML. In both of these cases, the structure is similar. The main file is an HTML file, but it contains code embedded in it in another language. For server-side web programming, files are usually identified by an extension corresponding to the programming language, such as .php. Code in these files is delimited by character sequences such as <? and ?>. Figure 9-36 shows an example of a PHP file. The main file is treated as HTML. The portions within the <?php and ?> delimiters are treated as PHP. As well as getting different syntax coloring, most other syntax assistance features also work for the embedded language. It may not be clear in the printed book, but here SlickEdit displays the comments in green, keywords in orange, the string in turquoise, and the rest of the text in black.

Figure 9-36

Client-side JavaScript is often placed into its own .js file, which SlickEdit treats just like any other source file. JavaScript may also be embedded within HTML files, within the <script> tag. In this case, SlickEdit supports the embedded syntax between the <script> tag and its closing </script> tag. Figure 9-37 shows an example of JavaScript embedded in an HTML file. Again, the main file is treated as HTML. The text within the <script> and </script> tags is treated as JavaScript, getting syntax coloring and other language-specific assistance.

Figure 9-37

Here Documents in Scripts


UNIX shells, and several scripting languages, support multiline strings called here documents. These are extremely convenient for templates that output code, such as HTML or SQL.

191

Part II: Using SlickEdit


Here documents begin with <<IDENT, where IDENT is some identifier, often EOF. The multiline string extends to the next occurrence of IDENT in the code. Figure 9-38 shows an example of a here document in a Ruby script. Between the <<HTMLEOF and HTMLEOF, SlickEdit treats the text as HTML. Color syntax highlighting is applied, and other syntax assistance features work too. It may not be clear on the printed page, but the color syntax in this example highlights an error. The closing tag for <html> is misspelled as </hmtl>. On the screen, this shows as orange, the color for unknown XML element. The correct HTML elements show in purple, the color for keywords.

Figure 9-38

Note that for SlickEdits embedded language features to work with here documents, you must use the name of the lexer (HTML in the example above) in the string terminating the here document.

Wor king with Comments


SlickEdit understands two kinds of comments: line comments and multiline comments. Line comments are the kind where a character or sequence of characters marks the rest of the line as a comment. Familiar examples are:
// in C++, Java, and many other languages. # in shell and scripting languages.

Multiline comments are also known as block comments. These comments typically use a sequence of characters to mark the beginning and another to mark the end. Examples are:
/* and */ in C, C++, Java, and many other languages. <!-- and --> in HTML and XML.

Comments are used for two main purposes in coding. The intended purpose of comments is to document the code. However, they are also commonly used to exclude code from the compiler (or interpreter), whether temporarily or permanently. In C/C++, the preprocessor is also used to selectively omit sections of code. In many other languages, there is no preprocessor, and comments are the standard technique for selectively omitting code. SlickEdit has several features that assist when using line comments or multiline comments for either of these purposes.

192

Chapter 9: Editing Code

Line Comments
Single-line comments can be added to document small pieces of code. Line comments are also frequently appended to the ends of lines to document declarations or logic. Perhaps less frequently, longer comments can be made with line comments that run over more than one line. For these comments, SlickEdit can provide assistance by wrapping lines as you type. One single-line comment is treated as a special case. Wrapping features dont start until you have more than one contiguous line comment. Wrapping for line comments is off by default. See Configuring Comments below. In many programming languages, including the C/C++ family, block comments do not nest. For this reason, they are often inappropriate for commenting-out code. Line comments do not have this problem and can be safely used to comment-out any code, even code that already has line or block comments. With help from the editor, you can apply or remove line comments on a range of lines easily. You can apply line comments to a selection or the current line like this:

1. 2.

If you want to apply line comments to multiple lines, select them first. Invoke comment (Document Comment Lines).

You can use comment-erase (Document Uncomment lines) in a similar way to remove line comments. These commands are not bound to keys in the CUA or WROX emulations. You could bind them to keys if you want to. But rather than use up two keys for applying and removing line comments, how about using a single key to toggle them instead? The macro code below defines a utility function wrox_in_comment(), which returns True if the cursor is currently on a commented line. After that, it defines a command, wrox-toggle-comment, and a binding for that command to Ctrl+Shift+slash.
boolean wrox_in_comment() { push_bookmark(); p_col = 1; begin_line_text_toggle(); int orig_col = p_col; int orig_line = p_line; int status = search(., U,CC); boolean result = (!status && orig_col == p_col && orig_line == p_line); pop_bookmark(); return result; } _command void wrox_toggle_comment() name_info(,VSARG2_REQUIRES_EDITORCTL) { boolean selection = _select_type() != ; if (wrox_in_comment()) { comment_erase(); } else { comment();

193

Part II: Using SlickEdit


} if (!selection) { cursor_down(); } } defeventtab default_keys; def C-S-/ = wrox_toggle_comment;

You can use wrox-toggle-comment instead of comment and comment-erase. The wrox-toggle-comment command determines whether the cursor is currently on a commented line or not. If the cursor is on a commented line, the command invokes comment-erase, otherwise it invokes comment. If there is no selection, wrox-toggle-comment also moves the cursor down one line. This makes it quick and easy to toggle the line comments on a few lines.

Multiline Comments
Multiline comments, oddly enough, often span more than one line. SlickEdit wraps multiline comments automatically, according to margin rules that you can configure. See Configuring Comments below. When you start a multiline comment by typing /*, SlickEdit automatically inserts the closing */ after the cursor. This is shown in Figure 9-39. This has the advantage that it keeps your file structure valid, so that syntax coloring and other assistance work correctly.

Figure 9-39

If you intended the multiline comment to end somewhere else, you can simply move to that location and insert the */ yourself. SlickEdit removes the */ that it inserted. This is shown in Figure 9-40. However, usually you simply type in your comment.

Figure 9-40

194

Chapter 9: Editing Code

JavaDoc Comments
A special form of multiline comment is the JavaDoc comment, which originated in its current form with the Java programming language. JavaDoc is a very useful idea because it provides a standard format for documentation comments in source code. This allows tools to extract and process the documentation reliably. On the Java platform, the javadoc tool generates HTML documentation from Java source code. There are other tools for Java too, and also for other programming languages. C/C++ programmers often use JavaDoc comments with tools such as Doxygen. Doxygen is a kind of uber-javadoc. It can generate HTML documentation, but also LaTeX, RTF, PDF, and UNIX man pages. It supports Java, and also C/C++, Objective-C, Python, IDL, and to some extent other languages too. See http://www.stack.nl/~dimitri/doxygen/ for more information about Doxygen. As it happens, Slick-C itself also uses a documentation system based on JavaDoc, which enables a lot of SlickEdits online help to be generated automatically from the Slick-C source code. And, as we expect from Microsoft, C# also has its own incompatible version of the same idea, called an XMLDoc comment. SlickEdit supports JavaDoc comments for Java, C/C++, and Slick-C, and XMLDoc comments for C#. To add a JavaDoc comment to a member:

1. 2. 3. 4.

Insert a line above the member. Type /*. SlickEdit adds the closing */. Type a second *. This indicates to SlickEdit that the comment is a JavaDoc comment. Press Enter to split the line. SlickEdit fills in a JavaDoc comment template, with relevant information from the signature of the member. An example is shown in Figure 9-41. The cursor is placed at the start of the JavaDoc description, ready for you to start typing.

Figure 9-41

Configuring Comments
Comment behavior is configured per extension, in the Extension Options dialog. There are two tabs. The first tab, Comments, shown in Figure 9-42, defines several different configuration options for comments. There is also a string editing option hidden away in this tab, which controls whether strings are split when you press Enter.

195

Part II: Using SlickEdit


See the online Help for detailed descriptions of these options.

Figure 9-42

The second tab, Comment Wrap, is shown in Figure 9-43. This tab controls which types of comments have wrapping enabled and what margins to use. Again, the online Help has a lot of documentation about these options.

Figure 9-43

196

Chapter 9: Editing Code

Summar y
In this chapter, we covered several of SlickEdits features for editing code in specific programming languages. SlickEdits support for programming languages ranges from simple color syntax highlighting, which works with virtually any programming language, through to advanced features specific for major languages that SlickEdit targets, such as C/C++ and Java. The advanced features in SlickEdit in many areas match or rival those found in IDEs. Combined with SlickEdits superior text editing and navigation, this is what makes SlickEdit a compelling generalpurpose programming editor. Code is not the only part of a programmers life. Most programmers also spend much time dealing with data in one form or another. In the next chapter, we look in detail at SlickEdits perhaps surprising capabilities for dealing with data.

197

Editing Data
Programmers frequently have to deal with data. Much of your programming job may be concerned with manipulating data, whether the data are in a corporate database, read from an instrument, or generated to describe a 3D world in a game. Of course, if a certain task is within the scope of the main project youre working on, you will write code for the task in your main programming language it will be a feature of the application youre building. Often, though, you find you need to do something quick and ad hoc with some data. Someone sends you a spreadsheet with some test data that need to be entered in the database. You might need to sort a log file and count the number of error messages in it. You might want to take a directory listing and generate a one-off script from it. These are just some of many different scenarios that seem to arise daily in many programming or IT jobs. Different programmers have different preferences for dealing with these situations. UNIX gurus are usually proficient with tools such as sed and awk, not to mention more powerful scripting languages, such as Perl, Python, or Ruby, all of which are well suited for quick data hacks. Windows programmers might prefer a more interactive environment such as Microsoft Excel for manipulating data that are in rows and columns. SlickEdit provides several features that help out with ad hoc or one-off data manipulation. Using SlickEdit for one-off data jobs can provide an appealing mix of interactivity and scripted automation. This chapter describes some of SlickEdits features that are useful for data, and also covers some techniques you can use to make ad hoc data manipulation as quick and easy as possible. We start by discussing more of what you can do with block selections, which are one of SlickEdits most fundamental tools for working with data. Next, we cover several tools that SlickEdit provides for working with data, for filling in data, sorting data, generating data, and calculating with data. Finally, we present three techniques in detail that can be used for working with data generally. This chapter presents some further Slick-C code as examples. It also relies on the code in
wrox_next_prev_word.e from Chapter 6.

Part II: Using SlickEdit

Block Selection
The most fundamental tool for dealing with data is the block selection. Using block selections, you can: Reorder columns of data by moving blocks left or right. Remove unwanted columns. Add data in columns, such as commas and quote marks. Sort data. Generate sequences. Search and replace within columns.

Using combinations of features with block selections, you can perform an unlimited variety of editing tasks in an intuitive, interactive way.

Moving, Copying, and Deleting with Block Selections


The basic operations with block selection are the same as with other kinds of selection, but work in a particular way with block selection. Consider the data shown in Figure 10-1. A column of data is selected, 10 lines by 3 columns. Well use this selection and starting position to illustrate the various move, copy, and delete commands.

Figure 10-1

Use move-to-cursor (WROX: Alt+M) to move the selected block to the cursor position, moving existing text to the right. Figure 10-2 shows the result of a move.

Figure 10-2

200

Chapter 10: Editing Data


Use copy-to-cursor (WROX: Alt+C) to copy the selected block to the cursor position, moving existing text to the right. Figure 10-3 shows the result of a copy.

Figure 10-3

Use cut (Ctrl+X or WROX: Alt+D) to delete the selected block. Figure 10-4 shows the result of a cut. The deleted block is placed in the clipboard. If you paste from the clipboard back into SlickEdit, the paste is treated as a block.

Figure 10-4

Just as they are with line or character selections, the move-to-cursor and copy-to-cursor commands with block selections are nondestructive, in that they do not delete any existing text. Instead, these commands move existing text to the right. There are corresponding commands that overwrite the existing text. Again, starting from Figure 10-1: Use adjust-block-selection (WROX: Alt+A) to move the selected block to the cursor position, overlaying existing text and filling in the original position with spaces. Figure 10-5 shows the result of a block adjustment.

Figure 10-5

Use overlay-block-selection (WROX: Alt+O) to copy the selected block to the cursor position, overlaying existing text. Figure 10-6 shows the result of a block overlay.

201

Part II: Using SlickEdit

Figure 10-6

These commands are intelligent enough to handle source/destination conflicts.

Navigating Block Selections


If the data you are working on fill the entire buffer, you can simply use the normal buffer commands to get to the top or bottom: Use top-of-buffer (Ctrl+Home) to get to the top of the buffer. Use bottom-of-buffer (Ctrl+End) to get to the bottom of the buffer.

The Preserve column on the top/bottom setting controls the position of the cursor when using these commands. The setting is found in the More tab of the General Options dialog (Tools Options General). The default value of this setting is off, which means that the cursor will go to the first column of the first line when you use top-of-buffer, and to the last column of the last line when you use bottom-of-buffer. Its usually better to turn this setting on, especially if you are editing columns of data. This configuration setting can also be changed by setting the macro variable def_top_bottom_ style to 1. On the other hand, the data are often only a part of the buffer. There may be multiple chunks of data within a single buffer. In this case, these selection navigation commands are useful: Use begin-select (WROX: Alt+Y) to move the cursor to the top-left of a selected block. Use end-select (WROX: Alt+E) to move the cursor to the bottom-right of a selected block.

Bookmarks can also be useful if you are editing a large amount of data. See Chapter 6 for more information about bookmarks.

Entering Data in Columns


Its often necessary to enter text repeatedly into every line. SlickEdit has a couple of ways of doing this, using block selections. Which you choose depends on your preferences, and several considerations. Use fill-selection (WROX: Alt+F) to fill a block with a particular character. Use block-insert-mode (Edit Other Block Insert Mode) to put SlickEdit into block insert mode.

202

Chapter 10: Editing Data

Filling Data
The fill-selection command offers a simple way to fill a block with a single character. Usually the block is a single column, and the character is some kind of punctuation, such as a comma or quotation mark. The command can also handle blocks that are more than one column, and occasionally this is useful. To fill a region with a character:

1. 2. 3.

Make a block selection. Invoke fill-selection (WROX: Alt+F). SlickEdit prompts you, Type a key to fill mark with. Type a key. The selection is filled.

You can use fill-selection to type words or other text into columns. The procedure is like this:

1. 2. 3. 4.

Make a block selection. Invoke fill-selection to type in the last character of the word. Invoke shift-selection-right (Shift+F8) to move the text, including the character you typed. Repeat Steps 2 and 3 with each character, typing from the end of the word to the beginning.

This is not a very convenient procedure, because you need to type the word backward. Usually its much easier to use block insert mode.

Using Block Insert Mode


Block insert mode is a powerful and intuitive way to enter text or data in columns. Using block insert mode, you can type, edit, and move the cursor as if you were typing on one line, but SlickEdit applies your changes to all lines in the selection. To use block insert mode:

1. 2. 3.

Make a block selection. Invoke block-insert-mode (Edit Other Block Insert Mode). SlickEdit prompts you with Block/column insert mode active. Press ESC when done. Type characters to insert them in the column. The selection moves as you type.

While in block insert mode, you can move the selection left and right using cursor-left and cursorright (the left and right arrow keys). You can use Delete and Backspace to delete characters. You can also use undo to undo mistakes. You can quit the block insert mode using the Escape key, or by deselecting the block.

203

Part II: Using SlickEdit


Block insert mode is implemented in a rather special way. The block-insert-mode command actually contains its own event loop, and listens directly for keyboard events. This is different from most parts of SlickEdit. You may find that while in block insert mode, if you use commands (i.e., press keys) other than the ones mentioned here, you get funny characters on the screen. If this happens, use undo to undo the changes. Another consequence of the way in which block insert mode works is that you cannot record macros that use block insert, and you cannot play macros to enter text while in block insert mode. If you want to mix macros with inserting text into columns, use fill-selection. (Block insert mode actually uses fill-selection itself.)

Sor ting Data


Sorting is not a common part of programming or text editing, but it is very common when dealing with data. SlickEdit provides several commands for sorting: Use sort-buffer to sort the entire buffer. Use sort-on-selection to sort using a selection as the key. Use sort-within-selection to sort within a line or block selection.

The most useful of these commands for data is sort-on-selection. Use sort-on-selection to sort data in a particular column. SlickEdits sorting algorithm is stable, which means that lines that have equal sort keys remain in the same relative order after a sort. Its also worth remembering that undo works fine after sorting. There are several options that can be used with any of the sorting commands. They are fully documented in the online documentation. There is also a GUI interface to the sorting commands, shown in Figure 10-7. You can invoke the GUI interface with the command gui-sort, or via Tools Sort.

Figure 10-7

204

Chapter 10: Editing Data

Generating Data
When dealing with data, it is often necessary to generate a sequence of numbers. Here are some examples: Generating a sequence of primary keys for some test data. Generating a sequence of years. Generating a sequence of dates.

SlickEdits enumerate command helps with these tasks. To use enumerate to generate a sequence of data, follow these steps:

1. 2.

Make a block selection where you want the data generated. Use the enumerate command to generate the data.

The enumerate command has the following arguments:


start the starting number. Optional, defaults to 0. increment the number to increment by. Optional, defaults to 1. width the number of digits to pad with leading zeros. Optional, default does not add leading

zeros. Figure 10-8 shows the result of the command enumerate 100 5 3, with a 10 3 block selection.

Figure 10-8

The enumerate command has some additional options supporting hex output and flags for C/C++ programs. Consult the online Help for the full list. In SlickEdit 11, there is a bug in SlickEdits enumerate command, that causes the padding option of enumerate not to work properly. This bug has been fixed in version 12, but is easy to patch for version 11. See http://community.slickedit.com/index.php?topic=1058.msg4491#msg4491 for details. There is also a GUI interface to enumerate, shown in Figure 10-9. You can invoke the GUI interface with the command gui-enumerate (Edit Other Enumerate).

205

Part II: Using SlickEdit

Figure 10-9

Calculating with Data


Generally speaking, text editors are not strong for doing calculations. Thats what spreadsheets are for. However, it often happens that you need a quick calculation done on data that are already in the editor, such as adding a column of numbers that are data in your file. SlickEdit provides some basic support for these tasks. Suppose we have some invoice data in a file as shown in Figure 10-10.

Figure 10-10

To add up the shipping charges from these data:

1. 2. 3.

Make a block selection that includes the shipping charge column and nothing else. Move the cursor to the line after the shipping charges, under the shipping charge column. Invoke the add command on the command line. SlickEdit adds up the numbers and places the sum into the buffer at the cursor position. The result is shown in Figure 10-11.

Figure 10-11

206

Chapter 10: Editing Data


SlickEdit can compute more elaborate expressions too. To compute the entire invoice cost from the data above:

1. 2. 3. 4. 5. 6. 7.

Make a block selection one column wide between the price and quantity columns. Invoke the fill-selection command (WROX: Alt+F). SlickEdit prompts you for a character. Type an * to fill the selection with the multiplication symbol. Invoke deselect to drop the selection. Make a new block selection that includes all the data. Move the cursor to the line after the data, under the price column. Invoke the add command on the command line. SlickEdit adds up the numbers, multiplying the prices by the quantities, and places the sum into the buffer at the cursor position. The result is shown in Figure 10-12.

Figure 10-12

The operators supported by the add command are those of the Slick-C programming language. See the online Help for more details. Usually you will not use SlickEdit as a spreadsheet. However, the ability to add up a column of numbers without leaving the editor is sometimes useful.

Manipulating Data
In this section, we look at several techniques for manipulating data in columns, beyond the basics weve covered so far. These represent ways in which you can add, change, and restructure data. The techniques fall into three basic categories: Using SlickEdits block selections to manipulate columns of data interactively and to type into columns. Using keyboard macro record/playback to repeat operations on data. Using search and replace to manipulate data.

207

Part II: Using SlickEdit


Were going to illustrate these three techniques using a simple example. We start with a file that contains some data representing codes and start dates, like this:
GBA7 GBX2 GBX6 GBY3 GBY6 GBY7 GBY8 GBZ2 GBZS GCB5 02/12/2007 02/14/2007 04/01/2007 03/07/2007 03/17/2007 02/14/2007 02/09/2007 02/15/2007 04/03/2007 05/06/2007

These data may have been extracted from a database, pasted from a spreadsheet, or sent in an e-mail. Notice that the dates are in the format widely used in the United States, which is not a useful format for storing in a computer. For our examples, we are going to transform these data into XML elements, like this:
<code <code <code <code <code <code <code <code <code <code id=GBA7 id=GBX2 id=GBX6 id=GBY3 id=GBY6 id=GBY7 id=GBY8 id=GBZ2 id=GBZS id=GCB5 start_date=2007-02-12/> start_date=2007-02-14/> start_date=2007-04-01/> start_date=2007-03-07/> start_date=2007-03-17/> start_date=2007-02-14/> start_date=2007-02-09/> start_date=2007-02-15/> start_date=2007-04-03/> start_date=2007-05-06/>

We need to reformat the dates into ISO format, and add XML markup: punctuation, elements, and attributes. For the purpose of the example, were working with only 10 lines of data. In practice, the techniques can be used for many more lines. Some techniques work well with dozens or even hundreds of lines. Other techniques can be used with thousands of lines. In our example, we are converting space-delimited data to XML, but this is just one of an unlimited variety of conversions we could do. The same techniques work equally well for many other cases.

Block Editing
SlickEdits block editing feature is the most straightforward, intuitive way of dealing with columns of data. With block editing, you manipulate columns of data by: Using move, copy, and delete commands to rearrange columns. Using block fill and block insert to add or remove delimiters and other text.

208

Chapter 10: Editing Data


The main advantages of the block editing technique are: It is intuitive and interactive. It works well in combination with other block techniques. It works reasonably well with medium amounts of data.

Block editing is intuitive and interactive because you see the changes on the screen as you edit. You manipulate columns directly. You can use undo if you make a mistake. Often you need to add or move column data in conjunction with other changes, such as sorting, generating sequence numbers, or changing tabs to commas. In these cases, you may find it easiest to use block selections for all the editing, rather than mixing techniques. Block commands are reasonably fast even with thousands of lines. For larger files, you may find that block commands are too slow. See Large Data Files below for some information on performance with large files. The main disadvantages of the block editing technique are: It doesnt work if the data are not aligned. It is not automatically repeatable.

If data are not aligned, you cannot select the columns. Examples of cases where this happens are: A variable number of tabs are used to indent tabular data. Columns are variable length, so that the delimiters do not line up in the same columns.

You may be able to align the data before editing, which can make it a lot easier to use block selections. We discuss one way of doing this, with SlickEdit macros, in the section Aligning Data below. Block edits, being interactive, are not as repeatable as commands. In fact, because of the way in which block insert mode is implemented, it is not able to be used in conjunction with macros. In practice, this is not a serious limitation, since block insert mode is interactive by nature. If macros need to work with blocks, they can use many other block commands, including select-block and fill-selection, thus achieving all the same things that are done with block insert mode.

Example
In this example, we go through the steps to transform our test file to XML data using block editing. We begin with the data, as shown in Figure 10-13. Well do the job in two parts. The first part is to use block selection and movement commands to reorder the fields of the date column into ISO format. The second part is to use block insert mode to add the XML markup around the data. Here are the steps for the first part:

1. 2.

Move the cursor to the beginning of the 02 on the first line. Invoke select-block (WROX: Alt+B) to start a block selection for the month column.

209

Part II: Using SlickEdit

Figure 10-13

3. 4. 5.

Invoke bottom-of-buffer (Ctrl+End) to move the cursor to the bottom of the file. Move the cursor to the 5 in the 05 on the last line. Invoke select-block to lock the selection. The month column is selected, as shown in Figure 10-14.

Figure 10-14

6. 7. 8.

Invoke top-of-buffer to return to the first line. Invoke end-line to move the cursor to the end of the line. Invoke move-to-cursor (WROX: Alt+M) to move the month column to the end. Figure 10-15 shows the result.

Figure 10-15

9. 10. 11. 12. 13. 14.

Invoke deselect (WROX: Alt+U) to drop the selection, since were going to start another one. Move the cursor back to the beginning of the 12 on the first line. Invoke select-block to start a block selection for the day column. Invoke bottom-of-buffer to move the cursor to the bottom of the file. Move the cursor to the 6 in the 06 on the last line. Invoke select-block to lock the selection. The day column is selected, as shown in Figure 10-16.

210

Chapter 10: Editing Data

Figure 10-16

15. 16. 17.

Invoke top-of-buffer to return to the first line. Invoke end-line to move the cursor to the end of the line. Invoke move-to-cursor to move the day column to the end. Figure 10-17 shows the result.

Figure 10-17

We have now moved the date fields into the correct order. What remains is to remove the left-behind slash characters, and add the XML markup and hyphen (-) separators. Well use block insertion mode to do all that. Make sure you still have a block selection on the day column, and then follow these steps:

1.

Invoke Edit Other Block Insertion Mode. SlickEdit switches to block insertion mode, as shown in Figure 10-18. The status bar also indicates that block insertion mode is active, as shown in Figure 10-19.

Figure 10-18

Figure 10-19

2.

Invoke cursor-left (left arrow key) repeatedly to move the block to the left, until it is in the first column, as shown in Figure 10-20.

211

Part II: Using SlickEdit

Figure 10-20

3.

Type <code id=. Block insertion adds the text to all lines, as shown in Figure 10-21.

Figure 10-21

4.

Invoke cursor-right (right arrow key) repeatedly to move the block over until it is after the code field, as shown in Figure 10-22.

Figure 10-22

5. 6.

Invoke delete-char (Delete key) three times to delete the space and the two unwanted slash characters. Type start_date=. Block insertion adds the text to all lines, as shown in Figure 10-23.

Figure 10-23

7. 8.

Invoke cursor-right four times to move the cursor past the year field. Type the hyphen date separator.

212

Chapter 10: Editing Data


9. 10. 11. 12.
Invoke cursor-right twice more to move the cursor past the month field. Type the hyphen date separator again. Invoke cursor-right twice more to move the cursor past the day field. Type /> to complete the XML markup. The final version is shown in Figure 10-24.

Figure 10-24

Discussion
We can see that block selections, combined with the block movement and fill commands and block insertion mode, make an easy and appealing way to edit small-to-medium amounts of data.

Macro Record and Playback


Macro record and playback is often a quick and convenient way to do the same operations to a set of lines. For example, it is an easy way to add commas at certain positions on each line. The basic idea of macro record and playback is this: You start recording on the first line, do what you need done, then finally move the cursor to the beginning of the next line and finish recording. You can now play back the macro for each line. The main advantages of the macro record and playback technique are: It is somewhat intuitive and interactive. It is often more flexible than block editing. It can often be used even if data are not aligned. It can be made repeatable.

Because you get to see every step as its done for the first line, macro recording is intuitive. Even if you make a mistake, you can often correct it without aborting recording the macro. For example, the undo command can be recorded as part of a macro. You do need to take care that the steps you record will work correctly for all lines, not just the first line. For example, if data are not aligned, you cannot rely on a certain number of left or right cursor movements to move the cursor to a given field the field may start in a different column on different lines. Instead, you can use commands such as prev-word and next-word to move among columns flexibly. Doing this requires a clear understanding of how these commands work.

213

Part II: Using SlickEdit


If you have recorded a complex sequence of commands into a macro and you think you might use the same sequence again, you can save the macro with a name and use it again later. The main disadvantages of the macro record and playback technique are: It is not automatically repeatable. It doesnt work well with large amounts of data.

If you record a new macro without saving your current one, you have to re-record all the commands over again. See Chapter 1 for an introduction to saving recorded macros.

Example
In this example, we go through the steps to transform our test file to XML data using macro record and playback. We begin with the same data again that were shown in Figure 10-13. To use the macro record and playback technique, we begin by recording the necessary operations on the first line:

1.

Invoke record-macro-toggle (Ctrl+F11). SlickEdit shows the message Recording macro in the message area and the macro recording indicator in the status bar, as shown in Figure 10-25.

Figure 10-25

2.

Type the first part of the text: <code id=. This is shown in Figure 10-26.

Figure 10-26

3. 4.

Invoke cursor-right (right arrow) to move the cursor past the code. Type the next part of the text: start_date=. This is shown in Figure 10-27.

Figure 10-27

214

Chapter 10: Editing Data


5. 6. 7. 8.
Invoke cursor-right to move the cursor to the beginning of the year field. Invoke select-block (WROX: Alt+B) to start a block selection. Invoke cursor-right three more times to move the cursor to the end of the year field. Invoke select-block to lock the block selection on the year, as shown in Figure 10-28.

Figure 10-28

9. 10.

Invoke cursor-left to move the cursor back to the character after the quote mark for the XML date attribute. Invoke move-to-cursor to move the year field to the correct place, as shown in Figure 10-29.

Figure 10-29

11. 12. 13.

Invoke deselect (WROX: Alt+U) to drop the selection. Invoke insert-toggle (Insert key) to switch to overwrite mode. The cursor should change to a block cursor. Use delete, cursor-right and overtype the slashes with hyphens, to change the rest of the date to ISO format, and complete the XML element. The completed line is shown in Figure 10-30.

Figure 10-30

14. 15. 16.

Invoke insert-toggle to switch back to insert mode. Invoke begin-line-text-toggle (Home) to move the cursor back to the start of the line. Invoke cursor-down (down arrow) to move the cursor to the start of the second line.

215

Part II: Using SlickEdit


17.
Invoke record-macro-toggle again to finish recording the macro. SlickEdit displays the Save Macro dialog, shown in Figure 10-31.

Figure 10-31

18.

Press Escape to save the macro as the last macro. We dont need to give this macro a name, since we are not keeping it permanently.

At this point, weve done all the edits we need to on the first line. Figure 10-32 shows the buffer, with the cursor at the beginning of the second line.

Figure 10-32

Its important that we moved the cursor to the correct position on the second line before we finished recording the macro. This is so that we can now invoke the macro repeatedly to edit the rest of the file:

19. 20.

Invoke record-macro-end-execute (Ctrl+F12) to run the macro. The same edits are done for the second line, as shown in Figure 10-33. Invoke record-macro-end-execute eight more times to complete the file. The finished file is the same as with block editing.

Figure 10-33

216

Chapter 10: Editing Data


Discussion
Macro record and playback is a convenient solution for data editing and can be more flexible than block editing if fields are not aligned. Its not necessary always to use cursor-left and cursor-right to move the cursor. These commands can move the cursor a fixed number of columns. In contrast, the prev-word and next-word commands are often more useful for moving the cursor a fixed number of fields, regardless of their alignment. The prev-word and next-word commands are bound to Ctrl+Left and Ctrl+Right by default in the CUA emulation. In the WROX emulation, they are bound to Alt+Left and Alt+Right, and the alternative commands wrox-prev-whitespace-word and wrox-next-whitespace-word are bound to Ctrl+Left and Ctrl+Right. Both sets of word movement commands are useful for macro recording and playback, in different situations. See Chapter 6 for a more detailed discussion of these word movement commands. Macros can also help with aligning data. See the section below, Aligning Data. When using the macro record and playback technique to work with data, the pattern followed is often to start with the cursor at the beginning of the line, do some edits, then move the cursor to the beginning of the next line before finishing the macro. As we saw, this movement to the next line can be done with the begin-line-text-toggle and cursor-down commands. If youre doing this a lot, it can be worth creating a short macro for taking the cursor straight to the first column of the next line and binding that macro to a key of its own. The following code does this, binding the command wrox-start-of-next-line to Alt+Enter.
_command void wrox_start_of_next_line() name_info(,VSARG2_REQUIRES_MDI_EDITORCTL) { p_line++; p_col = 1; } def A-ENTER=wrox_start_of_next_line;

See Chapter 16 for more information about macros and several more examples of macros that are useful for working with data. Using record-macro-end-execute is fine if you only have a few dozen lines or so. If you have more lines, you can automate the repetition of the recorded macro. The following code is a simple command, wrox-repeat-n, that executes a given command n times:
_command void wrox_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; }

217

Part II: Using SlickEdit


int i; for (i = 0; i < n; i++) { execute(command); } }

Using this command, we can write this command, wrox-repeat-n-last-macro, to execute the last recorded macro n times:
_command void wrox_repeat_n_last_macro(_str args = null) name_info(,VSARG2_EDITORCTL) { wrox_repeat_n(args :+ last_macro); }

SlickEdits syntax assistance can sometimes get in the way when you are using macro record and playback, particularly if you are doing data-oriented operations on a lot of lines. For example, suppose you have the following data in a Java file:
SBL1 SJP1 VATS VBAT VBE2 35.87 34.39 36.17 37.57 38.80

Suppose you want to convert these lines into Java statements like this:
result.add(energy(tni(SBL1), result.add(energy(tni(SJP1), result.add(energy(tni(VATS), result.add(energy(tni(VBAT), result.add(energy(tni(VBE2), ma(35.87))); ma(34.39))); ma(36.17))); ma(37.57))); ma(38.80)));

If you record a macro to add the code to the data for a single line, it comes out something like this:
_command last_recorded_macro() name_info(,VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL) { _macro(R,1); keyin(result); last_event(name2event(.));java_auto_codehelp_key(); keyin(add); last_event(name2event(());c_paren(); keyin(energy); last_event(name2event(());c_paren(); keyin(tni); last_event(name2event(());c_paren(); keyin(\); next_word(); keyin(\); last_event(name2event()));keyin_match_paren(); last_event(name2event(,));java_comma(); cursor_right(); keyin(ma); last_event(name2event(());c_paren();

218

Chapter 10: Editing Data


keyin(\); end_line(); keyin(\); last_event(name2event()));keyin_match_paren(); last_event(name2event()));keyin_match_paren(); last_event(name2event()));keyin_match_paren(); keyin(;); begin_line_text_toggle(); cursor_down(); }

The calls to routines such as java_auto_codehelp_key(), c_paren(), and java_comma() implement SlickEdits syntax assistance. For a recorded macro, the syntax assistance is not required. In fact, it can sometimes cause a macro to behave incorrectly. In addition, the syntax assistance uses a lot of processing power and can slow down macro playback noticeably. To avoid these issues, switch the buffer to fundamental mode using the fundamental-mode command before recording the macro. Recorded in fundamental mode, the macro for the data operation above becomes:
_command last_recorded_macro() name_info(,VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL) { _macro(R,1); keyin(result.add(energy(tni(\); next_word(); keyin(\); last_event(name2event()));keyin_match_paren(); keyin(,); cursor_right(); keyin(ma(\); end_line(); keyin(\); last_event(name2event()));keyin_match_paren(); last_event(name2event()));keyin_match_paren(); last_event(name2event()));keyin_match_paren(); keyin(;); begin_line_text_toggle(); cursor_down(); }

This is significantly faster to execute. Once you are finished working with recorded macros, you can switch back to whichever mode the file was in previously. For example, to switch back to Java mode, use the java-mode command. There is also another opportunity for improvement in avoiding the calls to keyin_match_paren(). This feature provides visual assistance while you are typing. Again, it is not required in a recorded macro. To avoid generating these calls when recording, use the quote-key command (Ctrl+Q). Using quote-key for the closing parentheses, the recorded macro comes out like this:
_command last_recorded_macro() name_info(,VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL) { _macro(R,1); keyin(result.add(energy(tni(\);

219

Part II: Using SlickEdit


next_word(); keyin(\); keyin()); keyin(,); cursor_right(); keyin(ma(\); end_line(); keyin(\); keyin()); keyin()); keyin()); keyin(;); begin_line_text_toggle(); cursor_down(); }

This macro code is much more efficient to execute. In general, when you are using recorded macros and they are not running fast enough, or perhaps do odd things, you should check the generated macro source in lastmac.e. You may find that SlickEdit features are being invoked inadvertently. You can avoid many features if necessary by using the quote-key command.

Search and Replace with Data


Using search and replace in conjunction with block selection is one of the fastest and most powerful ways of manipulating data in SlickEdit. The main advantages of the search and replace technique are: It is very flexible, if you are good with regular expressions. It is relatively fast with large amounts of data. It is more repeatable.

You can use regular expressions to do a surprising amount of manipulation on a line. Users of UNIX tools such as sed and awk and users of dynamic languages such as Perl are aware of this. Once you master the arcane details of regular expressions, they are a very powerful tool. Regular expression search and replace is usually faster than other techniques for large files. If you use the command line for entering your Search and Replace command, it is stored there until it falls out of the command-line history. This makes it very easy to retrieve even complicated regular expression commands. You can change a command if necessary, and re-use it. The main disadvantages are: It is not interactive. It is relatively complex and unintuitive.

220

Chapter 10: Editing Data


You need to compose regular expression search and replace without seeing the results as you do it. This requires some planning and skill with regular expressions. Regular expression syntax is notoriously difficult to read. Simple expressions like /[A-Z][a-z]+/ (which matches a capitalized word) are easy enough. But search and replace expressions for data are usually a lot more complicated than that. For example, you can use a regular expression search and replace to re-format dates from local mm/dd/yyyy format to ISO yyyy-mm-dd format. A SlickEdit command for this is
c|(\:d\:d)/(\:d\:d)/(\:d\:d\:d\:d)|\3-\1-\2|u

This command does not deal with situations in which the day or month might be only one digit, rather than two. Nevertheless, if you are comfortable with regular expressions, they are a powerful way to manipulate data. SlickEdits Regex Evaluator tool window can help with figuring out regular expressions. We cover it in Chapter 15. Search and replace is probably the most complex way of dealing with data. Once you get beyond the capabilities of search and replace, you are probably beyond using the editor itself. Instead, you may need to write a custom program for data manipulation.

Example
In this example, we will use search and replace to transform our test file into XML data. We will do it in two steps. The first step will be to change the date into ISO format. The second step will be to add the XML markup. To use the search and replace technique to transform the file:

1. 2.

Move the cursor to the top of the file. Invoke the following command to change the dates from the U.S. format into ISO format:

c |(\:d\:d)/(\:d\:d)/(\:d\:d\:d\:d)|\3\-\1-\2|u

SlickEdit asks you to confirm the search and replace, as shown in Figure 10-34.

Figure 10-34

3.

Press g to confirm all changes. SlickEdit replaces all the dates with ISO-formatted dates, as shown in Figure 10-35.

221

Part II: Using SlickEdit

Figure 10-35

4. 5.

Move the cursor back to the top of the file. Invoke the following command to add the XML markup:

c |(\:a+) (.*)|<code id=\1 start_date=\2/>|u

SlickEdit asks you to confirm the search and replace again.

6.

Press g to confirm all changes. The job is done.

Discussion
Regular expressions can quickly become unwieldy when used for complex data edits. Here are a few techniques that can help you manage them: If a job is complex, use several search and replace commands rather than combining all edits into a single command. Store the commands in a temporary file while you work, so that you can edit them and re-use them. Remember that undo can be used to roll back search and replace changes. The Regex Evaluator tool can be helpful. See Chapter 15 for more details.

Aligning Data
Frequently data are not properly aligned for using block editing. Usually this occurs when fields are not all the same length. Consider the following data:
GBA07 02/12/2007 279.77 35080.13 125.39 GBX002 02/14/2007 280.98 36381.8 129.48 GBX6 04/01/2007 0.1 21.45 129.48 GBY13 03/07/2007 15.23 1829.22 120.09 GBY16 03/17/2007 69.59 10058.89 144.55 GBY7 02/14/2007 0.21 25.76 120.36 GBY008 02/09/2007 0.64 90.6 141.39 GBZ02 02/15/2007 25 3542.64 140.49 GBZS 04/03/2007 30.48 4338.75 142.37 GCB15 05/06/2007 42.67 6094.2 142.81

222

Chapter 10: Editing Data


In this example, we have some CSV data that need to be converted to another format, as before. But this time, the data are not aligned. This does not affect the search and replace method of conversion much. It may or may not affect the macro record and playback method, depending on how good we are about getting from one field to another. It severely affects how we can work with block selections, though. One approach we can take to this problem is to align the data before we do anything else. With the help of some macros, this is not difficult. The code below defines two alignment commands: Use wrox-align-left-with-field-above to left-align the current field with the field above. Use wrox-align-right-with-field-above to right-align the current field with the field above.

If you load the code, these commands will be bound to Alt+Shift+L and Alt+Shift+R.
_command wrox_align_left_with_field_above() name_info(,MACRO_ARG2|MARK_ARG2) { if (p_line < 2) { message(This function does not work on line zero or one.); return 0; } // save current position etc push_bookmark(); int cur_line = p_line; _str cur_char = get_text(); // move forward to non-whitespace on current line if (cur_char == || cur_char == \t || cur_char == \n) { wrox_next_whitespace_word(); } // remember column of stuff to move int cur_col = p_col; // go to next field on line above cursor_up(); wrox_next_whitespace_word(); // if we stayed on the same line when moving forward by a field ... if (p_line == cur_line-1) { // shift the text, returning to the original position afterward int diff = p_col - cur_col; pop_bookmark(); push_bookmark(); _insert_text(substr(, 1, diff, )); pop_bookmark(); } else { // return to the original position pop_bookmark(); } } _command wrox_align_right_with_field_above() name_info(,MACRO_ARG2|MARK_ARG2) {

223

Part II: Using SlickEdit


if (p_line < 2) { message(This function does not work on line zero or one.); return 0; } // save current position etc push_bookmark(); int cur_line = p_line; // move forward to end of next field on current line next_word(); // remember column of stuff to move int cur_col = p_col; // go to end of next field on line above cursor_up(); next_word(); int diff = p_col - cur_col; // if we stayed on the same line when moving forward by a field ... if (diff > 0 && p_line == cur_line-1) { // shift the text, returning to the original position afterward pop_bookmark(); push_bookmark(); _insert_text(substr( , 1, diff, )); pop_bookmark(); } else if (diff < 0 && p_line == cur_line-1) { pop_bookmark(); int i; for (i=0; i<(-diff); i++) { _delete_char(); } } else { // return to the original position pop_bookmark(); } } // default key bindings to alignment commands defeventtab default_keys; def A-S-L= wrox_align_left_with_field_above; def A-S-R= wrox_align_right_with_field_above;

In this example, well also use the supplied word-movement command wrox-next-whitespace-word, since its easier to use than SlickEdits own next-word for moving among space-delimited fields. We could use SlickEdits next-word command, but wed have to type more keystrokes because it navigates punctuation characters within fields, in this case the slash characters in the date fields and the decimal points in the numeric fields.

224

Chapter 10: Editing Data


To use the alignment macros to align the data in the test file, follow these steps:

1.

Insert some spaces to space out the data in the top column, as shown in Figure 10-36. We choose the spacing so that each field in the following lines will move to the right to become aligned.

Figure 10-36

2. 3. 4. 5.

Place the cursor at the start of the second line. Invoke record-macro-toggle (Ctrl+F11). SlickEdit shows the message Recording macro in the message area and the macro recording indicator in the status bar. Invoke wrox-next-whitespace-word (Ctrl+Right), to move the cursor to the beginning of the date field. Invoke wrox-align-left-with-field-above (Alt+Shift+L), to align the date field with the one above, as shown in Figure 10-37.

Figure 10-37

6. 7.

Invoke wrox-next-whitespace-word twice more, to move the cursor to the beginning of the first numeric field. Invoke wrox-align-right-with-field-above (Alt+Shift+R), to align the numeric field with the one above. The field, being numeric, is aligned on the right-hand side, before the decimal point. The result is shown in Figure 10-38.

Figure 10-38

225

Part II: Using SlickEdit


8. 9. 10. 11.
Repeat Steps 6 and 7 two more times to align the other two numeric fields. Invoke begin-line-text-toggle (Home) to move the cursor back to the first column. Invoke cursor-down (down arrow) to move the cursor to the beginning of the next line. Invoke record-macro-end-execute (Ctrl+F12) to save the macro and execute it for the third line of data. Figure 10-39 shows the file after the third line has been aligned.

Figure 10-39

12.

Invoke record-macro-end-execute seven more times to align the rest of the lines. Figure 10-40 shows the finished result.

Figure 10-40

The alignment commands always move text to the right. Afterward, we may end up with extra white space in columns, as is shown in Figure 10-40. We can now use block selection and deletion to get rid of this white space if necessary. Following alignment, we can use block editing to manipulate the data further. Alternatively, the alignment commands can be combined with other commands during macro recording and playback to perform combinations of edits.

Large Data F iles


The different techniques presented here perform at quite different speeds, particularly for large files. Macro playback is the slowest technique and is probably best avoided for files with more than 1,000 lines of data. Block editing is the next fastest and could be used for files up to around 10,000 lines, sometimes more. Search and replace is quite fast and usable with files containing 100,000 lines or more. Table 10-1 compares the performance of the three techniques. I ran all three techniques via a benchmarking macro. I used the same data and conversion as presented in the Data Manipulation section, but duplicated to a large number of lines.

226

Chapter 10: Editing Data


Table 10-1
Technique Block Editing Macro Playback Search and Replace 100 Lines 0:00 0:00 0:00 1,000 Lines 0:01 0:04 0:00 10,000 Lines 0:10 0:33 0:00 100,000 Lines 0:06

Undo is available after any of these edits, and typically takes a similar amount of time as the edit itself. Interestingly, disabling undo seems to make little difference to the performance of these edits, at least for these examples.

Here is the code for the (very simple) benchmarking macro:


_command void wrox_benchmark(_str command = null) name_info(COMMAND_ARG,VSARG2_EDITORCTL) { if (command == null) { message(I need a command.); return; } long start = (long) _time(G); execute(command); long finish = (long) _time(G); long elapsed = finish - start; message(Command [ :+ command :+ ] took :+ elapsed :+ seconds.); }

Summar y
In this chapter, we have taken a detailed look at SlickEdits capabilities for editing data. Editing data is characterized by data in columns or fields, and repetitive editing over a number of lines. We looked at some of the basic tools SlickEdit provides, most of which are used in conjunction with block selections. Then we studied three distinct techniques for manipulating data with SlickEdit: block editing, macro record and playback, and search and replace. Each of these techniques is useful for repetitive edits on a number of lines. We also saw how macros can be used to align data to make them more amenable to block editing. This concludes our three chapters on general editing features. The next chapter covers the more specific topics of aliases and templates.

227

Aliases and F ile Templates


Programming often involves creating certain constructs repetitively, but with variations. For example, the classic C++ for() loop looks like this:
for (int i = 0; i < size; i++) { // do something }

Aside from the loop counter and the bound, and, of course, the body, a lot of the loop construct is boilerplate. Built-in syntax assistance in a programming tool such as SlickEdit can go a long way to reduce the amount of typing you have to do for these constructs, but there are always other constructs that you use that the tool doesnt know about. There are many examples of repetitive chunks of text other than programming constructs. In some cases, whole files follow a particular pattern, at least to begin with. Aliases and file templates are a couple of SlickEdit features that assist with repetitive text. The alias feature expands short abbreviations into larger chunks of text, and can be used for a wide variety of purposes. File templates allow you to define standard boilerplates for often-used file structures, in one or more files, and create new items based on them at any time. In this chapter, we look at the alias and template features, and see various applications of them.

Aliases
Aliases provide a powerful feature for expanding a shortcut or abbreviation into a larger string. Aliases work within the editor, but also work in many dialogs, such as the Open dialog. Things that aliases can be used for include: Frequently accessed directories and filenames. Frequently entered snippets of text, for example, copyright notices.

Part II: Using SlickEdit


Frequently used programming constructs. Overriding SlickEdit syntax expansion. Larger multiline chunks of text, such as file or function headings.

You can define global aliases that work everywhere in SlickEdit. You can also define aliases specific to file extensions. Aliases are basically a substitution mechanism. They also support features that allow you to customize the substituted text and control the cursor placement and movement after expanding them.

File Aliases
There are several configuration files I have to edit on my system quite often. A couple of examples are: The TCP/IP hosts file, located in C:\Windows\system32\drivers\etc\hosts. The Oracle lookup file tnsnames.ora, located on my system in C:\oraclexe\app\ oracle\product\10.2.0\server\NETWORK\ADMIN\tnsnames.ora.

These files are not part of any particular project; thus I cant get at them quickly using the Files tool window. And, as you can see, because the paths to these files are rather long (under Windows anyway), it can be frustrating to open them with the normal Open dialog. Aliases are ideal for this. To define an alias to the hosts file on Windows, follow these steps:

1.

Invoke alias (Tools Options Aliases). SlickEdit displays the Select Alias File dialog, shown in Figure 11-1.

Figure 11-1

2.

Select alias.slk and click OK. This is the file for global aliases; the other files define extension-specific aliases. SlickEdit displays the Alias Editor, shown in Figure 11-2. Several global aliases are predefined by SlickEdit.

230

Chapter 11: Aliases and File Templates

Figure 11-2

3. 4. 5. 6.

Click New. SlickEdit displays the Enter New Alias Name dialog. Enter hosts for the Alias Name. Click OK to close the Enter New Alias Name dialog. Enter C:\Windows\system32\drivers\etc\hosts in the text area for the alias text.

Its important to remember to click New and type in a new alias name before you type in the alias text. Its quite easy to type the new alias name into the filter field by mistake and overwrite the alias text of an existing alias.

7.

Click OK when you are finished.

The alias is added to the global aliases. To try it, open the hosts file using the Open dialog:

1. 2. 3. 4.

Invoke gui-open (Ctrl+O). Type hosts into the File name field. Invoke codehelp-complete (Ctrl+Space). SlickEdit expands the alias. Press Enter. SlickEdit opens the file.

Using aliases for directories like this is useful because it saves you having to navigate manually. It also prevents you from changing your working directory to the location of the file, which you might do inadvertently otherwise, while navigating to it.

231

Part II: Using SlickEdit


Aliases can be very useful for frequently accessed directories too. SlickEdit ships with some useful predefined directory aliases, including: bin for the SlickEdit executables directory. config for the users configuration directory. ma for the directory containing supplied macro source.

The config and ma aliases are frequently handy in the daily use of SlickEdit. When defining an alias for a directory, end the substitution value with the path-separator character (\ on Windows, / on UNIX or GNU/Linux). That gives the smoothest use in the Open dialog. After expanding the alias, you can start typing a further directory name or file name, or simply press Enter to have SlickEdit refresh the directory listing. When using aliases for directories or filenames containing spaces, it helps to start the substitution value with a double quote. That will help SlickEdit expand file names that you type in the Open dialog after expanding the alias. (If you dont use a double quote, SlickEdit thinks the space separates two different filenames.) Combining these tips, you might want to define a handy alias for your home directory on Windows. (On UNIX or GNU/Linux, you probably dont need this.) Call the alias home, and define its expansion as:
C:\Documents and Settings\username\

where username is your Windows username. You can use %USERNAME% instead for more flexibility if you wish, as we see below. Now if you expand the alias in the File name textbox of the fast Open dialog, SlickEdit refreshes the completions list immediately with matching files in your home directory.

Using Aliases in Code


Lets define an alias for a copyright notice. Suppose your company places a notice like this in the top of every file:
Copyright 2007 Acme Inc

You can save typing when entering the copyright notice by defining an alias for it. Use the Alias Editor to define an alias cpr for Copyright 2007 Acme Inc. The obvious problem with this alias is that it has the year hard-coded. Change the 2007 in the substitution value to %\d, like this:
Copyright %\d Acme Inc

Now, when you expand the alias, you get something like this:
Copyright 2007-04-05 Acme Inc

232

Chapter 11: Aliases and File Templates


The %\d is a special escape sequence for insert the date. The date is formatted yyyy-mm-dd, which is according to my Windows short date preference. SlickEdit offers several escape sequences in aliases, as shown in Table 11-1.

Table 11-1
Escape Sequence
%EnvVar% %\d %\e %\t %\f %\i %\b %\c %\l %\s %\n %\o %(ParamName) %\m macro % %\xcol %\x+col %\x-col %%

Description Insert the value of the EnvVar environment variable. Insert the date (locale preference format). Insert the date (MMDDYY). Insert the time. Insert the filename. Indent. Unindent. Place cursor. Preserves leading spaces at beginning of line. Preserves trailing spaces at end of line. Inserts current function name. Inserts current function name with signature. Argument replacement. Execute macro in-place. Moves the cursor to the specified column. Increment column by amount. Decrement column by amount. Inserts a percent character.

The %\m sequence is especially powerful. Because you can execute any macro, it opens up virtually unlimited possibilities. The macro can be a command, in which case it is executed in place in the buffer. The macro can also be a Slick-C function, in which case, its result is inserted into the buffer.

233

Part II: Using SlickEdit


Lets use the %\m escape sequence with a macro to change the copyright alias to insert only the current year, rather than the full date. Heres a Slick-C function that returns the current year as a string:
_str wrox_year() { _str mm; _str dd; _str yyyy; parse _date() with mm/dd/yyyy; return yyyy; }

Change the substitution value of the cpr alias to:


Copyright %\m wrox_year% Acme Inc.

Now try expanding the alias again. If the current year is still 2007 when you try it, you should get:
Copyright 2007 Acme Inc

The %\c escape sequence places the cursor by creating a hotspot. You can use this escape sequence multiple times to create multiple hotspots. You then use next-hotspot (Ctrl+[) to jump through the hotspots after expanding the alias. Well see more of this below.

Dynamic Directory Aliases


Using %\m, you can create some handy aliases that evaluate directories dynamically. The following two routines, wrox_project_dir() and wrox_buffer_dir(), return the current projects directory and the current buffers directory, respectively:
_str wrox_project_dir() { return maybe_quote_filename(strip_filename(_project_name, N)); } _str wrox_buffer_dir() { // switch windows to _mdi child to get buffer name, // so that this macro works in other windows int new_wid = _mdi.p_child; int orig_wid = p_window_id; p_window_id = new_wid; _str buf_name = p_buf_name; p_window_id = orig_wid; return maybe_quote_filename(strip_filename(buf_name, N)); }

You can define a pdir alias as:


%\m wrox_project_dir%

234

Chapter 11: Aliases and File Templates


You can also define a bdir alias as:
%\m wrox_buffer_dir%

Use these aliases when opening files, on the command line, or in the Open dialog. Sometimes you might want to have a directory alias relative to another directory alias. For example, you might like to create an hf alias for your hotfixes directory. The hotfixes directory is under the SlickEdit configuration directory, which is referenced by the config alias. You can use the expand-alias command inline to nest one alias in another, like this:
config%\m expand_alias%hotfixes

This alias works like this: The text config is entered into the buffer. The expand-alias command is invoked, which expands the config alias. The text hotfixes is inserted afterward.

Unfortunately, this doesnt quite work. The expand-alias command is defined to return an int, which is inserted into the buffer, giving a result like this:
C:\jhurst\My SlickEdit Config\12.0.2\0hotfixes

We can easily fix this with a simple wrapper for expand-alias:


_command void wrox_expand_alias_inline() name_info(,) { expand_alias(); }

The wrapper command returns void and therefore inserts nothing extra into the buffer. We can now define the hf alias with this expansion:
config%\m wrox_expand_alias_inline%hotfixes

And now the result of expanding the alias is correct:


C:\jhurst\My SlickEdit Config\12.0.2\hotfixes

Extension-Specific Aliases
Sometimes you might want the same alias to have different meanings depending on the current file extension. An example of this is an hdr alias that expands into a file header. For Java or C++ files, the alias should expand to:
// // // // $Id$ Copyright 2007 Acme Inc username date

235

Part II: Using SlickEdit


For SQL files, it should be this instead:
----$Id$ Copyright 2007 Acme Inc username date

To create the Java-specific alias, follow these steps:

1. 2. 3. 4. 5. 6.
// // // //

Invoke alias (Tools Options Aliases). SlickEdit displays the Select Alias File dialog. Select the java.als file for Java-specific aliases, and click OK. SlickEdit displays the Alias Editor. Click New to add a new Java alias. SlickEdit displays the Enter New Alias Name dialog. Enter hdr for the alias name. Click OK to close the Enter New Alias Name dialog. Enter the following text for the substitution value:
$Id$ Copyright %\m wrox_year% Acme Inc %USERNAME% %\d

7.

Click OK to save the alias and close the Alias Editor.

Now if you open a new file with extension .java, type in hdr, and invoke codehelp-complete (Ctrl+Space), you should get results similar to this:
// // // // $Id$ Copyright 2007 Acme Inc jhurst 2007-04-05

There is no sql.als file set up by default when you install SlickEdit. To create a new alias file for SQL files, follow these steps:

1. 2. 3. 4. 5.

Open the Extension Options dialog (Tools Options File Extension Setup). Select the sql extension. Select the General tab. Enter sql.als for the Alias filename. Click OK to close the Extension Options dialog. SlickEdit adds sql.als to its list of alias files.

Now you can add the SQL-specific hdr alias using steps similar to those for Java.

236

Chapter 11: Aliases and File Templates

Syntax Expansion with Aliases


You can also use aliases to override some of the built-in syntax expansion features supplied with SlickEdit. For example, SlickEdits syntax expansion recognizes the class keyword in C++, but it doesnt expand it to anything. This is because, when typing class in C++, you might be starting a forward declaration. If you would like to make class expand to a class definition template by default, you can create a Cspecific alias called class, with this substitution:
class %\c { public: private: };

C++ aliases are in c.als. The %\c places the cursor in the position for typing in the classs name when you expand the alias. You can expand the class alias by pressing space, rather than invoking codehelp-complete (Ctrl+Space). SlickEdits syntax expansion knows about aliases and checks to see whether an alias overrides a particular syntax expansion before performing it. Thus, you can use aliases to override any standard syntax expansion. If you want to create a class forward declaration (and not expand the alias), use keyin-space (Shift+Space) instead of pressing Space. The keyin-space command bypasses syntax expansion. Heres another C++ example, using the for statement. The default syntax expansion produces:
for () { }

If you prefer, you can add a C-specific alias called for, with this expansion:
for (%\c ; %\c ; %\c) { %\c%\m sur_text% }

This alias adds the semicolons and has several hotspots you can move the cursor through. The alias also supports the dynamic surround feature, by including the %\c%\m sur_text% sequence. Heres an example of an extension-specific alias using Slick-C. The syntax expansion for the _command keyword in Slick-C files does not honor brace style preferences. If, in a Slick-C file, you type _command and press Space, you get the following code:
_command void () name_info(,) { }

This occurs even if you have set your brace preference to put opening braces at the ends of lines. You can correct this by defining a Slick-C-specific alias called _command, with this substitution:
_command void %\c(%\c) name_info(%\c,%\c) { %\c }

237

Part II: Using SlickEdit


The placement of the hotspots matches that of the original syntax expansion behavior. Another idea for extension-specific aliases is to use aliases for commonly required include or import statements. For example, when using Java with the EasyMock library in unit tests, its common to import several methods statically:
import import import import static static static static org.easymock.EasyMock.createMock; org.easymock.EasyMock.expect; org.easymock.EasyMock.replay; org.easymock.EasyMock.verify;

This is a great opportunity for an easymock alias. There is a really quick technique for creating an extension-specific alias from existing code. Just select the code, right-click, and select Create Alias. You will be prompted for an alias name and then be placed in the Alias editor to fine-tune the alias.

Surround Aliases
An extension-specific alias can support dynamic surround by including the special sequence %\c%\m sur_text% in the appropriate place, as shown above in the for loop example. SlickEdits surround-with feature, which we looked at in Chapter 9, makes use of special surround-with aliases. You can modify the supplied surround-with aliases or add your own. Surround-with aliases are extension-specific and are accessed by checking the Surround With box in the Alias Editor. For example, the supplied HTML surround-with aliases include many HTML tags, but not <div>. Lets add a surround-with alias for <div>. Follow these steps:

1. 2. 3. 4. 5. 6. 7.

Invoke alias (Tools Options Aliases). SlickEdit displays the Select Alias File dialog. Select the html.als alias file for HTML aliases, and click OK. SlickEdit displays the Alias Editor. Click the Surround With box. SlickEdit displays the surround-with aliases for HTML files. Click New to add a new surround-with alias. SlickEdit displays the Enter New Alias Name dialog. Enter div for the Alias Name, and click OK to close the dialog. Enter the following for the substitution value:

<div name=%\c>%\m sur_text -select%</div>

Click OK to close the Alias Editor.

You can now use <div> with surround-with. As with dynamic surround, surround-with aliases use the special macro function sur_text. This macro inserts the surrounded text into the expansion at the desired position. The sur_text function can take several different options. See the online Help for full details. Note that if you want your alias to support both surround-with and dynamic surround, you need to enter it twice: once as a regular alias and again as a surround-with alias.

238

Chapter 11: Aliases and File Templates

Aliases with Parameters


You can specify parameters for variable content in your alias. Suppose you are developing a database application and you commonly create reference, or lookup, tables with SQL scripts like this:
CREATE TABLE name ( id INTEGER NOT NULL, description VARCHAR(50) NOT NULL, active_yn CHAR(1) CONSTRAINT name_active CHECK (active_yn IN (Y, N)) ); ALTER TABLE name ADD CONSTRAINT name_pk PRIMARY KEY (id);

Lets create an extension-specific lookup alias that will save typing when creating these scripts. Well put a hotspot after the description column, to allow other columns to be added, and another hotspot after the inserted text. Follow these steps:

1. 2. 3. 4. 5.

Invoke alias (Tools Options Aliases). SlickEdit displays the Select Alias File dialog. Select the sql.als file for SQL-specific aliases, and click OK. SlickEdit displays the Alias Editor. Click New to add a new SQL alias. SlickEdit displays the Enter New Alias Name dialog. Enter lookup for the alias name. Enter the following text for the substitution value:

CREATE TABLE %(NAME) ( id INTEGER NOT NULL, description VARCHAR(50) NOT NULL,%\c active_yn CHAR(1) CONSTRAINT %(NAME)_active CHECK (active_yn IN (Y, N)) ); ALTER TABLE %(NAME) ADD CONSTRAINT %(NAME)_pk PRIMARY KEY (id); %\c

In this alias, were using a parameter (NAME) for the table name.

6.

Click Add under the Parameters list. SlickEdit displays the Enter Alias Parameter dialog, shown in Figure 11-3.

Figure 11-3

239

Part II: Using SlickEdit


7. 8. 9. 10.
Enter NAME for the Parameter Name. Enter Table Name for the Prompt. Click OK to create the parameter. SlickEdit adds the parameter to the list of parameters for the alias. Click OK to save the alias and close the Alias Editor.

You can use this alias in SQL files whenever you need to create a skeleton lookup table. To use the alias to create a customer_type table, follow these steps:

1. 2.

Create a new file called create_table_customer_type.sql. In the new file, type lookup, then invoke codehelp-complete (Ctrl+Space). SlickEdit prompts for the alias parameters, as shown in Figure 11-4.

Figure 11-4

3.

Enter customer_type for the Table Name, and click OK. SlickEdit expands the alias and inserts the following text:

CREATE TABLE customer_type ( id INTEGER NOT NULL, description VARCHAR(50) NOT NULL, active_yn CHAR(1) CONSTRAINT customer_type_active CHECK (active_yn IN (Y, N)) ); ALTER TABLE customer_type ADD CONSTRAINT customer_type_pk PRIMARY KEY (id);

The cursor is at the hotspot at the end of the description line, where you can add more column definitions if you want to.

4.

Invoke next-hotspot (Ctrl+[) to move the cursor to the hot spot at the end of the inserted text.

Aliases and Configuration


When SlickEdit initializes your configuration, it copies the default alias files into your configuration directory. New alias files (*.als) that you create are also placed in the configuration directory. Be careful if you delete your configuration directory, because you will lose your aliases. In Chapter 17, we look at programmatic configuration of aliases, which can be used to avoid this problem.

240

Chapter 11: Aliases and File Templates

F ile Templates
File templates extend the concept of predefined chunks of text or code to multiple files. You can use file templates to instantiate constructs quickly in a single file, or in multiple files. A classic example of a template is for a C++ class, where you have to create a header (.h) file and a corresponding implementation (.cpp) file. SlickEdit comes with several predefined templates that you can use right away. You can also customize them, or add your own.

Instantiating a Template
Lets instantiate a template for a C++ class. Follow these steps:

1.

Invoke add-item (File New Item from Template). SlickEdit displays the Add New Item dialog, shown in Figure 11-5. The templates are organized into categories, which are arranged in a hierarchy.

Figure 11-5

2. 3. 4. 5.

Expand the C++ category. Subcategories are displayed under C++. Select the Class category under C++. The C++ Class category includes templates for C++ Basic Class, C++ Derived Class, and C++ Header File. Select C++ Basic Class. Enter MyNewClass for the Name.

241

Part II: Using SlickEdit


6. 7.
Change the Location if necessary. Click Add. SlickEdit creates two new files:
MyNewClass.cpp the class definition. MyNewClass.h the class declaration.

SlickEdit opens MyNewClass.h for editing.

Creating a Template
Now well add a template of our own. SlickEdit doesnt come with any templates for PL/SQL programming. Lets add a template for creating an Oracle PL/SQL package. Like C++ classes, PL/SQL packages have two parts: The Package Definition created with the CREATE PACKAGE statement. The Package Body created with the CREATE PACKAGE BODY statement.

We will make a template that places each of these statements in its own file. Before we start creating the template in SlickEdit, we need to create the two files that will be in the template. Create a file called create_package_template.sql, containing the following code:
----$$Id$ $copyright$ $username$ $localdate$

CREATE OR REPLACE PACKAGE pkg_$itemname$ AS -- add members here ... PROCEDURE test; END; / GRANT EXECUTE ON pkg_$itemname$ TO $granted_user$;

The identifiers between $ characters are substitution parameters. They will be substituted when the template is instantiated. Some of the substitution parameters are predefined by SlickEdit, such as $username$ and $localtime$. Other substitution parameters are user-defined, and some of these are global, while others are defined at the time the template is instantiated. Well explain the substitution parameters in more detail shortly. The instantiated file will contain a version-control keyword $Id$ on the first line. The double $ in $$Id$ prevents SlickEdit from interpreting Id as a substitution parameter. Create another file called create_package_body_template.sql, containing the following code:
-- $$Id$ -- $copyright$ -- $username$

242

Chapter 11: Aliases and File Templates


-- $localdate$ CREATE OR REPLACE PACKAGE BODY pkg_$itemname$ AS -- complete definitions of members here ... PROCEDURE test IS BEGIN NULL; -- fill in test method. END; END; /

Now were ready to define the template in SlickEdit. Follow these steps:

1.

Invoke template-manager (File Template Manager). SlickEdit displays the Template Manager, shown in Figure 11-6.

Figure 11-6

2. 3. 4.

Right-click on the User Templates category, and select New Category from the context menu. SlickEdit displays the New Category dialog. Enter PLSQL for the Category name. Click OK to close the New Category dialog.

243

Part II: Using SlickEdit


5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
Right-click on the PLSQL category, and select New Template in Category from the context menu. SlickEdit displays the New Template dialog. Enter create_package for the Template name. Click OK to close the New Template dialog. SlickEdit creates the template entry in the Template Manager. Enter New PL/SQL package for the Description. Enter name for the Default name. Select the Files tab. Click the + next to the Files list to add a file to the template. SlickEdit displays the Add File dialog. Enter the path and filename for your create_package_template.sql file, or use Browse to navigate to it. Enter create_pkg_$itemname$.sql for the Target filename. Click OK to close the Add File dialog and add the file to the template. SlickEdit adds the file. Repeat the process to add the create_package_body_template.sql file. Enter create_pkg_ body_$itemname$.sql for its Target filename. Select the Custom Parameters tab. Click the + next to the Custom Parameters list to add a custom parameter. SlickEdit displays the Add Parameter dialog. Enter granted_user for the Name. Enter PUBLIC for the Value. Check the Prompt for value checkbox. Enter User to grant EXECUTE to for the Prompt string. Click OK to close the Add Parameter dialog. Click Options. SlickEdit displays the Template Options dialog, shown in Figure 11-7.

Figure 11-7

244

Chapter 11: Aliases and File Templates


24. 25. 26. 27. 28.
Click the + next to the Global substitution parameters list. SlickEdit displays the Add Parameter dialog. Enter copyright for the Name. Enter Copyright 2007 Acme Inc for the Value. Click OK to close the Template Options dialog and add the global substitution parameter. The $copyright$ substitution parameter can now be used in all our templates. Click Close to close the Template Manager.

That was a lot of steps, but the result is quite powerful. Lets instantiate the template. Follow these steps:

1. 2. 3. 4. 5. 6. 7.

Invoke add-item (File New Item from Template). SlickEdit displays the Add New Item dialog. Select the PLSQL category under User Templates if it is not already selected. Select the create_package template if it is not already selected. Enter customer for the Name of the new item. Click Add. SlickEdit displays the Parameter Entry dialog. Enter ADMIN for the User to grant EXECUTE to. Click OK to close the Parameter Entry dialog and instantiate the template. SlickEdit creates two files and opens create_pkg_customer.sql.

The instantiated contents of create_pkg_customer.sql are:


----$Id$ Copyright 2007 Acme Inc jhurst 2007-04-06

CREATE OR REPLACE PACKAGE pkg_customer AS -- add members here ... PROCEDURE test; END; / GRANT EXECUTE ON pkg_customer TO ADMIN;

The instantiated contents of create_pkg_body_customer.sql are:


----$Id$ Copyright 2007 Acme Inc jhurst 2007-04-06

CREATE OR REPLACE PACKAGE BODY pkg_customer AS -- complete definitions of members here ... PROCEDURE test IS

245

Part II: Using SlickEdit


BEGIN NULL; -- fill in test method. END; END; /

Usually when you are using templates you will add the instantiated files to your project. The Add New Item dialog has a checkbox to control whether this happens automatically. If there is no current project, the option is disabled. If there is a current project, then new items are added to it unless the checkbox is unchecked. When invoked from the Project menu (Project Add New Item From Template), the Add to current project checkbox is on by default. For this example, we chose not to copy the source file to the template directory.

Substitution Parameters
We saw several different kinds of substitution parameters in the example. SlickEdits built-in substitution parameters are described in the online Help. They are repeated in Table 11-2, but you should check the online Help in case new ones have been added since this book went to print.

Table 11-2
Parameter
$itemname$ $fileinputname$

Description Name of item entered, as on the Add New Item dialog. Name of item entered, as on the Add New Item dialog, without file extension. Name of item entered, as on the Add New Item dialog, with all unsafe characters replaced with safe characters. Same as $safeitemname$ with all characters uppercased. Same as $safeitemname$ with all characters lowercased. Location of operating system temp directory. No trailing file separator. Root namespace or package for the current project. Time of day in the form hh:mm[am|pm]. Example: 11:34pm. Time of day in locale-specific format. Time of day in the form hh:mm:ss.

$safeitemname$

$upcasesafeitemname$ $lowcasesafeitemname$ $tempdir$

$rootnamespace$ $ampmtime$ $localtime$ $time$

246

Chapter 11: Aliases and File Templates


Table 11-2 (continued)
Parameter
$localdate$ $date$ $projectname$ $safeprojectname$

Description Current date in locale-specific format. Current date in the form mm/dd/yyyy. Current project name (no path, no extension). Current project name (no path, no extension), with all unsafe characters replaced with safe characters. Current workspace name (no path, no extension). Current workspace name (no path, no extension), with all unsafe characters replaced with safe characters. Current project working directory. No trailing file separator. Current project build (output) directory. No trailing file separator. Current project configuration name. Current workspace configuration name. This will be the same as $projectconfigname$ except for MS Visual Studio workspace, which will have a separate workspace/solution configuration name. Location of current project file. No trailing file separator. Location of current workspace file. No trailing file separator. Operating system login name.

$workspacename$ $safeworkspacename$

$projectworkingdir$ $projectbuilddir$ $projectconfigname$ $workspaceconfigname$

$projectdir$ $workspacedir$ $username$

Unfortunately, the template feature has no equivalent of the alias features %\m escape sequence. This limits its flexibility somewhat. For some uses of %\m, such as our use for the current year to insert into a copyright notice, the global substitution parameters can be used effectively. In the case of the current year, you only have to change the substitution value once per year, and it would apply to all projects. For other uses of %\m, there is no suitable alternative in the template feature. Per-template substitution parameters can be used to customize the content of your template. In the example above, we used this for the GRANT EXECUTE statement. Again, if we want to instantiate the template and have no GRANT EXECUTE statements, or more than one, we cant configure the template to do that. However, once the template is instantiated, its easy enough to edit the file and make the necessary changes. In fact, an alias would help with this.

247

Part II: Using SlickEdit


We could create an extension-specific alias, grantx, with expansion:
GRANT EXECUTE ON %\c TO %\c;

This alias, along with word completion (for the package name), would make it pretty quick to add GRANT EXECUTE statements.

Managing Templates
When you create a file template, you have the choice of copying the source files into the template directory or linking to them in their original location. Usually in a professional environment, the template source files should be checked into version control, probably in a special VCS project for templates. With that setup, you can check out a local copy wherever you want and point the SlickEdit template entries at the source files.

Instantiating Templates in Macros


In Chapter 4, we saw how you can create custom project types and use the InitMacro attribute to run an initialization macro when the project type is instantiated. When creating a new project of a custom type, its often useful to instantiate one or more file templates. You can, of course, do this manually after creating a new project. If you want certain file templates to be a standard part of your custom project type, you can instantiate them in your initialization macro. Lets revisit the Java example from Chapter 4. Most Java projects are built using Ant, with a build.xml file. If you are using Java, you probably have a standard layout for your Ant build scripts that you re-use with each project. Obviously, the same idea applies to makefiles and other standard build scripts for other languages. In this section, well add a file template for build.xml and related files and show how to instantiate the template when creating a new project of a custom project type. First, well create the new file template. For this example, well have three files:
build.xml the Ant build script. build.properties the default build properties used by the script. build.number.properties a special properties file with build numbers for numbered

builds. To follow the example, perform these steps:

1.

Create a file called build.xml, with the following content:

<!-$$Id$ $copyright$ $username$ $localdate$ --> <project name=$projectname$ basedir=. default=compile-java > <tstamp>

248

Chapter 11: Aliases and File Templates


<format property=build.date pattern=yyyy-MM-dd HH:mm:ss/> </tstamp> <!-- Properties: local properties override common properties --> <property file=build.local.properties/> <property file=build.number.properties/> <property file=build.properties/> <path id=classpath.lib> <fileset dir=${lib}/> </path> <path id=classpath.test> <fileset dir=${lib.test}/> </path> <target name=clean description=Clean temporary/generated files and directories> <delete dir=${build}/> </target> <target name=prepare description=Create directory structure for build> <mkdir dir=${build}/> <mkdir dir=${build.classes}/> </target> <target name=compile-java depends=prepare description=Compile prod code > <javac srcdir=${src.java} destdir=${build.classes} debug=${compile.debug} optimize=${compile.optimize} source=${compile.source} target=${compile.target}> <classpath refid=classpath.lib/> </javac> <copy todir=${build.classes}> <fileset dir=${src.java} excludes=**/*.java/> </copy> </target> <target name=compile-test depends=prepare,compile-java description=Compile test code> <javac srcdir=${src.test} destdir=${build.classes} debug=${compile.debug} optimize=${compile.optimize} source=${compile.source} target=${compile.target}> <classpath refid=classpath.lib/> <classpath refid=classpath.test/> </javac> <copy todir=${build.classes}> <fileset dir=${src.test} excludes=**/*.java/> </copy> </target> <target name=compile depends=compile-java,compile-test description=Compile all code/> <target name=test depends=compile description=Run all tests> <delete dir=${test.xml.dir}/> <mkdir dir=${test.xml.dir}/>

249

Part II: Using SlickEdit


<junit fork=true dir=. errorProperty=test.failed failureProperty=test.failed> <classpath path=${build.classes}/> <classpath refid=classpath.lib/> <classpath refid=classpath.test/> <formatter type=brief usefile=false/> <test name=AllTests/> </junit> <fail message=Tests failed! Check test reports. if=test.failed/> </target> </project>

This is a simple build script, including basic steps for compiling production and test code and running tests. In a real environment, you would also include standard targets for packaging and possibly distributing your application, and other targets too. Note that the template uses substitution parameters for the copyright, user, and local date as before. We also use the predefined substitution parameter $projectname$ to set the Ant project name from the name given to the project in SlickEdit. This can, of course, be changed after the template is instantiated.

2.
# # # #

Create an accompanying build.properties file, with this content:


$$Id$ $copyright$ $username$ $localdate$

project.name = $projectname$ build.version.number = ${version.number}.${release.number}.${build.number} build.version.string = ${build.version.number} built on ${build.date} # compiler options compile.debug = false compile.optimize = true compile.source = 1.5 compile.target = 1.5 # paths lib = lib lib.test = ${lib}/test build = build build.classes = ${build}/classes build.javadoc = ${build}/javadoc src.java = src/java src.test = src/test

3.

Create a build.number.properties file, with this content:

build.number=00 version.number=01 release.number=00

250

Chapter 11: Aliases and File Templates


4. 5. 6. 7.
Create a new file template category Java, under User Templates. In the Java category, create a template called Ant build file. In the template, set the name, description, and default name to Ant build file. Link the template to the three source files build.xml, build.properties, and build.number .properties.

Now that we have the template, the next step is to cause the custom project type to instantiate it when creating a new project. We will extend the custom project created in Chapter 4, with the InitMacro named wrox_create_java_dirs(). In the Author/Chapter11 directory on the CD-ROM is an updated version of that macro, called wrox_create_java_project(). The code is shown below:
_command int wrox_create_java_project() name_info(,) { // create src/java/com/wrox/ _str java_path = _file_path(_project_name) :+ src :+ java :+ FILESEP :+ com :+ FILESEP make_path(java_path); // create src/test/com/wrox/ _str test_path = _file_path(_project_name) :+ src :+ test :+ FILESEP :+ com :+ FILESEP make_path(test_path);

FILESEP :+ :+ wrox;

FILESEP :+ :+ wrox;

// add wildcard for src/*, recursive, excluding SVN files _ProjectAdd_Wildcard(_ProjectHandle(), src\\*, *\\.svn\\*, true); add_item(%VSLICKCONFIG%\\templates\\ItemTemplates\\Java\\Ant build file\\Ant build file.setemplate, build.xml, , true, false); return 0; }

The new statement, containing the add_item() call, should all be on one line. The function call instantiates the Ant build file template from the user templates directory and adds the files to the current project. Note that the add_item() macro function detects the environment variable %VSLICKCONFIG% and replaces it with your SlickEdit configuration directory. Load this code, and change the InitMacro to refer to the new name. The next time you create a new project of type Java Project WROX, you should get it initialized with the standard build scripts, as well as the source directories. The add_item() macro used here is the same command that is invoked from the menu via File Add New Item from Template. When invoked from the menu, the macro displays the Add New Item dialog. If you use the macro from Slick-C code, you can provide parameters, as weve done here, to bypass the dialog. As with a number of SlickEdit macro/commands, the parameters are not documented in the Help system, but they are not difficult to figure out by reading the source code. Reading the Slick-C source code is essential for making significant extensions and customizations. Sometimes when browsing the Slick-C macro source code you will find that a command works by calling some other, simpler macro function. Or, you may discover the internal workings of some mechanism, such as the XML structure of configuration files. You can use this knowledge in your own programming

251

Part II: Using SlickEdit


when appropriate. However, remember that the internal workings can change from release to release. The more your own code relies on low-level functionality and implementation details, the more likely it is to break between releases. Try to use higher-level functionality and documented commands and functions as much as possible, as they are less likely to change.

Summar y
In this chapter, we looked at two related features that allow you to add your own customized time-savers to SlickEdit. Aliases are useful for a wide variety of situations, from shorthands for commonly used files and directories, to full-sized coding constructs, including overriding the built-in syntax expansion. The inline macro execution capability of aliases is particularly powerful for advanced uses. File templates are useful when you want to define a standard boilerplate layout for one or more files. The difference comes down to a matter of granularity. Aliases are pieces of code; templates are one or more files. In the next chapter, we cover several topics relating to document types.

252

Document Types
When you open a file in SlickEdit, the editor determines several things about it. Weve already seen the importance of the extension in determining the document mode. (The mode is basically the programming language family; see Chapter 9.) Most programming language source files are simple ASCII files (or nearly enough), and that is all that matters. SlickEdit can also edit files of other types. Sometimes there is more involved in determining how to read them or display them. SlickEdit can open binary files. For binary files, its usually more useful to view them in hex mode as bytes rather than as text characters. Sometimes hex mode is useful for text files too. SlickEdit supports XML files as well. XML files are Unicode rather than ASCII and can be represented on disk in a variety of encodings. Unicode is a massive character set (~100,000 characters). This introduces some challenges, because most fonts are not capable of displaying the entire set. When dealing with XML documents, SlickEdits default behavior is to try to provide as much assistance as it can by downloading referenced DTDs and schemas from the Internet. I use a laptop for almost all my work, and because Im on the road a lot, not always connected to the Internet, sometimes I dont want this behavior. Sometimes I need to prevent SlickEdit from fetching documents from the Internet. An even better option is to store local copies of required resources and get SlickEdit to use them instead. In this chapter, we cover a variety of topics concerning types of files and ways to view and edit them.

Document Mode
When you open a source file with a known extension, SlickEdit places the document into the mode associated with the extension. If SlickEdit does not recognize the extension, the editor goes into Fundamental mode. Usually the automatically selected mode is just what you want, because it enables all the features associated with the programming language.

Part II: Using SlickEdit


Sometimes you dont want the features enabled, or you want a different mode. For example, syntax expansion features can get in the way when using Macro Record and Playback. You can use select-mode (Document Select Mode) to select a different mode for the editor. You can also switch modes using specific commands for each mode. The mode switching commands are simply the name of the mode followed by -mode. For example, the command to switch to Fundamental mode is fundamental-mode, and the command to switch to HTML mode is html-mode. An example in which this mode-switching is useful is in Ruby on Rails views, which are .rhtml files containing a mixture of HTML and Ruby code. SlickEdit supports some combinations of HTML and scripting languages (such as ASP and JavaScript), but not HTML and Ruby. However, you can get some of the benefits of both languages by switching between HTML and Ruby modes while editing the file. We gave some examples of working with embedded languages in Chapter 9.

Binar y F iles
When you open a binary file, SlickEdit attempts to display it as text by default. For binary files, this is usually meaningless. To view a binary file, switch to hex mode using the hex command (View Hex or Ctrl+Shift+H). SlickEdit displays the file as 16-byte chunks as shown in Figure 12-1. You can still edit the text part on the right-hand side, or you can edit the hexadecimal representation by clicking in the lefthand side. To switch back to text mode, invoke hex again.

Figure 12-1 SlickEdit also supports Line Hex mode via the linehex command (View Line Hex). Line hex mode shows each line of the source file on a separate line in the editor, showing both ASCII characters and hex bytes. This mode is useful if you have a file that has line structure but binary data. An example might be a PDF file. Hex mode can be useful for text mode too, occasionally. For example, you can use it to check line endings in a file when you are not sure if the file has UNIX or DOS line endings (or might have both). You can use it to check tab characters in makefiles.

Character Sets and Encodings


Before Unicode became popular, all source code editors used code pages to edit source files. Originally, SlickEdit could only edit code page source files like the other source code editors. There are some advantages to code page editors. Code page editors do not need to translate the bytes in your file when you open the file. This has some speed advantages, allows for a single editor storage format that can display the bytes in your file as lines of text or in hex, and guarantees that there are no translation errors. The

254

Chapter 12: Document Types


disadvantage of code page editors is that realistically you cant edit Unicode files. This is because there is no code page that contains all the characters in the Unicode character set. Now that Unicode is widely used for XML and other text files, code page editing is not enough. Today, most source code editors that support Unicode files convert code page files to an internal Unicode representation (usually UTF-16 or UTF-8). All Microsoft text editors, including Visual Studio, do this. In order to retain the advantages of code page editing for those files for which it is suitable, SlickEdit has two basic in-memory representations: Single Byte Character Set/Double Byte Character Set (SBCS/DBCS) SBCS/DBCS mode means code page editing. In this mode, the text in your file is not translated except for EBCDIC, which is a slight variant of this mode because characters are translated to ASCII. Unicode (represented internally as UTF-8) This is typically used for XML. In this mode, if the data in your file are not already in UTF-8, SlickEdit will translate them into UTF-8.

SlickEdit normally determines the encoding and thus the character set automatically, based on the file extension and content. If the file extension is associated with XML, the file is loaded as Unicode. If the file contains a Unicode Byte Order Mark (BOM), also known as a signature, the BOM determines the encoding, and the file is loaded as Unicode. Otherwise, the file is loaded as SBCS/DBCS. You can override the encoding on the Open dialog. Most of the encodings require your files text to be converted to UTF-8, but some are for SBCS/DBCS mode. The Windows Fast Open dialog, or Windows 3.1 style Open dialog, does not have an option to override the encoding. If you need to override the encoding when opening a file on Windows, you need to switch to the standard Open dialog. It is important to understand the distinction between Unicode and SBCS/DBCS when working with XML files, because some features are not fully supported for the Unicode representation. For example, hex mode is not supported for XML files in encodings other than UTF-8, because the disk representation is different from the in-memory representation. If you need to view a UTF-16 XML document in hex, for example, you need to open it using an SBCS/DBCS encoding, such as Binary. Several other features, mainly concerning limitations of fonts, are also not supported for Unicode. These are documented in the online Help. You can use the encoding option in the Open dialog to create a new file in a specific encoding. For example, you can create a text file using UTF-16 encoding. When you save the file, SlickEdit stores a UTF-16 BOM at the beginning, and writes two bytes per character.

XML Document Types


XML files are often described using a Document Type Definition, or DTD, which is a specification describing the valid content of files of the given type. The DTD specifies which elements the document may contain, what content the elements may contain, whether they are mandatory or optional, their attributes, and so forth. An XML document that conforms to its DTD is said to be valid. In 2001, the W3 Consortium introduced the XML Schema standard as a new and more powerful way to describe content rules for XML documents. XML Schema is used by many modern XML systems, including most of those in Web Services, such as SOAP and WSDL.

255

Part II: Using SlickEdit


When SlickEdit opens an XML file that references a DTD or schema, the editor loads the document definition so that it can validate the document structure and provide syntax assistance. If the document is not valid, SlickEdit displays error messages in the Output tool window and also highlights unknown elements using the configured Unknown XML Element color. In order to validate a document, SlickEdit needs to refer to the DTD or schema. Usually the DTD or schema is given by a URL. For example, the URL for the DTD for configuration files for the Spring framework is http://www.springframework.org/dtd/spring-beans-2.0.dtd. This downloading can take a noticeable time, even if you are on a fast network. If you are behind a firewall or not connected to the network, the downloading fails after a timeout. During this time the editor is effectively hung, and you cannot work. One solution to this issue is to store a copy of the DTD/schema on your local hard disk and refer to that copy instead. Lets configure SlickEdit to refer to a local copy of the Spring configuration DTD. On my system, the framework is installed in C:\lib\spring-framework-2.0.2. Follow these steps:

1.

Open the URL Mappings dialog (Tools Options URL Mappings). SlickEdit displays the dialog, shown in Figure 12-2.

Figure 12-2

2. 3. 4. 5.

Click Add. SlickEdit adds a new empty entry. Enter http://www.springframework.org/dtd/spring-beans-2.0.dtd for From. Enter C:\lib\spring-framework-2.0.2\dist\resources\spring-beans-2.0.dtd for To. Click OK. SlickEdit adds the URL mapping.

After adding this URL mapping, SlickEdit retrieves the DTD from the local disk instead of over the network. Locally mapped URLs are stored in options.xml in your SlickEdit configuration directory. When setting up URL mappings, SlickEdits support for multiple clipboards is helpful. You can copy the From and To parts into the clipboard in turn, then use list-clipboards (Ctrl+Shift+V) to paste them selectively into the URL Mappings dialog.

256

Chapter 12: Document Types


If you dont have a local copy of the DTD or schema and you are working offline, you may prefer to disable SlickEdits document validation, so that you can open files quickly, without timeouts. The autovalidation setting is in the XML Formatting Options dialog, reached from the XML Options button on the Extension Options dialog for XML (Tools Options File Extension Setup). Turning off auto-validation prevents SlickEdit from validating XML documents when it opens them. You can still validate them manually at any time by invoking the xml-validate command. Even with auto-validation turned off, SlickEdit still tries to download the DTD or schema, so that it can use it to provide syntax expansion and color highlighting. You can prevent SlickEdit from downloading DTDs or schemas for syntax expansion by adding extensions to the def_xml_no_schema_list macro variable. For example, enter this command:
set-var def_xml_no_schema_list .xml .xsd

This command disables automatic download of DTDs and schemas for syntax expansion for all XML and XSD files. You can enable syntax expansion and color highlighting for a specific file you have open by invoking apply-dtd-changes. You can also invoke this command by right-clicking in the window and clicking Apply DTD, TLD, or Schema Changes. For the best editing experience with XML files, I recommend that you download all DTDs and schemas referred to by your documents and store local copies on your hard drive. Use the URL mapping configuration to prevent SlickEdit from downloading them from the Internet every time it opens a file. Here is a macro and function you can use to automate downloading URL resources and creating local mappings for them:
_command void wrox_make_url_mapping(url) name_info(,) { edit(url); // Note: SlickEdit knows how to fetch http:// addresses _str resourcename = wrox_make_local_resource_filename(); save(resourcename); quit(); typeless handle=_cfg_get_useroptions(); int index = _xmlcfg_set_path(handle,/Options/URLMappings); int new_index = _xmlcfg_add(handle, index, MapURL, VSXMLCFG_NODE_ELEMENT_START, VSXMLCFG_ADD_AS_CHILD); _xmlcfg_set_attribute(handle, new_index, From, url); _xmlcfg_set_attribute(handle, new_index, To, resourcename); _cfg_save_useroptions(); } _str wrox_make_local_resource_filename() { int i = 0; _str basename = _config_path() :+ resource; while (file_exists(basename :+ i)) { i++; } return basename :+ i; }

257

Part II: Using SlickEdit


To use this macro to download the Spring configuration DTD to a local copy, load the macro and enter this command on the SlickEdit command line:
wrox-make-url-mapping http://www.springframework.org/dtd/spring-beans-2.0.dtd

The macro uses a function, wrox_make_local_resource_filename(), which returns an unused filename in the SlickEdit configuration directory. The function uses the SlickEdit-provided function _config_path() to get the configuration directory. It then works by simply appending numbers to the prefix resource until it finds a name that does not currently exist as a file in the configuration directory. The macro uses SlickEdits ability to fetch HTTP resources when passed to the edit command. You dont need to do anything else to load an HTTP resource into SlickEdit. Its not industrial strength: Theres no error-handling, so you wont use it for building your next Web Services infrastructure, but for automating some manual tasks in the editor, it will do just fine. After loading the resource, the macro saves it to the new file. Finally, it uses some of SlickEdits XML handling functions to open the options.xml configuration file and add the URL mapping.

Summar y
In this chapter, we have covered several areas loosely gathered under the topic of document types. Firstly, the document mode determines much of the appearance and behavior of the editor, particularly for files having syntax highlighting and assistance. In Chapter 17, some examples of defining new document modes for your own languages are demonstrated. SlickEdit can open files in a variety of character sets and encodings, including binary files. Finally, most of the chapter was concerned with XML document types and effective ways to manage DTDs and XML schemas for working with these. In the next chapter, we take a look at SlickEdits Compare and Merge tools, which are used for managing and comparing different versions of files and directories.

258

Comparing and Merging


For some reason or another, we programmers always seem to end up with multiple, slightly different versions of the same file. Or worse multiple, slightly different versions of the same source tree. Now, one thing Ive noticed in my career is that this has been happening a lot less since I started using version control. Proper use of version control reduces the need for archived or backup copies of source code, or copies of the same source tree all over your disk. We look at version control in more detail in the next chapter. Of course, it still happens. (Usually when it happens to me, it means I havent been using version control properly!) This must be a fairly common occurrence for programmers, and perhaps other computer users too, because there are several commercial tools on the market whose sole function is to compare directories and files and resolve the differences. Happily, if you already own SlickEdit, you probably dont need one of those tools, because SlickEdit has great file and directory comparison and merging built right in. You can even run SlickEdits comparison tools outside the editor, as a full replacement for standalone tools for the same purpose. In this chapter, well take a look at comparing and merging files and directories. Well also take a look at some basic versioning capabilities built into SlickEdit.

Comparing F iles and Directories


SlickEdits file and directory comparison tool is called DIFFzilla. You can use DIFFzilla to compare buffers with each other, buffers with files, or files with other files. You can also use it to compare entire subdirectories of your file system.

Part II: Using SlickEdit

Comparing Two Files


Suppose that, in a fit of performance-tuning enthusiasm, we re-wrote the gnu_queens program to use old style C arrays instead of STL collections. We have a copy of the old source code in a separate backup directory. Lets use DIFFzilla to examine the differences between the STL board.h and the arrays board.h. Follow these steps:

1.

Invoke diff (Ctrl+equals). SlickEdit displays the DIFFzilla setup dialog, shown in Figure 13-1. You use this dialog to set up the files or directories you wish to compare.

Figure 13-1

2. 3. 4.

Enter the path and filename of the old version of board.h in Path 1. You can use the button labeled to select the file from the file system. You can use the button labeled B to select an open buffer. Enter the path and filename of the new version of board.h in Path 2. Click OK. SlickEdit displays the Diff window, shown in Figure 13-2.

The differences in the file are indicated graphically. You can navigate backward and forward among the differences using the Next Diff and Prev Diff buttons. The most common use of DIFFzilla is simply to compare two versions of a file. However, you can also use DIFFzilla to resynchronize files by eliminating differences. The first row of buttons in the Diff window provides operations for copying lines or blocks from either side to the other. You can save either side at any time while you are working in the Diff window, and you can undo changes. In fact, the two buffer panes act like the regular SlickEdit editor pane in most ways, so you can type and make use of a limited set of SlickEdit editing features, such as cursor movement and syntax assistance. Not all commands work by default in the Diff window. If you try to use a command that is not supported in Diff, you will receive a message box stating Command xxx currently not allowed in Diff mode. For example, you cannot use selections to copy lines directly from one pane to the other, or within a pane. You can use the clipboard to copy selections, however.

260

Chapter 13: Comparing and Merging

Figure 13-2

The Diff window uses its own command dispatch mechanism. The commands that are supported are listed in the diffedit.e macro file supplied in the macros directory under the SlickEdit installation. If you want to add additional commands, you can add them there. Use caution when making changes to supplied macros. Changes to the supplied macros can affect the behavior of the editor. For example, while the standard prev-word and next-word commands are supported in DIFFzilla, the WROX alternatives wrox-prev-whitespace-word and wrox-next-whitespace-word are not. To add them, follow these steps:

1. 2.

Edit diffedit.e. Add these lines near the top of the file, to declare prototypes for the commands:

_command void wrox_next_whitespace_word(); _command void wrox_prev_whitespace_word();

3.

Add these lines to the declaration of the DiffCommands array:


wrox-next-whitespace-word wrox-prev-whitespace-word =>wrox_next_whitespace_word, =>wrox_prev_whitespace_word,

4.

Invoke load. You should now be able to use wrox-prev-whitespace-word and wrox-next-whitespace-word in DIFFzilla editor panes.

This tip can work for your own commands and for many standard SlickEdit commands that have been omitted from DiffCommands, for whatever reason. Thanks to Hartmut Schaefer (hs2) for this tip.

261

Part II: Using SlickEdit

Comparing Sections within a File


Sometimes, instead of comparing entire files, you need to compare only a range of lines. Occasionally you may need to compare ranges of lines within a file. For example, here is a fragment from an XML schema definition:
<?xml version=1.0?> <xsd:schema xmlns:xsd=http://www.w3.org/2001/XMLSchema> ... <xsd:complexType name=PartialAddress> <xsd:annotation> <xsd:documentation> Purpose - Define a partial address. Detail - This type allows the transfer of portions of an address. Where a complete address is to be transferred, the Address type should be used. </xsd:documentation> </xsd:annotation> <xsd:sequence> <xsd:choice minOccurs=0> <xsd:element name=StructuredAddress type=StructuredAddressPartialComponents/> <xsd:element name=UnstructuredAddress> <xsd:complexType> <xsd:sequence> <xsd:element name=AddressLine type=AddressLine nillable=true maxOccurs=3/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:choice> <xsd:element name=SuburbOrPlaceOrLocality type=SuburbOrPlaceOrLocality nillable=true minOccurs=0/> <xsd:element name=StateOrTerritory type=StateOrTerritory nillable=true minOccurs=0/> <xsd:element name=PostCode type=PostCode nillable=true minOccurs=0/> <xsd:element name=DeliveryPointIdentifier type=DeliveryPointIdentifier nillable=true minOccurs=0/> </xsd:sequence> </xsd:complexType> ... <xsd:complexType name=Address> <xsd:annotation> <xsd:documentation> Purpose - Define an address. Detail - The address format allows for either a structured or an unstructured physical address, with locality, state and postcode always being carried as structured elements. </xsd:documentation> </xsd:annotation> <xsd:sequence> <xsd:choice> <xsd:element name=StructuredAddress type=StructuredAddressComponents/> <xsd:element name=UnstructuredAddress>

262

Chapter 13: Comparing and Merging


<xsd:complexType> <xsd:sequence> <xsd:element name=AddressLine type=AddressLine nillable=true maxOccurs=3/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:choice> <xsd:element name=SuburbOrPlaceOrLocality type=SuburbOrPlaceOrLocality nillable=true minOccurs=0/> <xsd:element name=StateOrTerritory type=StateOrTerritory/> <xsd:element name=PostCode type=PostCode/> <xsd:element name=DeliveryPointIdentifier type=DeliveryPointIdentifier nillable=true minOccurs=0/> </xsd:sequence> </xsd:complexType> ... </xsd:schema>

To limit the comparison to a range of lines, click the More button under Path 1 in the DIFFzilla setup dialog. Like most of SlickEdit, the DIFFzilla functionality is available via a macro function. The diff command invokes DIFFzilla and has many options. Most of the options are documented in the online Help, and the rest, corresponding to options available in the setup dialog, can be discovered by looking at the source code in diff.e. Heres an example of using DIFFzilla from a macro to save work. When comparing ranges of lines, it is rather tedious to note the line numbers for the starts and ends of the ranges and enter them into the DIFFzilla setup dialog. This macro can make comparing ranges of lines a bit easier:
_command void wrox_diff_lines(_str bookmarks = 1 2 3 4) name_info(BOOKMARK_ARG*,VSARG2_REQUIRES_EDITORCTL) { _str bookmark1; _str bookmark2; _str bookmark3; _str bookmark4; parse bookmarks with bookmark1 bookmark2 bookmark3 bookmark4; push_bookmark(); goto_bookmark(bookmark1); _str filename1 = p_buf_name; int start_line1 = p_line; goto_bookmark(bookmark2); if (p_buf_name != filename1) { message(Bookmark 2 must be in same file as bookmark 1.); pop_bookmark(); return; } int end_line1 = p_line; if (end_line1 <= start_line1) { message(Bookmark 2 must be after bookmark 1 in file.); pop_bookmark(); return;

263

Part II: Using SlickEdit


} goto_bookmark(bookmark3); _str filename2 = p_buf_name; int start_line2 = p_line; goto_bookmark(bookmark4); if (p_buf_name != filename2) { message(Bookmark 4 must be in same file as bookmark 3.); pop_bookmark(); return; } int end_line2 = p_line; if (end_line2 <= start_line2) { message(Bookmark 4 must be after bookmark 3 in file.); pop_bookmark(); return; } _str commandline = ; commandline = commandline :+ -range1: :+ start_line1 :+ , :+ end_line1 :+ ; commandline = commandline :+ -range2: :+ start_line2 :+ , :+ end_line2 :+ ; commandline = commandline :+ maybe_quote_filename(filename1) :+ ; commandline = commandline :+ maybe_quote_filename(filename2); diff(commandline); pop_bookmark(); }

This macro defines a command, wrox-diff-lines, which invokes DIFFzilla for a pair of ranges in a pair of files. The ranges are defined by the four bookmarks, named by default 1 through 4. To use this macro to compare two ranges, follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9.

Navigate to the start of the first range. Invoke alt-bookmark with bookmark 1 (WROX: Ctrl+Shift+1). This marks the start of the first range for the macro. Navigate to the end of the first range. The end of the first range should be after the start, and in the same file. Invoke alt-bookmark with bookmark 2 (WROX: Ctrl+Shift+2). Navigate to the start of the second range. This can be in the same file as the first range, or in a different file. Invoke alt-bookmark with bookmark 3 (WROX: Ctrl+Shift+3). Navigate to the end of the second range. The end of the second range should be after the start, and in the same file. Invoke alt-bookmark with bookmark 4 (WROX: Ctrl+Shift+4). Invoke wrox-diff-lines. The macro loads DIFFzilla to compare the ranges specified by the bookmarks.

If you wish, you can use different names for the bookmarks, in which case you must specify them on the command line when you invoke the command.

264

Chapter 13: Comparing and Merging

Comparing Directories
You can use DIFFzilla to compare whole directory trees, as well as individual files. To compare directories, check the Multi-File radio button in the DIFFzilla setup dialog. To compare entire directory trees, check the Recurse into subdirectories checkbox. Figure 13-3 shows an example of a Multi-File Diff. You can select any pair of files and compare them with DIFFzilla.

Figure 13-3

In Figure 13-3, some of the subdirectories showing differences are Subversion admin directories (the .svn subdirectories). When comparing directories, you sometimes want to exclude such items from the comparison. To exclude the .svn subdirectories, add .svn\ to the Exclude Filespecs. When the Multi-File Diff Output window is displayed, you can right-click in the results windows to get a context menu. This menu is shown in Figure 13-4.

Figure 13-4

On the context menu, you can filter the results by a variety of criteria. You can also click Hide to hide subtrees you are not interested in. These options can rapidly make a large list of differences more manageable.

265

Part II: Using SlickEdit

DIFFzilla Options
The options tab of the DIFFzilla setup dialog has many options for fine-tuning the comparison. You can select from several ways of comparing or ignoring white space, line endings, and case. You can skip comments at the beginning of the file, which is handy if your files have version control information on the first few lines.

Running DIFFzilla Standalone


You can run DIFFzilla as a standalone tool. Under Windows, the SlickEdit installation creates a shortcut for DIFFzilla in the SlickEdit folder in your Start Menu. You can also use DIFFzilla from the command line, provided that the SlickEdit executable directory is in your path. The command is called vsdiff. Consult the online Help to find out about the command-line options.

Merging Changes
DIFFzilla is most often used for comparing files or directories. As weve seen, you can also edit files while you are comparing them, and DIFFzilla has tools for reconciling differences by copying lines or blocks from one side to the other. SlickEdit includes another tool that is sometimes more useful for another kind of change reconciliation: 3 Way Merge. Use 3 Way Merge when you have an original file and two independent changed versions. This scenario is illustrated in Figure 13-5. The 3 Way Merge tool displays data from all three files and allows you to merge them selectively into the output.

Base File

Rev 1

Rev 2

3 Way Merge

Base File

Figure 13-5

266

Chapter 13: Comparing and Merging


Lets look at a simple example. In order to make things as clear as possible, well use a rather contrived set of files. Heres the original:

This is a file used to demonstrate 3 way merging. This is the line in the base file. Here is line 1 of 3. Here is line 2 of 3. Here is line 3 of 3. Here is line 1 to be deleted. Here is line 2 to be deleted.

Heres the first revised version:

This is a file used to demonstrate 3 way merging. This is the line in the diff1 file. Here This Here Here is line line is is line is line 1 of 3. added in diff1. 2 of 3. 3 of 3.

Here is line 2 to be deleted.

Heres the second revised version:

This is a file used to demonstrate 3 way merging. This is the line in the diff2 file. Here Here This Here is line is line line is is line 1 of 3. 2 of 3. added in diff2. 3 of 3.

Here is line 1 to be deleted.

Lets run 3 Way Merge on these files, placing the result in a new file, output.txt:

1. 2. 3. 4.

Invoke merge (Tools File Merge). SlickEdit displays the 3 Way Merge Setup dialog, shown in Figure 13-6. Enter base_file.txt for the Base file Filename. Enter rev1.txt for the Revision 1 Filename. Enter rev2.txt for the Revision 2 Filename.

267

Part II: Using SlickEdit

Figure 13-6

5. 6.

Enter output.txt for the Output file Filename. Click OK to invoke 3 Way Merge. SlickEdit displays 3 Way Merge, as shown in Figure 13-7. The output file starts with the contents from base_file.txt.

Figure 13-7

7.

Use the buttons to navigate the merge, and apply changes from either of the revisions to the output file as desired.

268

Chapter 13: Comparing and Merging


8. 9.
Click Close to finish 3 Way Merge. SlickEdit prompts you whether you want to save the changes to the output file. Click Yes to save the changes.

The 3 Way Merge tool can be particularly useful in combining multiple independent revisions from version control.

Backup Histor y
As weve mentioned, the diff and merge tools are often used in conjunction with version control. SlickEdit also provides a fine-grained change-tracking tool for changes made between commits into version control, or for changes made to files not in version control. Every time you save a file, SlickEdit stores the changes youve made since the last save. You can review these snapshots using the Backup History tool window. View this tool window via View Toolbars Backup History, or by invoking activate_deltasave (WROX: Alt+T, followed by H). The tool window is shown in Figure 13-8.

Figure 13-8

The tool window reflects the changes made to the current buffer. The list shows the date and time of each save. You can select a pair of saves, as shown in Figure 13-8, and use DIFFzilla to compare the file versions. The DIFFzilla headings for the panes display the version numbers you are comparing. You can also select a single save in the list and use DIFFzilla to compare it to the current buffer contents. This provides an easy way to find out exactly what you have changed in the file since your last save. The first time you edit a file with SlickEdit, there is no backup history for it until you save it at least once. If you make some changes, you cannot use the Backup History tool window to see them until the first save. (This limitation may be removed in a future version of SlickEdit.) For this situation, to see what changes you have made, use DIFFzilla directly to compare the on-disk version of the file with the buffer version. You can do this very quickly in the DIFFzilla setup dialog using keyin-buf-name (Alt+N):

1. 2. 3. 4. 5.

Invoke diff (Ctrl+=). SlickEdit displays the DIFFzilla setup dialog. Invoke keyin-buf-name (Alt+N). SlickEdit enters the buffer name in Path 1. Press Alt+2 to move the focus to Path 2. Invoke keyin-buf-name (Alt+N). SlickEdit enters the buffer name in Path 2. Press Enter to run DIFFzilla.

269

Part II: Using SlickEdit


Ensure that Use file on disk is unchecked for Path 1 (to use the buffer version) and checked for Path 2 (to use the on-disk version). Backup history changes are stored by default in the vsdelta subdirectory of your SlickEdit configuration directory. Therefore, for example, on Windows this might be in C:\Documents and Settings\ username\My Documents\My SlickEdit Config\12.0.0\vsdelta. You can change this and other backup history settings on the Backup tab of the File Options dialog (Tools Options File Options). Usually, its not important to know where the snapshots are stored: They just work. Be careful to keep the location in mind if you delete your SlickEdit configuration though you will lose your backup history.

Summar y
Comparing and managing differences between multiple versions of files is an inevitable part of a programmers job. Good version control practices can reduce the pain involved considerably, but you will still find that there are plenty of times you need to compare file versions, whether in your version control system or out of it. SlickEdit provides tools for comparing files and directories. DIFFzilla can be used within SlickEdit, or as a standalone tool in its own right. SlickEdits 3 Way Merge tool can be used to reconcile changes from different sources. Finally, SlickEdits Backup History tool window is a great way to see changes youve recently made to a file, independent of your version control system. Backup history is a valuable feature, but it is no substitute for proper version control. In the next chapter, we look at some of SlickEdits integration with two popular version control systems, CVS and Subversion. We will find that SlickEdit uses DIFFzilla extensively within its version control integration also.

270

Version Control
Version control should be a key part of any programmers workflow. (Every file involved in the writing of this book was checked into and versioned in a Subversion repository.) Whether you work in a large distributed team, or are coding alone on a personal project, version control tools are very useful in helping you manage changes and versions of your code base. Most programmers have been through a phase of using what I call ZIP file archive version control, which is pretty much what its name implies. If youre using ZIP files or other ad hoc copies of your source code for version control, you are probably spending a lot of time using the diff tool and scratching your head. You may also have some trouble explaining why you cannot reproduce the behavior found in released versions of your product, because you cannot reliably reproduce those versions! Do yourself (and your customers) a favor, and start using version control. SlickEdit provides support for several version control systems. In this chapter, we look at the two main popular open source version control systems: CVS and Subversion. As usual, we wont be studying these version control systems in minute detail. You should refer to the appropriate documentation for each version control system for more detail. The main point of this chapter is to show how SlickEdit uses Slick-C and macro commands to interact with version control. You can use macros within the SlickEdit environment to add your own preferred key bindings and valueadded commands. We show a set of possible key bindings for working with each of CVS and Subversion, and some sample macros that make these version control systems quicker and easier to use with SlickEdit. This should give you a start for building on your own requirements.

CVS
CVS, or the Concurrent Version System, is the venerable de facto standard open source version control system. It was developed in the 1980s and is widely used today, although its use may be declining, with many developers switching to Subversion.

Part II: Using SlickEdit


In the sections below, we go through common version control tasks with CVS. We assume that you have a CVS server already set up and that you are familiar with the basic CVS commands. If you are unfamiliar with CVS in general, you will need to consult reference documentation elsewhere to learn how to set it up and how to use its basic functions. The definitive guide to CVS is the Cederqvist manual, available online at http://ximbiot.com/cvs/manual/. CVS determines the default server and protocol from the CVSROOT environment variable. You can specify an alternative server and protocol using the -d option, but its usually easiest to use CVS by setting the CVSROOT environment variable. In our examples, we assume that you have CVSROOT set up for your CVS server. You can set CVSROOT in your operating system environment, or in vslick.ini. In our examples, well use the pserver protocol to access a CVS server over the network. On my system, the CVS server is on a host named vcs. Im using user name jhurst, and the repository is in directory /var/cvs on the server. My CVSROOT entry in vslick.ini looks like this:
CVSROOT=:pserver:jhurst@vcs:/var/cvs

Your details will obviously be different. CVS supports several other authentication schemes besides pserver, but we wont be covering those in this book. With the pserver authentication scheme, you can start a CVS session using the cvs login command. The CVS client stores your password in an encrypted form in the file .cvspass in your home directory during your session. This saves you from having to type the password for every command. You can make the client clear the password using the cvs logout command. In the setup examples below, we assume you are not logged in to CVS to start with.

Using an Existing Working Copy


If you already have a working copy of your project checked out from CVS, you can set up your SlickEdit project to use that working copy. Then you need to tell SlickEdit about your version control system. The steps below assume you already have a SlickEdit workspace set up, and that the files in it are a working copy from a CVS repository:

1.

Invoke vcsetup (Tool Version Control Setup). SlickEdit displays the Version Control Setup dialog, shown in Figure 14-1. This dialog allows you to select your version control system and configure its options. The dialog shown in Figure 14-1 is for Windows. The UNIX version is slightly different. (The UNIX version does not have SCC providers.) Check the Command-line systems box. CVS is a command-line system. Some version control systems provide API integration, but SlickEdit integrates with CVS via command-line commands. Select CVS in the list of Version Control Systems. Click Setup. SlickEdit displays the CVS Setup dialog, containing setup options specific to CVS. The dialog is shown in Figure 14-2. Ensure that the CVS executable is correct for your system. SlickEdit needs to be able to find the CVS executable in order to issue CVS commands.

2. 3. 4. 5.

272

Chapter 14: Version Control

Figure 14-1

Figure 14-2

6. 7.

Change other options according to your preferences. Click Login. SlickEdit displays the CVS Login dialog, shown in Figure 14-3. This dialog allows you to specify your repository and login details. In Figure 14-3, SlickEdit has filled in the User Id, Host, Repository, and Authentication type correctly from the CVS/Root file in the working copy.

Figure 14-3

273

Part II: Using SlickEdit


My CVS server is set up to use the pserver protocol, which is the most basic CVS authentication protocol. If you are using a different protocol, the details of connection will be different.

8. 9. 10. 11. 12. 13.

Click OK. SlickEdit prompts you whether you wish to set CVSROOT in vslick.ini. Click No. SlickEdit runs the cvs login command in a console to log in to your CVS server. The login command prompts you for your CVS password. Type your password, and press Enter. The console prompts you to Hit any key to continue. Press a key. The console closes. Click OK to dismiss the CVS Setup dialog. Click OK to dismiss the Version Control Setup dialog.

SlickEdit updates the project definition in the .vpj file to indicate that the CVS version control system is used with the project. You are now ready to start working with your files with version control.

Checking Out an Existing Project


If you dont have a working copy already checked out on your system, you can use SlickEdit to check out the project. Follow these steps:

1. 2.

Change to the directory under which you want to place the working copy. Invoke cvs-checkout-module (Tools Version Control Check Out Module). SlickEdit displays the first page of the Check Out CVS module wizard, shown in Figure 14-4. The page shows projects available on your CVS server.

Figure 14-4

3. 4.

Select the module you want to check out. Enter the path where you want the new working copy to be created.

274

Chapter 14: Version Control


5.
Click Next. SlickEdit shows the next page of the Check Out CVS module wizard, shown in Figure 14-5. This page shows the branches and tags that exist in the module. In Figure 14-5, there are no branches or tags; only the tip of the project is available.

Figure 14-5

6. 7. 8.

Select the branch or tag you want to check out. Click Finish. SlickEdit displays the Checkout workspace dialog, summarizing your options for checking out the module. Click OK to close the Checkout workspace dialog. SlickEdit invokes CVS to check out the module. CVS output is shown in the Output tool window. If everything worked correctly, you now have a new working copy.

Checking out a module does not change your working directory. If you checked out the module to another location, you still need to change directory to that location. Checking out a module also does nothing to create a SlickEdit project. If your SlickEdit project files are version controlled, you can now open the project in the working copy. Otherwise, you will need to create a new SlickEdit project for the files in the fresh working copy.

Reviewing Changes
When you are working with version control, you regularly need to review the local changes you have made and refresh your working copy with changes others have made. CVS achieves this with the cvs update command. In SlickEdits version control menu, there are several update variants available. Most of these update variants are implemented (for CVS) using the cvs-gui-mfupdate command. For example, to update your current project, you can use this command:
cvs-gui-mfupdate project_dir

If you want to update directories recursively under the project, add the r option. This macro uses our wrox_project_dir() function to update the current project, and all subdirectories:
_command void wrox_cvs_update_project() name_info(,) { cvs_gui_mfupdate(-r wrox_project_dir()); }

275

Part II: Using SlickEdit


Note that the macro requires the wrox_project_dir() function, defined in wrox_directories.e from Chapter 11. Also, the command only works when there is an active project. In the wrox_cvs.e file, this command is bound to Alt+V followed by U. When you invoke cvs-gui-mfupdate for your project, SlickEdit shows the CVS Update Directory window, which looks something like what is shown in Figure 14-6.

Figure 14-6

The window reflects the output of the cvs update command, using visual cues to indicate the status of files. You can move the mouse over the status icons to find out what they mean. In Figure 14-6, we see that:
board.cpp has local changes.

The SlickEdit workspace and project files gnu_queens.vpj and so on have not been added to version control. The file LICENCE.txt has been changed by another user. The file README.txt has been added by another user. The directory doc/ has been added by another user.

SlickEdit invokes cvs update with the n option, which causes CVS to report updated files on the server, but not to refresh them on the local disk. Use the Update or Update All button to accept refreshes of new or changed files from the server. For the local changes and the refreshed files, you can use the History or Diff buttons to find out more about changes. When you use the Diff button to compare revisions against other revisions or the local copy, SlickEdit fetches the necessary versions from CVS and then invokes the SlickEdit DIFFzilla tool to show the comparison. Figure 14-7 shows DIFFzilla in action, comparing the local changes in a file to the latest version in the repository. The headings above the panes indicate which revision is in each pane. Other buttons appear, such as Revert, when you select a file for which the action is valid. Right-click on a file, and use the context menu for other commands.

276

Chapter 14: Version Control

Figure 14-7

Adding Files
Its often easiest to add new files to CVS from the CVS Update Directory window. For example, lets add the SlickEdit project and workspace files in the sample project to CVS:

1. 2.

Select gnu_queens.vpj and gnu_queens.vpw in the CVS Update Directory window. Right-click on one of the files, and choose Add Files from the context menu. SlickEdit displays the Options for CVS Add dialog, shown in Figure 14-8. You can specify options for adding the file here, such as -kb for a binary file.

Figure 14-8

3.

Click OK to close the Options for CVS Add dialog. SlickEdit schedules the files for adding. The CVS Update Directory window updates the icons to indicate that the files are pending being added.

If you are in a new file and you wish to add it to CVS, you can do it with the cvs-add command (WROX: Alt+V, A). This approach can be quicker if you already have the file open in a buffer, but it does not give you the opportunity to use options such as -kb when adding a file. However, its unlikely you would add a binary file by having it open in a buffer. Adding files in CVS is a two-step process. After marking files to be added, they still need to be committed.

277

Part II: Using SlickEdit

Committing Changes
As with adding, you will usually commit changes from the CVS Update Directory window. Lets commit the newly added project and workspace files to CVS:

1. 2.

Select gnu_queens.vpj and gnu_queens.vpw in the CVS Update Directory window. Right-click on one of the files, and choose Commit selected files from the context menu. SlickEdit displays the Comment window, as shown in Figure 14-9.

Figure 14-9

3. 4. 5.

Enter Adding SlickEdit project and workspaces for the comment. Check the Apply to all checkbox to apply your comment to both files. Click OK. SlickEdit commits the files, and they are removed from the CVS Update Directory window.

Merge Conflicts
If you have made local changes to a file and another user commits changes on the same lines to the server, CVS reports a merge conflict when you update your local copy. Figure 14-10 shows the CVS Update Directory window showing board.cpp with a merge conflict.

Figure 14-10

278

Chapter 14: Version Control


The icon indicates that the file has a merge conflict, because it has both a local and remote modification and also a yellow error triangle. If you want to find out more about what has changed in the file, you can use DIFFzilla. If you click Diff, you get a window prompting you which revisions to compare, as shown in Figure 14-11.

Figure 14-11

These choices reflect the different revisions involved in the merge conflict: The older repository version (1.2 in the example). The new changes committed by another user (1.3 in the example). Your own local changes.

You can choose any pair and use DIFFzilla to compare them. Once you have decided which changes you would like to keep, you have two basic choices: You can click Revert to throw away your own changes and revert to the latest repository version. You can click Update to cause CVS to insert its merge markers into the file. You then edit the merged lines until you have resolved all the conflicts, and then commit the file.

Using Commit Sets to Group Changes


A best practice of using version control is that a given change set should pertain to one and only one feature or bug fix. That makes it a lot easier to read the history of the project: You can see exactly why each change was made to a given file if changes reflect specific features or issues. Also, if it becomes necessary to back out a feature or fix, its a lot easier if the changes for it are not mixed up with other changes. A good policy to follow is to commit early, commit often. This gets your code in front of the other developers as early as possible, so that they can provide feedback and identify problems, rather than waiting until the code is completely finalized. Also, integration and build problems resulting from combining changes from different developers are discovered as early as possible. Sometimes, though, you find that you have made local changes that relate to different things and should not be committed all together. This often happens, for example, when you are working on one fix and discover that you need to refactor a class or function in a way that is tangential to your fix. For complex fixes, you might find that you touch several different modules for different reasons. By the time you realize it, you could have a couple dozen or more files changed that need to be committed separately to make clear the reasons for the different changes.

279

Part II: Using SlickEdit


Commit sets are a standard way of dealing with this situation. Normally when you use CVS version control, you probably wont use commit sets, because they involve extra steps and can interrupt your workflow for simple changes. For complex changes, however, they are very useful. SlickEdit allows you to create named commit sets, specify the check-in message for them, and move files between them. Suppose we have changed four files in our project, but for two different reasons: For Project Administration, weve added .cvsignore and changed README.txt. For Documentation, weve updated board.cpp and board.h, adding some comments. Lets create some commit sets for these two unrelated changes. (This example used only four files. Obviously, for four files you would simply select the sets of related files in the CVS Update Directory and commit them together. Use commit sets when you have more files and its not so easy to remember which file belongs with which change.) Follow these steps:

1.

Invoke commit-sets (Tools Version Control Commit sets). SlickEdit displays the CVS Commit Sets dialog, shown in Figure 14-12. This dialog allows you to manage your commit sets.

Figure 14-12

2. 3. 4. 5.

Click Add. SlickEdit displays the New Commit Set dialog. Enter Project administration for the New Commit Set Name. Click OK to close the New Commit Set dialog. SlickEdit adds the commit set to Current commit sets. Repeat Steps 24 to add a commit set called Documentation.

The first commit set added is Project administration. Its shown in bold because it is the default commit set. When you add files to commit sets in the CVS Update Directory window, they are added to the default commit set.

280

Chapter 14: Version Control


Having created a commit set, you need to add files to it and specify the check-in comments. Lets add the source files and check-in comment to the Documentation commit set:

1. 2. 3. 4. 5.

Select the Documentation commit set on the CVS Commit Sets dialog. Click Edit. SlickEdit displays the editing dialog for the commit set. Click Add files. SlickEdit displays an Open dialog for selecting files for adding. Select board.cpp and board.h. Click OK to close the Open dialog. SlickEdit adds the files to the commit set. The result is shown in Figure 14-13.

Figure 14-13

6. 7.

Enter Added some documentation comments as the Comment for all files. Click OK to close the CVS Commit Sets editing dialog.

SlickEdit allows you to specify a different comment per file in a commit set. However, this runs contrary to the idea of a change set. With CVS, theres no technical reason why you cant use a different comment for different files, because each file is committed separately to the repository, even when using a commit set feature such as SlickEdits. With other version control systems, such as Subversion, change sets are atomic, and all files in the change set must share the same comment. Also, even with CVS, many tools rely on files committed together sharing the same comment in order to group them and reconstruct change sets retrospectively. For example, the FishEye CVS repository browser (http://www.atlassian.com/software/fisheye/) constructs synthetic change sets for CVS commits using the check-in comments. Also, the cvs2svn tool (http://cvs2svn.tigris.org), used to convert CVS repositories to Subversion, creates true Subversion change sets from groups of CVS

281

Part II: Using SlickEdit


commits sharing the same comments. For this reason, I recommend that you use a single comment for all files in a commit set. The Add File button on the Commit Set editor is one way to add files to a commit set. It is nice if you know what files you want in the commit set, and it also has the advantage that a file doesnt have to have any local changes at the time you add it to the set. The other way to add files to a commit set is via the CVS Update Directory window. Lets add the other two changed files to the default commit set, using the CVS Update Directory window:

1. 2. 3.

Invoke wrox-cvs-update-project. SlickEdit displays the CVS Update Directory window. Select .cvsignore and README.txt. Right-click on one of the files, and select Add to commit set from the context menu. SlickEdit adds the files to the default commit set.

As of this writing, SlickEdit allows you to add files to more than one commit set. Thats probably not what you want to do; thus its up to you to make sure your files are only in the commit sets you intend. Once you have all your changes done and all your files in the correct commit sets with the check-in comments entered, you can commit your commit sets. To commit the Documentation commit set, follow these steps:

1. 2. 3.

Invoke commit-sets (Tools Version Control Commit sets). SlickEdit displays the CVS Commit Sets dialog. Select the Documentation commit set. Click Commit. SlickEdit verifies that all files have check-in comments and then commits the files. If any file does not have a check-in comment, SlickEdit displays a warning message in a confirmation dialog.

After you commit a commit set, it is moved from the Current commit sets group to the Past commit sets group.

Branches and Tags


Branches and tags are the fundamental way of organizing your history and versions in version control. Branching and tagging are relatively infrequent operations and not normally part of your regular editcompiletest workflow. For this reason, SlickEdit doesnt provide branching and tagging commands in the editor. You can branch and tag your files from the command line using the normal CVS commands. The commands can be entered in SlickEdits Build tool window, if you like. For example, to create a release branch for release 1.1 of the gnu_queens project, you would enter a command like:
cvs rtag b RB_01_01 gnu_queens

Figure 14-14 shows the command as executed in the Build tool window.

282

Chapter 14: Version Control

Figure 14-14

After creating a release branch, you typically need to check out a working copy of that branch, complete final changes, and then tag the release. Lets do that within SlickEdit:

1. 2. 3. 4.

Invoke workspace-close (Project Close Workspace) to close the current workspace. Invoke activate-build (WROX: Alt+T, B) to activate the Build tool window. Enter the command cd .. to change your local directory to the parent of your project. (This is assuming that you were in the project directory to start with.) Enter this command to check out the 1.1 release branch of the gnu_queens project:

cvs co r RB_01_01 d gnu_queens_cvs_01_01 gnu_queens

SlickEdit shows the output of the CVS command in the Build tool window. If the command worked correctly, you now have the 1.1 release branch checked out in the gnu_queens_01_01/ subdirectory.

5.

Invoke workspace-open (Project Open Workspace), and navigate to and open the gnu_queens.vpw workspace in the release branch subdirectory. You are now working with the project in the release branch.

You can do final release preparation and testing in the release branch, while the rest of the team works in the tip. Once you have built and released the release, you can tag it, so that you can get back to the exact source code revisions for the release at any future time. Enter this command in SlickEdits Build tool window, to create a tag for release 1.1.0 of the gnu_queens project:
cvs tag REL_01_01_00

For the tasks involved in branching and tagging, SlickEdits Build tool window works very well with regular CVS commands. SlickEdit also provide a powerful graphical history browser that you can use to browse branches and tags in your project.

Browsing the History


You can browse the history for a particular file in your project. To do this, follow these steps:

1. 2.

Open the file you want to browse. Invoke cvs-history (Tools Version Control History for <filename>). SlickEdit displays the Log info window, shown in Figure 14-15.

283

Part II: Using SlickEdit

Figure 14-15

In this window, you get a view of all the revisions made to the file, across all the branches. You can click on any revision to examine the date and comment for the revision. You can compare a revision to the tip, or to any other revision.

Keyboard Bindings
In SlickEdits default configuration, the user interface for CVS operations is accessed through menus. Most of the commands are available in at least three different ways: From the main menu, under Tools Version Control. From the context menu in a file. From the context menu in the Projects tool window.

The context menu approaches require the mouse and thus are not very suitable for commonly used operations. The Tools Version Control menu is the fastest way to access the version control features in the default configuration. However, all the SlickEdit CVS functionality is also available in the form of SlickEdit commands. Therefore, its easy to set up convenient keyboard shortcuts for the commonly used commands. In the file wrox_cvs.e on the CD-ROM, you will find one possible keyboard binding scheme for CVS commands. This scheme uses the same technique as the WROX emulation uses for accessing tool windows. Because there are quite a few CVS commands and only so many keystrokes available, the scheme uses a prefix key for CVS commands. All the shortcuts begin with Alt+V, which is followed by a mnemonic for the command. Thus, for example, the command to update the current project (wrox-cvs-update-project) has the shortcut Alt+V followed by U. Table 14-1 shows a subset of the SlickEdit CVS-related commands. Commands that work on the current file will prompt for a file if none is open. The WROX keyboard shortcuts are shown, as well as a

284

Chapter 14: Version Control


description of the command. Use the WROX shortcuts provided here as an example, to set up your own customized shortcuts to streamline your workflow.

Table 14-1
Command
commit-set-add commit-sets cvs-add cvs-checkout-module cvs-commit cvs-diff-with-tip cvs-history cvs-login cvs-query cvs-remove cvs-review-and-commit

Key (none) (none) Alt+V, A Alt+V, M Alt+V, C Alt+V, D Alt+V, L

Description Adds the current file to the default commit set. Shows the commit sets. Adds the current file to CVS version control. Checks out working copy of module from repository. Commits the current file. Shows the local changes. Shows the Log info window for the current file. Invokes CVS login.

Alt+V, Q Alt+V, R Alt+V, V

Invokes the CVS query facility. Removes the current file from version control. Displays DIFFzilla showing local changes, allowing revision. Then follows with commit dialog. Displays the CVS Setup dialog. Updates the current file. Updates the current directory. Updates the current project.

cvs-setup cvs-update cvs-update-directory wrox-cvs-update-project

(none) (none) (none) Alt+V, U

Subversion
Subversion was designed in the early part of this decade to be a replacement for CVS and to address its shortcomings. Some of the significant advantages of Subversion over CVS are: It supports the history of renames and moves. It supports transactional commits of multiple files. When committing a set of files together, all of them are committed, or none of them is. The repository structure and communication protocols are designed to minimize network use. Subversion can perform many operations without using the network.

285

Part II: Using SlickEdit


Despite the differences, most of the Subversion features with SlickEdit work just the same as the CVS features. For example, commit sets are the same; thus we wont repeat the details in this section. The principles of branching and tagging are the same as for CVS, but the details are rather different; therefore, we discuss branching and tagging with Subversion in some detail. If you are unfamiliar with Subversion, you will need to consult reference documentation elsewhere to learn how to set it up and use its basic functions. A free version of Version Control with Subversion is available online at http://svnbook.red-bean.com/. Many other books also cover effective use of Subversion. When you issue commands against the remote repository, you always must specify a full URL. When you issue commands that work with the working copy, Subversion obtains the repository URL (if necessary) from control files in the working copy. In our examples, well use the svn+ssh protocol, which is a way of accessing Subversion remotely via an SSH tunnel. Subversion supports several other protocols, but we wont look at those in this book. On my system, the Subversion server is on the same host as the CVS one, a machine named vcs. The Subversion repository for the examples is in the directory /var/svn/slickedit/ on that host. Because Im using the user name jhurst, the repository URL is svn+ssh://jhurst@vcs/var/svn/slickedit. When using Subversion on the command line, the URLs can be rather long and painful to type. Its handy to define some environment variables for often-used URLs or parts of URLs. For example, in my Cygwin .bash_profile, I define the environment variable SVN like this:
export SVN=svn+ssh://jhurst@vcs/var/svn/slickedit

To make the environment variable available in SlickEdit, I put the following line in vslick.ini:
SVN=svn+ssh://jhurst@vcs/var/svn/slickedit

Make the appropriate changes for your environment. Usually when you are working with Subversion, you dont want to see the hidden admin files that it places in its .svn/ directories. For example, when you are defining projects, you dont want to include those files in the project for tagging. When you are navigating the directory tree with the Open dialog, its usually easier if the .svn/ directories do not appear. The exception to this is, of course, when you are using SlickEdit to examine a Subversion admin file when you are experiencing problems with Subversion itself. But thats an unusual circumstance; thus most of the time you want the .svn/ directories to be invisible. On Windows, one easy way to do this is to choose Do not show hidden files and folders in the Windows Explorer Folder Options. SlickEdit honors the value this setting has at the time SlickEdit starts. (Thus, if you change the setting, you need to restart SlickEdit to pick it up.) If you prefer to use Show hidden files and folders on Windows, you have to take steps to prevent SlickEdit from including .svn/ files in projects. If you are defining a project and adding a tree or a wildcard, you can enter *\.svn\* in the Exclude or Exclude filespecs text field.

286

Chapter 14: Version Control

Configuring SlickEdit for Subversion


To configure SlickEdit for Subversion, follow these steps:

1. 2. 3. 4.

Invoke vcsetup (Tools Version Control Setup). SlickEdit displays the Version Control Setup dialog. Check the Command-line systems box. Subversion is a command-line system. Select Subversion in the list of Version Control Systems. Click Setup. SlickEdit displays the Subversion Setup dialog, containing setup options specific to Subversion. The dialog is shown in Figure 14-16.

Figure 14-16

5. 6. 7.

Ensure that the Subversion executable is correct for your system. Click OK to close the Subversion Setup dialog. Click OK to close the Version Control Setup dialog.

Creating a New Project


Creating a new project in Subversion is simply a matter of issuing the appropriate svn mkdir commands. As with CVS, SlickEdit does not provide GUI features for project management or branching or tagging in Subversion. You have to create projects using the command line. You can create the gnu_queens project in subversion with these commands:
svn mkdir %SVN%/gnu_queens -mCreating directory /gnu_queens/. svn mkdir %SVN%/gnu_queens/trunk -mCreating directory /gnu_queens/trunk/.

(If youre using Cygwin or UNIX, you need to use $SVN instead of %SVN%.) In these examples, well follow the normal Subversion convention that the main trunk, where most of the project changes occur, is in the trunk/ subdirectory. Branches and tags will be in the branches/ and tags/ subdirectories, respectively. Lets create the branches/ and tags/ subdirectories for the project too:
svn mkdir %SVN%/gnu_queens/branches -mCreated gnu_queens/branches directory. svn mkdir %SVN%/gnu_queens/tags -mCreated gnu_queens/tags directory.

In order to add files to the project, you need to get a working copy.

287

Part II: Using SlickEdit

Checking Out a Working Copy


To check out a working copy from Subversion, follow these steps:

1. 2. 3. 4.

Invoke svn-browse (Tools Version Control Check Out). SlickEdit displays the Subversion Browser. Before you can browse repositories, you need to define them in the browser. Click Add to List. SlickEdit displays the Add Subversion Repository dialog. Enter the repository URL. Click OK to close the Add Subversion Repository dialog. SlickEdit refreshes the Subversion Browser with the new repository and the directories found under it.

When SlickEdit executes Subversion commands, you may see one or more console windows appear on your screen. This is because SlickEdit executes Subversion commands by shelling out to a console process. The windows should disappear when the commands finish.

5.

Expand the tree for gnu_queens. SlickEdit shows the trunk/, branches/, and tags/ subdirectories under the gnu_queens project. The window is shown in Figure 14-17.

Figure 14-17

6. 7.

Select the trunk/ entry under gnu_queens. Click Checkout. SlickEdit displays the Checkout from Subversion dialog, shown in Figure 14-18.

Figure 14-18

8. 9.

Enter the desired location for the project to be checked out to. Click OK. SlickEdit checks out the project.

288

Chapter 14: Version Control

Reviewing and Committing Changes, Adding Files


The procedure for reviewing changes is the same for Subversion as for CVS. As with CVS, you may find it handy to have a macro that you can use to update and review changes in your entire project. Heres a Subversion version of the macro:
_command void wrox_svn_update_project() name_info(,) { svn_gui_mfupdate(wrox_project_dir()); }

This command opens the Subversion Update Directory window, showing all the changes in your project. The wrox_svn.e file supplied with this book includes this macro, with a keyboard binding so that you can invoke it with Alt+V followed by U. Figure 14-19 shows the window, with the same set of changes we saw for the CVS example. The format is slightly different, because the Subversion support is able to tell us more about the new directory (doc/) that was added to the repository.

Figure 14-19

With CVS, you can review and update files changed on the server into your working copy individually. That is because with CVS, every file is committed separately. With Subversion, change sets are committed atomically; thus you cannot update just one file from a change set into your working copy. If you try to use the Update button to update an individual file, SlickEdit prompts with a confirmation box, to check that you want to update the entire directory. Adding files and committing changes with Subversion are the same as for CVS.

Merge Conflicts
If you have local changes in a file when you update from the repository, and there is a new version of the same file with changes on the same lines, it creates a merge conflict. When this happens, Subversion creates four files in your working copy, to allow you to resolve the conflict. For example, I created a merge conflict on board.cpp. I had been working on revision 3 in my working copy, but revision 7 was checked in with changes to the same line. When I ran svn update, I got these files in my directory:
board.cpp The working copy file, now with merge conflict markers in it on the conflict lines. board.cpp.mine The file with the local changes as they were before running svn up.

289

Part II: Using SlickEdit



board.cpp.r3 The file as it was in the repository at revision 3. board.cpp.r7 The file as it is in the repository at revision 7.

You can use the four files to decide what you want to do with each merge conflict. Make your edits on the file with the original name, that is, board.cpp in this example. Use the others for reference to see what youre doing, or in case you make a mistake. When you have resolved all the conflicts, you should have removed all the merge conflict markers from the file. At that point, issue this command on the command line or in the Build tool window:
svn resolved board.cpp

Subversion reports:
Resolved conflicted state of board.cpp

Branches and Tags


In Subversion, branches and tags are not specific concepts in the system. Instead, branches and tags are done by simply copying the source tree using svn copy. The designation of a copy as a branch or tag is simply a matter of convention. A common convention is to put the main line of development in a subdirectory under your project in the repository called trunk/, and to place branches and tags in subdirectories called branches/ and tags/, respectively. Following this convention, lets create a release branch for the gnu_queens project. Issue this command in the Build tool window:
svn copy %SVN%/gnu_queens/trunk %SVN%/gnu_queens/branches/RB-01.01 -mCreated release branch for gnu_queens 1.1.

After you have created a release branch, you need to switch to it to do the final testing and preparation for a release. To switch to a branch with Subversion, you can check it out as a separate working copy if you prefer. Or you can use the svn switch command. For example, to switch to the RB-01.01 release branch, use this command in the Build tool window:
svn switch %SVN%/gnu_queens/branches/RB-01.01

To return to the trunk, the command is:


svn switch %SVN%/gnu_queens/trunk

The switch command switches your working copy to the desired branch. The advantages of using svn switch are: It is simple. It is usually far quicker than checking out a whole extra copy of the project, especially if there are many files with relatively few changes. You dont have lots of different copies of the code on your system. You dont have to switch projects in your editor.

290

Chapter 14: Version Control


The main disadvantage of using svn switch is that sometimes you might forget which branch you are in. To check which branch you are currently working on with your working copy, use the svn info command. When you have completed all the testing and other work for a release and it is finished, you should tag it so that you have a reproducible build. To tag the 1.1.0 release of the gnu_queens project, use this command:
svn copy %SVN%/gnu_queens/branches/RB-01.01 %SVN%/gnu_queens/tags/REL-01.01.00 -mTagged gnu_queens 1.1.0.

As you follow this convention for branches and tags, you will find it very easy to navigate to and check out particular branches and tags using SlickEdits Subversion Browser. Figure 14-20 shows the browser now that we have added a branch and a tag.

Figure 14-20

Browsing the History


To view the history for a file, follow these steps:

1. 2.

Open the file you want to browse. Invoke svn-history (Tools Version Control History for <filename>). SlickEdit displays the Subversion info window, shown in Figure 14-21.

In this window, you get a view of all the revisions made to the file, from its start to the latest revision. Subversion tracks changes across copies, moves, and renames, so you can see the history across these operations. Because branches and tags are done using svn copy, you can see the history across any branches or tags in the sequence from the current revision back to the start. Changes that occur on a branch other than the current one, including copies, moves, and renames as well as normal changes, cannot be seen. Thus, if the working copy is the 1.1 release branch, we cant see changes made to the trunk after the release branch was created. Similarly, if the working copy is the trunk, we cant see changes made in any other branch. You can, of course, use the command line to do arbitrary svn log or svn diff commands.

291

Part II: Using SlickEdit

Figure 14-21

Keyboard Bindings
As with CVS, we can improve the workflow with Subversion a little bit by adding some custom key bindings. The file wrox_svn.e supplies an example for Subversion. Table 14-2 shows common SlickEdit Subversion commands, as well as key bindings from wrox_svn.e.

Table 14-2
Command
commit-set-add commit-sets svn-add svn-browse svn-commit svn-diff-with-tip svn-history svn-remove svn-revert

Key (none) (none) Alt+V, A Alt+V, B Alt+V, C Alt+V, D Alt+V, L Alt+V, R Alt+V, T

Description Adds the current file to the default commit set. Shows the commit sets. Adds the current file to Subversion. Opens the Subversion Browser. Commits the current file. Shows the local changes. Shows the Log info window for the current file. Removes the current file from version control. Reverts the local changes on the current file.

292

Chapter 14: Version Control


Table 14-2 (continued)
Command
svn-review-and-commit

Key Alt+V, V

Description Displays DIFFzilla, showing local changes, allowing revision. Then follows with commit dialog. Displays the Subversion Setup dialog. Updates the current file. (This command is not really meaningful for Subversion.) Updates the current directory. Shows Update Directory window for the current project.

svn-setup svn-update

(none) (none)

svn-update-directory wrox-svn-update-project

(none) Alt+V, U

You will notice that the commands for Subversion are mostly different from those for CVS (with the exception of commands for commit sets), but the keyboard shortcuts are the same. The keyboard shortcuts are provided as examples, to allow you to customize them to your own workflow. If you are using both CVS and Subversion, you need to come up with a different scheme, allowing use of both sets of commands. One approach would be to use a different prefix key for CVS and Subversion. Another approach might be to create a macro to load the appropriate CVS/Subversion key bindings when you switch projects. Or, you might be happy simply to load the key bindings you prefer manually when you need them.

Summar y
In this chapter, we looked in detail at SlickEdits support for CVS and Subversion, two popular opensource version control systems. SlickEdit also supports several other proprietary systems. If your company is using a particular system, thats great, and hopefully SlickEdit supports it. (If SlickEdit doesnt support it, ask them to!) If you are looking for a great system that costs nothing, download Subversion. It has all the features most people need, its quite fast and very reliable, and it is used widely both in open-source and commercial environments. In the next chapter, we move on to some other tools SlickEdit provides, which can also be used as standalone tools in their own right.

293

Part III: Advanced SlickEdit


Chapter 15: Other Tools Chapter 16: Slick-C Macro Programming Chapter 17: Customization

Other Tools
As weve seen, SlickEdits DIFFzilla program is a useful program that is integrated in the editor but can also be used standalone, for comparing files or directories. SlickEdit includes several other tools that you can also use within the editor, but may find useful in their own right. SlickEdits remote ancestor was an IBM internal-use DOS editor in the 1980s. Along with the DOS editor, IBM also developed various PC productivity applications. One of the most popular of these was a file manager called FileMan. Other similar products existed in the DOS days outside IBM, such as XTree Gold. One idea that reoccurred a few times in text-mode computing was combining the text editor with the file manager, often by implementing the file manager in the text editor. This happened on the IBM VM/CMS mainframe operating system, for example, with the XEDIT text editor and FILELIST file manager. SlickEdit contains a text-based file manager implemented in Slick-C. You can use the file manager to browse and manage your files and directories and, of course, to open files. You can also use Slick-C in conjunction with the file manager to automate tasks involving both the files and the editor. The file manager is intended for use on file systems visible on your machine, that is, local file systems or network attached ones. Using the FTP tool window, you can also open and edit files on remote hosts via the FTP or SFTP/SSH protocols. Finally, SlickEdits Regex Evaluator tool window can be used to test regular expressions in any of SlickEdits supported regex styles. In this chapter, we take a brief look at each of these tools.

Part III: Advanced SlickEdit

The F ile Manager


You can use the file manager for various file management tasks. You can also use it to navigate directories and open files on your system. But perhaps the most powerful use of the file manager is to use Slick-C to automate tasks on files with SlickEdit. To invoke the file manager, follow these steps:

1.

Invoke the fileman command (File File Manager New File List). SlickEdit displays the List Files dialog, as shown in Figure 15-1.

Figure 15-1

2. 3.

Enter the path for the directory you want to work with. Click OK. SlickEdit opens a file manager buffer with the files in the given directory, as shown in Figure 15-2.

Figure 15-2 To add more files to the list, use the fileman command with the append option (File File Manager Append File List). The file manager can mix file listings from multiple directories. Instead of using the menu to list files in the file manager, you might find it quicker to invoke the list or dir command on the SlickEdit command line. Specify the directory for the list as a command-line argument, or list the working directory by default. With list or dir, you can also use some options, which are shown in Table 15-1. The list and dir commands are almost identical. With list, Tree File List is on by default; with dir, it is off. With dir, directory files are included by default, and directories are sorted to the top. With list, directory files are excluded by default, but if they are included, they are sorted with the other files in the list. This makes dir more suitable for working with a single directory at a time and navigating directories, and list more suitable for working with an entire subtree in one list. The ls command is also available, as an alias for dir.

298

Chapter 15: Other Tools


Table 15-1
Option
-|+D -|+H

Description Exclude/include directory files. Exclude/include hidden files. Ignored on UNIX; on Windows the default follows the Windows Explorer Show all files setting. Append path. Default is on. Exclude/include system files. Ignored on UNIX; on Windows the default follows the Windows Explorer Show all files setting. Tree file list. (Includes subdirectories.)

-|+P -|+S

-|+T

File Manager Commands


You can perform many different operations in the file manager. The file manager commands and shortcut keys are shown in Table 15-2. These commands can also be invoked through the right-click context menu. There are the usual sorts of things, like move, copy, and delete. There are also several commands concerning selections. Finally, you can run arbitrary commands on files selected in the file manager.

Table 15-2
Command
fileman-space fileman-enter select-all fileman-backup fileman-copy fileman-delete fileman-edit fileman-find fileman-replace fileman-move fsort

Key Space Enter Alt+Shift+A Alt+Shift+B Alt+Shift+C Alt+Shift+D Alt+Shift+E Alt+Shift+F Alt+Shift+G Alt+Shift+M Alt+Shift+O

Description Toggles select if file cursor is on. Edit file at cursor, or insert directory list. Select all files. Back up (copies) selected files to a directory. Copy selected files. Delete selected files. Edit selected files. Run multifile search in selected files. Run multifile search and replace in selected files. Move selected files. Sort list. continued

299

Part III: Advanced SlickEdit


Table 15-2 (continued)
Command
fileman-attr for-select deselect-all select-reverse select-attr select-ext gui-select-ext select-mark

Key Alt+Shift+P Alt+Shift+R (none) (none) (none) (none) (none) (none)

Description Set DOS attributes. Repeat a command on each selected file. Deselect all selected files. Reverse selected files. Select files based on DOS attributes. Select files based on given extension. Select files based on extension. Select files marked with a (character or line or block) selection. Deselect files marked with a selection. Empty the list. Unlist the selected files. Unlist files based on given extension. Unlist files based on extension. Unlist files based on DOS attributes. Unlist files based on filename matching a search string. Read a list of filenames from a file. Write the list of selected filenames to a file.

deselect-mark unlist-all unlist-select unlist-ext gui-unlist-ext unlist-attr unlist-search

(none) (none) (none) (none) (none) (none) (none)

read-list write-list

(none) (none)

Most GUI file managers use a tree on the left-hand side to navigate the directory structure, and a file list pane on the right-hand side to show files. The file list pane contains only files for the currently selected directory. The neat thing about text-based file managers is that you can list arbitrary combinations of files from different directories. Using fsort, you can group similar files together by name or extension.

Selecting Files
In order to do things with files in the file manager, you need to select files to operate on. You can toggle selection on the file on the current line by pressing Space. You can also use the various select and deselect commands to turn many selections off and on quickly.

300

Chapter 15: Other Tools


Using the various selection commands and the unlist-select command, you can easily filter the list down to the files in which youre interested. For example, to reduce a file manager list to show only .cpp files, enter these commands:
deselect-all select-ext cpp select-reverse unlist-select

You can combine these commands into new shortcut commands. For example, the macro below defines the command wrox-retain-exts. You can use this command to unlist all files in the list apart from the extensions provided as arguments to the command:
_command void wrox_fileman_retain_exts(_str exts=) name_info(,VSARG2_REQUIRES_FILEMAN_MODE) { exts = prompt(exts, Extensions to retain); deselect_all(); select_ext(exts); select_reverse(); unlist_select(); }

Automating Tasks
You can use the file manager to automate tasks in SlickEdit. Heres an example from Hartmut Schaefer (hs2). SlickEdit usually recognizes files as C++ header files by the extension being associated with C mode. But some libraries, such as the standard C++ library and some third-party libraries, use extensionless header files. SlickEdit recognizes an extensionless file as a C++ header file if both of the following conditions are true: The path of the file matches the regular expression in the macro variable
def_cpp_include_path_re.

The filename is in the space-delimited list of filenames in the macro variable


def_user_langext_files.

Both of these macro variables are normally managed from the GUI configuration on the Other tab of the C/C++ Formatting Options dialog (Tools Options File Extension Setup, C/C++ Options button). However, if you have a lot of header files to add to the list, it can be rather tedious to add them using the GUI. Instead, you can make use of the file managers ability to run arbitrary commands for selected files. Define this simple macro:
_command void wrox_addextlessfile(_str file = ) { message(file=[ :+ file :+ ]); int idx = find_index(def_user_langext_files, VAR_TYPE); _str val = _get_var(idx); strappend(val, file); _set_var(idx, val); }

301

Part III: Advanced SlickEdit


The macro receives a filename and appends it to the space-delimited list in def_user_langext_files. To use this macro with the file manager, follow these steps:

1. 2. 3.

Invoke list to open a file manager buffer with the directory containing the extensionless header files. Select all the extensionless header files. Invoke for-select (Alt+Shift+R). SlickEdit displays the Repeat Command on Selected dialog, shown in Figure 15-3.

Figure 15-3

4. 5.

Enter wrox_addextlessfile %n for the command. Click OK. SlickEdit applies the command for each selected file, passing the name of the file (without extension or path) to the command. The macro adds the filenames to the spacedelimited list.

If you use this technique, remember to configure your Extensionless C++ File Path Regular Expression too; the macro as shown deals with the files only. You should be able to adapt this technique for your own needs when you need to do operations in SlickEdit on several files.

FTP/SSH for Remote Editing


SlickEdits FTP connectivity is perfect for times you need to browse or edit files on a remote host. You wouldnt use it for coding, but it is great for browsing log files or editing configuration files on servers. As well as FTP, SlickEdit also supports connectivity via SSH, commonly used for logging into servers these days. Lets work through an example of setting up a SlickEdit connection to a remote machine.

1. 2.

Open the FTP tool window. (Using the WROX emulation, you can do this with Alt+T followed by T.) The FTP tool window is shown in Figure 15-4. There are currently no connections. Click the icon with the green plus sign to create a new connection. SlickEdit displays the Connect dialog, shown in Figure 15-5. There are currently no connection profiles.

302

Chapter 15: Other Tools

Figure 15-4

Figure 15-5

3.

Click Add. SlickEdit displays the Add FTP Profile dialog, shown in Figure 15-6.

Figure 15-6

303

Part III: Advanced SlickEdit


4.
Fill in the details for your connection in the Add FTP Profile dialog. You can choose either FTP or SFTP/SSH. If you use FTP, you can optionally specify the host type. If you use SFTP/SSH, you can optionally specify the authentication type. If you use SFTP/SSH on Windows, SlickEdit requires OpenSSH to be installed.

You can install OpenSSH as part of the free Cygwin UNIX emulation package. See http://www.cygwin.com. You cannot use PuTTY. OpenSSH is required.

5. 6. 7.

Click OK to close the Add FTP Profile dialog. SlickEdit adds the profile to the list available in the Connect dialog. Click Connect. If you are using SFTP/SSH on Windows, SlickEdit confirms the location of your ssh executable. The FTP tool window shows connection progress and then the directory and directory listing for the connection.

You can now navigate the directory tree on the remote host and edit files, provided you have appropriate permissions via your authentication credentials. You can create and open multiple FTP or SSH host connections at the same time. Select between connections in the top dropdown box in the FTP tool window. This makes SlickEdit a useful tool for browsing and analyzing server configurations and logs.

The FTP Client


In addition to the FTP tool window, which is used for opening and editing remote files in the editor, SlickEdit also provides the FTP Client tool window. This tool window is a GUI FTP client you can use to browse local and remote directories and upload or download files. The FTP Client tool window is shown in Figure 15-7.

Figure 15-7

304

Chapter 15: Other Tools


Note that the FTP tool window and FTP Client tool window are two distinct tool windows. They are displayed and hidden independently. However, they are linked, in that they share connection profiles and open connections. If you open a connection in the FTP tool window, it is available in the FTP Client tool window, and vice versa. At the time of writing (i.e., as of SlickEdit 12.0.2), the FTP tool window is activated with activate-ftp and toggled with toggle-ftpopen. The FTP Client tool window is toggled with toggle-ftp and appears to have no command simply to activate it. This inconsistency may be remedied in a future version of SlickEdit. In the meantime, its easy to add the missing activate command:
_command activate_ftpclient() name_info(,VSARG2_EDITORCTL) { return activate_toolbar(_tbFTPClient_form,_ctl_profile); }

Using HTTP To Open Web Pages


Its worth noting that as well as using the FTP tool window to browse or edit files via FTP or SSH protocols, you can also open files for browsing via HTTP. The edit command supports http:// URLs as filenames. Thus, for example, you can open the web page of my web site using this command on the SlickEdit command line:
edit http://www.skepticalhumorist.co.nz/index.html

However, you cannot change or save files opened this way.

The Regex Evaluator


SlickEdit provides the Regex Evaluator tool window, which you can use to test regular expressions in any of SlickEdits supported styles. You can open the Regex Evaluator tool window via View Toolbars as with other tool windows. You can also invoke activate-regex-evaluator (WROX: Alt+T followed by X). The Regex Evaluator tool window is shown in Figure 15-8. You enter a regular expression into the Regular Expression field, specify options, and enter one or more test strings in the Test Cases text area. The tool window updates automatically to indicate which test strings match the expression. In Figure 15-8, the expression matches dates in MM/DD/YYYY format. (It also matches DD/MM/YYYY.) The delimiters can be slashes or hyphens, and the months and days can each be one digit or two. The test expressions test most of the possibilities. The arrows in the left margin indicate matched test strings. The highlighted chunks of the test strings correspond to matching groups in the expression. The tool window even allows you to save and load regular expressions and their options and test strings. The data are saved as XML in the file you specify.

305

Part III: Advanced SlickEdit

Figure 15-8

Summar y
SlickEdits built-in additional tools are well integrated with the editor and, in some cases, are useful in their own right. In this chapter, we had a look at the file manager, which can be an effective way to manage and edit files. The file manager is also important because of its ability to automate tasks in the editor using Slick-C. We also looked at SlickEdits support for editing files on remote hosts using FTP and SSH. Finally, we had a quick intro to the regular expression evaluator, which you can use when developing and testing regular expressions for use in your macros. As in most of the chapters in this book, we provide some Slick-C code to illustrate how you can customize and extend SlickEdit in relation to the topics weve been discussing. By now you should have a good feel for what its like to work with Slick-C. In the next chapter, we finally get into Slick-C in detail, presenting the background and reference information that you can use to extend your Slick-C skills further.

306

Slick-C Macro Programming


Slick-C is the main tool you use to customize and extend SlickEdit. We have already seen a lot of Slick-C code in this book. Most of SlickEdits features are implemented in Slick-C. Slick-C source code is provided with SlickEdit, and you can use it as the basis for your own features. In this chapter, we take a look at various aspects of the Slick-C language in more detail. This chapter is not a complete reference for Slick-C. As well as reading this chapter, you should refer to the online Help for detailed reference information about Slick-C programming. The Slick-C Macro Programming Guide part of the online Help is also provided in PDF format in the SlickEdit installation. The installation includes another document Slick-C Macro Conventions and Best Practices for End Users which is also very useful. Finally, the SlickEdit Community Forums at http://community.slickedit.com have a section specifically for Slick-C macro programming. For really learning Slick-C and SlickEdit customization, nothing beats studying the supplied macro source code. If you are after extreme SlickEdit customization, you will want to become familiar with the supplied source code. If you want to understand how a feature works, or perhaps you think theres a bug in some feature, you can often find out by studying the source code for that feature. And, when you are trying to write some new function for your own needs, often the best way to see how to do things is to look for source code for features that do something similar. In this chapter, we illustrate the usage of Slick-C for typical tasks. We provide code snippets to show how to work with Slick-C features and useful library functions. To complete the chapter, we provide several examples of full-length macros for automating tasks within SlickEdit. For code snippets, Ive adopted a convention of using assertions to illustrate the behavior of Slick-C features and functions. As of version 12.0.2, SlickEdit provides an assertion facility via the built-in _assert() function. An assertion tests a condition and generates an informative stack trace if the condition fails. Assertions are useful in several aspects of programming, both in test code and live code. In this

Part III: Advanced SlickEdit


chapter, we will use the facility as a concise and informative way of presenting how Slick-C features work. For example:
int i1 = 0x80000000; int i2 = - i1; _assert(i1 < 0); _assert(i2 < 0); // anomaly of signed 32 bit integers!

For examples in this chapter, well use a few more functions to extend the basic _assert() for a few common cases:
void wrox_assert_false(boolean condition, _str msg = null) { _assert(!condition, msg); } void wrox_assert_equals_message(typeless expected, typeless actual, _str msg) { if (expected._varformat() == VF_LSTR && actual._varformat() == VF_LSTR) { _assert(expected :== actual, msg); // exact match for strings } else { _assert(expected == actual, msg); } } void wrox_assert_equals(typeless expected, typeless actual) { wrox_assert_equals_message(expected, actual, expected=[expected], actual=[actual]); }

The code snippets demonstrating Slick-C features this way are all contained in files with names beginning with wrox_try_ in the Author/Chapter16/ directory of the CD-ROM.

The Slick-C Language


Slick-C itself is a general-purpose language. Its basic features are similar to those found in many other conventional languages and scripting languages. The libraries are a little different from what you would find in a general-purpose language. The standard libraries in conventional languages are general-purpose. Slick-Cs libraries tend to be about editor features. For example, I/O is typically quite different in Slick-C macro programming from most other languages. To read a file in most programming languages, you have to call functions to open the file, read bytes or lines, and then close the file. With SlickEdit, you typically open the file in a buffer using _open_temp_view(), then work with the contents of the buffer. There are several other peculiarities of working with Slick-C, and well see some common Slick-C programming idioms in this chapter. Slick-C is named after C and looks kind of like C, but in many ways it isnt really like C at all. Even though Slick-C is compiled, it works more like a dynamic scripting language. Data structures in Slick-C are more dynamic than in typical compiled languages, and the runtime environment is richly dynamic also. The Slick-C Macro Programming Guide contains a section on the differences between Slick-C and C++.

308

Chapter 16: Slick-C Macro Programming


A great deal of SlickEdit is implemented in Slick-C. The engine itself, which includes the Slick-C interpreter, is implemented in native code (written mostly in C++). The interface between the Slick-C environment and the engine is via primitive functions and properties. Primitive functions are callable from Slick-C but are implemented in the engine. These functions are declared in the macro source file builtins.e. Properties are pseudovariables that provide an interface to attributes of the editor and are described in the section Properties, below. Figure 16-1 shows the architecture.

Slick-C Code (Supplied and User)

Slick-C Engine

Builtins

SlickEdit executable

Operating System

Figure 16-1

In this section, well take a quick tour of the features of Slick-C.

Modules and Names


When you compile a Slick-C file mymodule.e, the compiled module containing the generated code is created in a file mymodule.ex. You can unload a module using the unload command, which removes all the modules definitions from memory. If you want to know what modules youve loaded, check the contents of the def_macfiles macro variable. It contains a list of user-loaded modules. The name of a module is determined by the filename of the .e source file alone. The location is not significant. The SlickEdit hot fix system makes use of this fact by placing hot-fixed source files in your configuration directory, apart from the original product files. This makes it possible for you to switch between original and hot-fixed modules by loading files from either location as desired. Take care how you name your own modules. A couple of times while writing this book, I created modules with the same names as macro files provided with SlickEdit: html.e, util.e, and the like. If you load such a file, SlickEdit replaces all definitions it previously had loaded in the module of that name. This is a great way to trash your editor. For html.e, this removes or breaks a lot of HTML features. For util.e, it removes or breaks many basic routines, giving rise to random failures throughout SlickEdit. Be careful to name your modules uniquely. The best way to do this is to use a standard prefix that is unlikely to be used by SlickEdit itself. That is why every Slick-C source file accompanying this book begins with the prefix wrox_. You need to be careful with the names of your Slick-C commands and functions too. At the time of writing, Slick-C has no namespace facility. That means that all Slick-C definitions are global. If you define a routine with the same name as one provided by SlickEdit, you will replace its definition with yours, without warning. Again, the best convention is to use a prefix to ensure that your command and function names are unique. And similarly, that is why all the commands and functions provided in this book start with wrox_. Its awkward but safe.

309

Part III: Advanced SlickEdit


Proposed changes for Slick-C in SlickEdit 2008 include the concept of namespaces. Once namespaces are added to the language, supplied SlickEdit code will be either in no namespace or in a special SlickEdit namespace, and user code will be in a different namespace. This will remove the problem as far as functions and commands are concerned. The current plan for namespaces does not change the module system; thus you will still need to take care to name modules uniquely. Despite all this, it is certainly not convenient to have all your commands names begin with wrox_ or any other arbitrary prefix, particularly if you are typing them in. Not only are they unnecessarily long to type, but features such as auto-completion dont work as effectively when all the commands start with the same prefix. In the Example Macros section below in this chapter, well look at a macro you can use, at your discretion, to rename all the wrox_ commands in this book by removing the prefix.

Module Initialization
There are two special module initialization sections you can place into a Slick-C module, indicated by the keywords defload and definit. These sections look like this:
defload() { // code ... } definit() { // code ... }

The defload routine is run when the module has been compiled and loaded. It is not run again unless the module is compiled again. You can place one-time tasks in defload that need to be run when your module is set up. For example, if your module needs a special subdirectory to work, you can create it in defload. The definit routine is run when the module is compiled and loaded (before defload), and also whenever SlickEdit starts. You can place code in definit if it needs to be run every time the Slick-C environment is initialized. For example, you might place initialization for global variables in definit. If you have a choice, you should prefer to place code in defload rather than definit, because it will have less impact on the performance of the SlickEdit startup. You can distinguish between the load case and the init case in definit by calling the special function arg(), like this:
if (arg(1) == L ) { // load case }

Batch Macros
If you need to run some Slick-C code as a one-time job, rather than have it loaded as part of the editor environment for use all the time, you can run it as a Slick-C batch macro. A batch macro contains a block of code in a defmain section like this:
defmain() { // code ... }

310

Chapter 16: Slick-C Macro Programming


Batch macros are not loaded using the load command. They are not stored in the configuration state file, the way normal modules are. Instead, they are invoked explicitly and forgotten afterward. You can invoke a batch macro by entering its filename as a command on the command line (with or without the .e extension). You can specify an absolute or relative path when naming a batch macro to run. If you do not give a path, then you must have the file in a directory specified in the VSLICKPATH environment variable. You can also invoke a batch macro from macro code using the execute() function. We see applications of Slick-C batch macros in Chapter 17, where they are used for programmatic configuration.

Preprocessor
The Slick-C compiler includes a preprocessing step much the same as that for C. Most of the classic C preprocessor directives are supported, such as #include, #define, #if, #else, and #endif. To get the best error checking from the compiler, you should place these two lines at the top of every Slick-C file:
#pragma option(strict, on) #include slick.sh

The #pragma option(strict, on) line turns on several compile-time checks, such as variable declarations. It also enforces stricter syntax rules, making it less likely for your code to do something other than what you intend. Slick-C header or include files have the extension .sh. The standard slick.sh header file contains the most commonly used declarations, shared by most Slick-C code. Some supplied Slick-C macro files make use of additional header files, and, of course, you are free to create your own for your own macros. You can use the preprocessor to write conditional code the same way you would with C. For example, to make part of your macro code specific to UNIX, you can use:
#if __UNIX__ // UNIX code #else // non-UNIX code #endif

Similarly, you can use the __NT__ special macro to make code dependent on Windows.

Functions
Most of the code you write for SlickEdit is in the form of Slick-C functions. Slick-C functions are of several basic types: Commands are special functions that can be invoked from the command line or bound to keys or menu items. Commands are declared by preceding the function definition with the _command keyword. Ordinary functions cannot be invoked from the command line or bound to keys or menu

311

Part III: Advanced SlickEdit


or defined just as they are in C. An ordinary function can be declared static, which means that it is private to the current module. Built-in or primitive functions are implemented in the SlickEdit engine, not in Slick-C. They are declared in builtins.e, but only as prototypes. You cannot read the source or change their behavior.

We refer to ordinary functions simply as functions in this chapter. It is also possible to write functions in Windows DLLs that can be called from Slick-C. These functions are not covered in this book. The online Help contains reference information for many supplied macro functions. If the Slick-C declaration or definition has a JavaDoc comment preceding it, this documentation is extracted and included in the online Help. There is a master list at the end of the online Help contents called Macro Functions by Category. The @categories documentation tag indicates which function categories list a given function. For example, several functions are listed in the category String Functions. There are also many supplied Slick-C macro functions that dont have JavaDoc documentation. These macro functions do not appear in the online Help. In order to find out about these functions, you need to become familiar with the Slick-C source code.

Properties
Properties are special global pseudovariables. Like built-in functions, they are intrinsic to the Slick-C runtime environment and are declared in builtins.e. Properties are an important part of the interface between the Slick-C environment and the editor. Properties exist for a great many editor attributes. Reading a property accesses the value of the attribute. Writing a property updates the attribute, which may have various visible effects in the editor. For example, two very simple and useful properties are p_line and p_col, which reflect the cursor line and column in the current buffer. Macro code can read these properties, save their values in variables, and update them. If macro code changes the value of p_line or p_col, the cursor position in the buffer is updated accordingly. The following macro defines a command, wrox-goto-line-col, that can be used to navigate to a given line and column:
_command void wrox_goto_line_col(_str command = ) name_info(,) { if (command == ) { return; } _str line, col; parse command with line col; p_line = (int) line; p_col = (int) col; }

The command gets its job done simply by setting the properties p_line and p_col. You will find that a lot of Slick-C code works by reading and setting properties.

312

Chapter 16: Slick-C Macro Programming


Many properties are described in the online Help. They are also categorized from their documentation comments and can be found in the Macro Functions by Category page (Help Macro Functions by Category), along with functions. Some useful properties are shown in Table 16-1. Most of these properties apply to an editor control, but some properties apply specifically to other controls.

Table 16-1
Property
p_buf_id p_buf_name p_buf_size p_caps p_col p_DocumentName

Description Determines buffer displayed in current window. Determines buffer name. Returns number of bytes in buffer. Returns True if capitalization mode is on. Determines the character column position. Determines the document name. If not blank, the document name is displayed instead of the buffer name. It doesnt need to be a valid filename. Determines embedded language context mode. Determines embedded language lexer name. Determines the default encoding that the buffer will be saved in. Set to the encoding chosen if the user overrode automatic encoding processing. Determines extension file type support. When in hex mode, determines whether cursor is displayed in hex nibbles (True) or ASCII data (False). Determines whether text is displayed in hex or ASCII lines. (Use hex function to switch.) Buffer time stamp. Determines lexer name, which defines the language coloring elements for a buffer. Determines the current line number. Determines the mode name for the current buffer. continued

p_embedded p_EmbeddedLexerName p_encoding p_encoding_set_by_user

p_extension p_hex_field

p_hex_mode

p_LastModified p_lexer_name

p_line p_mode_name

313

Part III: Advanced SlickEdit


Table 16-1 (continued)
Property
p_modify p_newline p_Nofhidden p_Noflines p_sel_length p_sel_start p_UTF8 p_window_id

Description Determines whether the current buffer is modified. Returns the new line characters used for the current buffer. Returns the total number of hidden lines in the current buffer. Returns the number of lines in the current buffer. Determines the length of a selection in bytes. Determines the position of the left-most character of a selection. Determines whether the buffers data are UTF-8. Determines the current object/window.

Data Types
Slick-C provides a fairly typical set of data types, including basic types for numbers and strings, and data structures for dynamic arrays, hash tables, and user-defined structs. Slick-C also has a generic, or dynamic, typeless type.

Numbers
Slick-C supports three kinds of numbers:
ints are regular 32-bit signed integers. longs hold larger values, with precision up to 32 decimal digits. doubles are floating point numbers.

Most Slick-C programming uses integers. Note that all Slick-C numbers are signed. There is no unsigned modifier.
int i1 = 0x7fffffff; // 2^31 - 1 int i2 = i1 + 2; // - 2^31 + 1) int i3 = i1 + i2 - 1; // - 1 wrox_assert_equals(0x7FFFFFFF, dec2hex(i1)); wrox_assert_equals(2147483647, i1); wrox_assert_equals(-0x7FFFFFFF, dec2hex(i2)); wrox_assert_equals(-2147483647, i2); wrox_assert_equals(-1, i3);

314

Chapter 16: Slick-C Macro Programming


Long integers use a 32-bit representation up to 231 1. They preserve exact decimal accuracy up to 32 decimal digits and then switch to a floating-point representation beyond that:
long n1 = 99999999; n1 = n1 * 100000000 + 99999999; n1 = n1 * 100000000 + 99999999; n1 = n1 * 100000000 + 99999999; // 32 9s long n2 = n1 + 1; // 1 plus 32 0s long n3 = n2; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; n3 = n3 + 1; // 1 plus 30 0s plus 10? Nope, lost precision. wrox_assert_equals(n3, n2); wrox_assert_equals(0x4EE2D6D415B85ACEF80FFFFFFFF, dec2hex(n1)); wrox_assert_equals(99999999999999999999999999999999, n1); wrox_assert_equals(, dec2hex(n2)); wrox_assert_equals(1.0000000000000000000000000000000E+32, n2); wrox_assert_equals(, dec2hex(n3)); wrox_assert_equals(1.0000000000000000000000000000000E+32, n3);

Notice that once a long value gets bigger than 32 digits, it loses precision. For example, adding 1 to 1032 has no effect. This is unlikely to be a limitation for editor macros! Floating point numbers provide a large range of values:
double d1 = 9.9999999999999999999999999999999e999999999; double d2 = 0.1e-999999997; wrox_assert_equals(9.9999999999999999999999999999999E+999999999, d1/1.0); wrox_assert_equals(1.1E-999999998, d2*1.1);

Again, floating point numbers are not used in most editor macros.

Strings
Strings are represented in Slick-C using the built-in type _str. There is no such thing as a char in Slick-C. Elements of strings are also strings. You can get the length of a string using the length() built-in function:
wrox_assert_equals(13, length(Hello, World.));

Strings can be delimited with single quotes or double quotes. If you use double quotes, you need to use backslashes to escape double quotes and backslashes in the string. If you use single quotes, then

315

Part III: Advanced SlickEdit


backslashes are not used to escape characters in the string. To include a single quote within a string delimited by single quotes, use a repeated single quote.
wrox_assert_equals(\, ); // double quote in string wrox_assert_equals(, ); // single quote in string wrox_assert_equals(\\, \); // backslash in string

You can concatenate strings using the :+ operator. The + operator is restricted to numeric addition only, and cannot be used for concatenation. Most of the time the :+ operator is not necessary. You can simply abut strings as shown in the example below. It is often good practice to use the operator anyway, because it improves clarity.
wrox_assert_equals(Hello, World., Hello, World.); wrox_assert_equals(Hello, World., Hello, World.); _str a = Hello,; _str b = World.; wrox_assert_equals(Hello, World., a :+ b); wrox_assert_equals(Hello, World., a b); _str result = ; strappend(result, Hello, ); strappend(result, World.); // faster than result = result :+ ... wrox_assert_equals(Hello, World., result);

Another difference from C is that Slick-C strings are 1-indexed, rather than 0-indexed:
_str a = 0123456789ABCDEF; wrox_assert_equals(0, substr(a, 1, 1)); wrox_assert_equals(1, substr(a, 2, 1));

The strip() function strips unwanted leading and/or trailing characters from a string:
_str s = space string ; _str q = quoted string; wrox_assert_equals(space string, strip(s)); wrox_assert_equals(space string , strip(s, L)); // leading wrox_assert_equals( space string, strip(s, T)); // trailing wrox_assert_equals(quoted string, strip(q, B, )); // both, strip quotes

Here are some more examples of useful functions with strings:


wrox_assert_equals(65, _asc(A)); wrox_assert_equals(A, _chr(65)); wrox_assert_equals(TOM THUMB, upcase(tom thumb)); wrox_assert_equals(the giant, lowcase(THE GIANT)); wrox_assert(strieq(ABC, abc)); wrox_assert_equals(wrox-execute-current-command, translate(wrox_execute_current_command, -, _)); wrox_assert_equals(www.skepticalhumorist.co.nz, stranslate(http://www.skepticalhumorist.co.nz, , (http|ftp)://, U));

316

Chapter 16: Slick-C Macro Programming


There are several functions especially useful for working with filenames:
_str filename = C:\Documents and Settings\jhurst\trythis.c; wrox_assert_equals(C:\Documents and Settings\jhurst\trythis.c, filename); wrox_assert_equals(C:\Documents and Settings\jhurst\trythis.c, maybe_quote_filename(filename)); wrox_assert_equals(trythis.c, strip_filename(filename, P)); wrox_assert_equals(\Documents and Settings\jhurst\trythis.c, strip_filename(filename, D)); wrox_assert_equals(C:\Documents and Settings\jhurst\trythis, strip_filename(filename, E)); wrox_assert_equals(C:\Documents and Settings\jhurst\, strip_filename(filename, N)); wrox_assert_equals(c, get_extension(filename));

Despite the many string functions included with Slick-C, you will occasionally need to write your own. For example, there are no functions to extract the left-hand or right-hand part of a string. Here are some:
_str wrox_leftstr(_str string, int len, _str pad= ) { _str result = ; if (length(string) > len) { result = substr(string, 1, len); } else { result = string :+ translate(indent_string(len - length(string)), pad, ); } return result; } _str wrox_rightstr(_str string, int len, _str pad= ) { _str result = ; if (length(string) > len) { result = substr(string, length(string) - len + 1, len); } else { result = translate(indent_string(len - length(string)), pad, ) :+ string; } return result; }

And here are a couple of examples of using these functions:


wrox_assert_equals(http, wrox_leftstr(http://www.skepticalhumorist.co.nz, 4)); wrox_assert_equals(000123, wrox_rightstr(123, 6, 0));

317

Part III: Advanced SlickEdit


Parsing Strings
Slick-C uses a powerful and unusual construct for parsing strings, which it borrowed from the IBM mainframe scripting language REXX. If you have worked with scripting languages, you are probably used to using regular expressions for string parsing. Slick-C provides the parse with keywords for string parsing. Heres an example:
_str s = 2007-05-19; _str yyyy, mm, dd; parse s with yyyy-mm-dd; wrox_assert_equals(2007, yyyy); wrox_assert_equals(05, mm); wrox_assert_equals(19, dd);

The parse with construct uses a template or pattern to parse a string, placing matches or parts into variables. The parse with construct can be used for many situations in which you have to parse a string into parts according to a pattern. One of the most common cases is parsing command arguments. If you write a function that takes two string parameters, you would declare it like this:
void foo(_str a, _str b) { // ... }

However, this is not necessarily the best way to declare a command that takes two string parameters. When invoking functions, arguments are separated by commas. With commands, arguments are usually separated by spaces. Its friendlier to the user of a command if it is declared like this:
_command void wrox_try_parse_command(_str s=) name_info(,) { _str a, b; parse s with a b; // ... }

The user can invoke this command like this:


wrox-try-parse-command one two

If the arguments can contain spaces, you will need to do something more elaborate to parse them, because SlickEdit does not automatically parse quotation marks in command-line arguments. A common technique is to use parse with to extract repeated items from a string:
_str s = 1,2,3; _str head, rest; int i = 0; parse s with head,rest; while (head != ) { wrox_assert_equals(++i, head); parse rest with head,rest; } wrox_assert_equals(3, i);

318

Chapter 16: Slick-C Macro Programming


Although literal strings and output variables are the most common features used in parse with templates, several other features are supported. Table 16-2 shows the elements that can be contained in the template.

Table 16-2
Item
variable_name

Description Output variable. Null output variable (match ignored). New parse column. Parse column increment. Parse column decrement. String constant or pattern to search for. String expression to search for.

.
nnn +nnn -nnn text[,search_options] (expression)[,search_options]

The numeric offsets let you control the character positioning of parsing. The parenthesized expression feature allows you to use a variable in the template, including a variable that has been set earlier in the template. For example:
_str date1 = 2007/5/19; _str yyyy, mm, dd, delim; parse date1 with yyyy +4 delim +1 mm (delim) dd; wrox_assert_equals(2007, yyyy); wrox_assert_equals(5, mm); wrox_assert_equals(19, dd); _str date2 = 2008-12-01; parse date2 with yyyy +4 delim +1 mm (delim) dd; wrox_assert_equals(2008, yyyy); wrox_assert_equals(12, mm); wrox_assert_equals(1, dd);

The search options allow you to use regular expressions for parts of the template. The search options can be one or more of the characters in Table 16-3. Heres an example of parsing with a regular expression:
_str url = http://www.skepticalhumorist.co.nz/index.html; _str host; _str file; parse url with (http|ftp),U :// host / file; wrox_assert_equals(www.skepticalhumorist.co.nz, host); wrox_assert_equals(index.html, file);

319

Part III: Advanced SlickEdit


Table 16-3
Character
B I R U Y

Description Brief-style regular expression. Case-insensitive match. SlickEdit-style regular expression. UNIX-style regular expression. Binary value for DBCS searches (see online Help).

Using regular expressions with parse with is useful up to a point. But theres no way to use regular expressions in conjunction with storing a result in an output variable. Suppose you want to parse a date and ensure that its components are numeric. The example above does not check this and thus would parse 20XX/may/twentieth, for example, possibly giving a type conversion error later in the macro. The pos() function can be used for more complex parsing scenarios. The ordinary use of pos() is the familiar string function that returns the position of a substring in a search string:
wrox_assert_equals(6, pos(th, The other ones)); wrox_assert_equals(1, pos(th, The other ones, 1, I)); // case-insensitive wrox_assert_equals(6, pos(th, The other ones, 3, I)); // with start pos

The fourth argument to pos() is a set of options, which includes the options available for patterns in parse with. You can call pos() with a single argument to find the positions and lengths of matched subexpressions when using regular expressions. Call pos(S1) to get the start position of the first matched subexpression and pos(1) to get its length:
_str date = 2007-05-20; wrox_assert_equals(1, pos((\:d{4})([-/])(\:d{1,2})\2(\:d{1,2}), date, 1, U)); wrox_assert_equals(2007, substr(date, pos(S1), pos(1))); wrox_assert_equals(5, substr(date, pos(S3), pos(3))); wrox_assert_equals(20, substr(date, pos(S4), pos(4)));

A new utility function is planned for SlickEdit 2008 to simplify this idiom: get_match_substr(). As well as the pos() function, Slick-C also provides the lastpos() function, which has the same arguments but works backward from the end rather than forward from the start:
wrox_assert_equals(6, lastpos(th, The other ones, , I));

Arrays
Slick-C arrays look like C arrays, but, in fact, they are dynamic, which is much more convenient for a scripting language. Whenever you set an element of an array, Slick-C ensures that the array is long enough. For example, you can append items to an array like this:
_str a[]; a[a._length()] = one;

320

Chapter 16: Slick-C Macro Programming


a[a._length()] = two; a[a._length()] = three; a[a._length()] = four; wrox_assert_equals(4, a._length()); wrox_assert_equals(one, a[0]); wrox_assert_equals(two, a[1]); wrox_assert_equals(three, a[2]); wrox_assert_equals(four, a[3]);

Arrays have several built-in member functions defined for them, which are declared in builtins.e. For example, you can sort an array like this:
a._sort(); wrox_assert_equals(four, a[0]); wrox_assert_equals(one, a[1]); wrox_assert_equals(three, a[2]); wrox_assert_equals(two, a[3]);

There are several other functions that also take arrays as arguments. For example, there are the join() and split() functions, borrowed from Perl:
_str a[]; a[a._length()] = one; a[a._length()] = two; a[a._length()] = three; a[a._length()] = four; wrox_assert_equals(one,two,three,four, join(a, ,)); _str b[]; split(five,six,seven,eight, ,, b); wrox_assert_equals(five, b[0]); wrox_assert_equals(six, b[1]); wrox_assert_equals(seven, b[2]); wrox_assert_equals(eight, b[3]);

Note that Slick-Cs split() function only works with exact strings for splitting, not regular expressions.

Hash Tables
Hash tables are also known in other languages as dictionaries, maps, or associative arrays. They let you store keys and values. You can also use a hash table as a simple set by storing a dummy value against each key. The Slick-C syntax for declaring and accessing hash tables is similar to that for arrays:
_str h:[]; h:[first] = one; h:[second] = two; h:[third] = three; wrox_assert_equals(one, h:[first]); wrox_assert_equals(two, h:[second]); wrox_assert_equals(three, h:[third]);

321

Part III: Advanced SlickEdit


If you want to iterate over the elements in a hash table, the syntax is a little stranger, because you have to use a typeless iterator for the keys and use several built-in functions for the iteration:
typeless k; _str a[]; for (k._makeempty();;) { h._nextel(k); if (k._isempty()) { break; } a[a._length()] = k :+ : :+ h:[k]; } a._sort(); wrox_assert_equals(first:one, a[0]); wrox_assert_equals(second:two, a[1]); wrox_assert_equals(third:three, a[2]);

If youre like me, you probably find this idiom for iterating through items in a hash table a little weirdlooking. At the very least, its a little verbose. Future versions of Slick-C may provide a more natural way of iterating through hash tables. In fact, a foreach statement is tentatively planned for SlickEdit 2008. In the meantime, you can make things a little bit nicer for your own code by adding a function to return the keys as an array:
typeless wrox_hash_keys(typeless h:[], boolean sorted = true) { typeless k; typeless result[]; for (k._makeempty();;) { h._nextel(k); if (k._isempty()) { break; } result[result._length()] = k; } if (sorted) { result._sort(); } return result; }

Using this function, you can iterate through the items of a hash table by looping over its keys. The snippet below shows the function in action. Note that hash table keys are not sorted normally. (This is normal for hash data structures.) The convenience function wrox_hash_keys() sorts the result by default before returning it.
_str b[] = wrox_hash_keys(h); wrox_assert_equals(first, b[0]); wrox_assert_equals(second, b[1]); wrox_assert_equals(third, b[2]);

322

Chapter 16: Slick-C Macro Programming


Structs
Structs are familiar to C programmers, and a similar language feature is available in most other languages. Slick-C structs are much the same as in C.
struct NAMES { _str first_name; _str last_name; };

As with arrays and hash tables, you can declare and initialize structs globally:
NAMES name = { John, Hurst };

You can use structs to build up arbitrarily complex data structures:


struct NAMES_LIST { NAMES head; NAMES_LIST tail; };

However, be aware that in Slick-C, assignment is a deep copy (not a shallow reference copy such as in languages like Java). This example would therefore be a very inefficient way to implement a linked list, because adding an item would copy the whole list, unless the code is careful to traverse to the end of the list using pointers and then add the new item.

Typeless Container Variables


As seen with hash table iterators, Slick-C supports a typeless type. Variables declared as typeless can hold values from any type, including structs, arrays, and hash tables. If you need to, you can determine the actual type of value currently stored in a typeless variable using its _varformat() member function, declared in builtins.e. The function returns one of the VF_ constants defined in slick.sh.
_str wrox_typeless_type(typeless v) { switch (v._varformat()) { case VF_ARRAY: return ARRAY; case VF_EMPTY: return EMPTY; case VF_FREE: return FREE; // shouldnt happen! case VF_FUNPTR: return FUNPTR; case VF_HASHTAB: return HASHTAB; case VF_INT: return INT; case VF_LSTR: return LSTR; case VF_PTR: return PTR; default: return UNKNOWN; }

323

Part III: Advanced SlickEdit


} _str a[]; a[0] = one; a[1] = two; typeless e = null; _str h:[]; h:[one] = 1; h:[two] = 2; int i = 1; _str s = Hello; wrox_assert_equals(ARRAY, wrox_assert_equals(EMPTY, wrox_assert_equals(HASHTAB, wrox_assert_equals(INT, wrox_assert_equals(LSTR,

wrox_typeless_type(a)); wrox_typeless_type(e)); wrox_typeless_type(h)); wrox_typeless_type(i)); wrox_typeless_type(s));

The documentation for _varformat() warns that its behavior is likely to change in a future version of SlickEdit, thus you should be wary of using it. SlickEdit 2008 adds classes and changes the implementation of structs. In SlickEdit 2008, there is a new _varformat(), VF_OBJECT, which represents a struct or class instance.

Control Structures
Slick-C control structures are basically the same as in C, with a few minor enhancements because of the more dynamic nature of Slick-C. Whenever you create a block, it creates a new scope for local variables. This is the same as most modern C-style languages. This does allow you to re-use the same name for a new variable in a new scope:
int x = 1; { int x; x = 3; } wrox_assert_equals(1, x);

However, such usage is confusing and is not recommended. Its treated as a compilation error if you are using #pragma option(strict, on). The if() statement is straightforward:
int i = random(0, 10); if (i < 5) { wrox_assert(i < 5); } else { wrox_assert(i >= 5); }

324

Chapter 16: Slick-C Macro Programming


The for() statement is usually used for loops involving a known number of iterations:
int sum = 0; int i; for (i = 0; i < 10; i++) { sum += i; } wrox_assert_equals(45, sum);

Some people also like to use the for() loop for an unknown number of iterations:
for (;;) { // loop forever if (random(0, 10) < 1) { break; } }

The while() statement is more commonly used for loops with an unknown number of iterations, when the loop condition should be tested before executing the first iteration:
_str head, rest = 1,2,3; int i = 0; parse rest with head,rest; while (head != ) { wrox_assert_equals(++i, head); parse rest with head,rest; } wrox_assert_equals(3, i);

If the loop always should be executed at least once, the do() statement places the condition test at the end:
_str head, rest = 1,2,3; int i = 0; do { parse rest with head,rest; if (head != ) { wrox_assert_equals(++i, head); } } while (head != ); wrox_assert_equals(3, i);

Unlike most compiled languages, the Slick-C switch() statement can use strings as case targets, which is a great convenience:
_str month = May; int mm; switch (upcase(month)) { case JANUARY: mm = 1; break; case FEBRUARY: mm = 2; break; case MARCH: mm = 3; break;

325

Part III: Advanced SlickEdit


case APRIL: mm = 4; break; case MAY: mm = 5; break; case JUNE: mm = 6; break; case JULY: mm = 7; break; case AUGUST: mm = 8; break; case SEPTEMBER: mm = 9; break; case OCTOBER: mm = 10; break; case NOVEMBER: mm = 11; break; case DECEMBER: mm = 12; break; default: message(Unknown month: month); _StackDump(); } wrox_assert_equals(5, mm);

You should note that switch() using strings is really a syntactic convenience. The Slick-C compiler currently does not generate a jump table for switch statements.

Declarations and Definitions


A Slick-C module is made up of declarations and definitions. In this section, well cover how you declare some elements of Slick-C programs: Functions. Commands. Variables. Event Tables.

Functions
Weve already seen many examples of function definitions in this book. A definition includes the full function body. You can also write function declarations. A declaration includes the name, arguments, and return type of the function. Declarations are also known as prototypes and are commonly placed in header files. The purpose of declarations is to give the compiler more information about functions so that it can catch more errors at compile time. By default, Slick-C resolves function references at run time; thus it is legal to make use of any Slick-C function in code without declaring it. There is no check at compile time whether the function actually exists. While this is convenient and typical in dynamic languages, it does mean that you can accidentally mistype a function name and the compiler will not inform you of your error. Instead, the error will manifest itself at run time when Slick-C attempts to invoke the function. As of SlickEdit 12.0.2, you can enforce declaration checks using this #pragma at the top of your file:
#pragma option(strictprotos, on)

With this option, a prototype declaration or full definition is required before any use of a function.

326

Chapter 16: Slick-C Macro Programming


Because Slick-C does not support overloaded functions, you can define any given function name only once. This is not a limitation in practice because default arguments and variable arguments are supported; thus it is possible to simulate overloaded functions by treating arguments flexibly. Specify default arguments by assigning them in the function signature, like this:
_str wrox_leftstr(_str string, int len, _str pad= ) { // ... }

If you specify a default for any argument, all the arguments after that must also have default arguments. Specify variable arguments with in the function signature, like this:
void wrox_multimessage(_str m, ...) { _str messages = m; int i; for (i = 2; i < arg(); i++) { messages = messages \n arg(i); } _message_box(messages); }

When you use variable arguments, access them using the arg() function. Call the arg() function with no arguments to get the total number of arguments to the current routine. Call arg() with an argument number to retrieve that argument. Default arguments are a newer feature in Slick-C than variable arguments. In older code, you may find variable arguments being used when defaults would be more appropriate. For example, an alternative way to implement wrox_leftstr() using variable arguments is shown here:
_str wrox_leftstr(_str string, int len, ...) { _str pad = ; _str result = ; if (arg() >= 3) { pad = arg(3); } if (length(string) > len) { result = substr(string, 1, len); } else { result = string :+ translate(indent_string(len - length(string)), pad, ); } return result; }

In this case, the previous implementation using default arguments is clearer, and there is no need for variable arguments in defining wrox_leftstr(). Use variable arguments when you have a truly variable number of arguments, rather than simply optional arguments, which are better handled with default values.

327

Part III: Advanced SlickEdit


Commands
Commands can be bound to keys or run on the command line; ordinary functions cannot. Another difference between commands and ordinary functions is that the naming rules are relaxed for commands; thus they can include special characters not normally allowed in function names. This is how the names for some of the special SlickEdit commands work. For example, the find command is declared like this:
_command int find,l,/(argument list) { ...

Thus, L and the slash are valid alternative names for the command. The same feature applies in a similar way to the goto-line command (the shorthand is simply typing the desired line number as a command), and commands for moving up or down a given number of lines (the shorthands are - and +). However, this feature is not something you are likely to use in your own commands. The underscore character is commonly used in Slick-C identifiers. Commands containing underscores are displayed with the underscores changed to hyphens and can be entered that way too. Commands are defined the same way as functions, with some differences. Command definitions are preceded by the _command keyword, and they optionally have a name_info() expression after the argument list. The _command keyword simply indicates that the definition is a command. The optional name_info() expression specifies types of arguments accepted by the command, and the valid context for it. The name_info() expression is a string consisting of two parts, separated by a comma. The first part specifies the type of argument for the command, which is used on the command line to provide argument completion. It should be an _ARG value from slick.sh. Some of the most useful argument values are shown in Table 16-4.

Table 16-4
Argument Value
COMMAND_ARG BOOKMARK_ARG FILE_ARG DIR_ARG TAG_ARG

Description The command takes a SlickEdit command name as an argument. The command takes a bookmark name as an argument. The command takes a filename. The command takes a directory. The command takes a tagged procedure.

SlickEdit uses the argument information to provide completion for command arguments. For example, if you specify FILE_ARG for your command, SlickEdit can complete filenames on the command line for

328

Chapter 16: Slick-C Macro Programming


it. Append an asterisk (*) character to the argument parameter if the command can take one or more arguments. You can make your commands prompt for their arguments using the handy prompt() function defined in stdprocs.e. Suppose you have a command that takes a filename argument. Write the command like this:
_command void wrox_try_prompt_filename(_str filename=) name_info(FILE_ARG,) { filename = prompt(filename, Filename); // ... rest of command }

If the user types the command name, presses Space, and starts typing a filename, SlickEdits completion features help the user complete the filename. If the user types just the command name and presses Enter, SlickEdit prompts on the command line for the Filename parameter. Because of the name_info() specifying a file argument, prompt() supplies auto-completion for the filename. SlickEdit commands such as name and edit use this facility. If your command takes a command-name argument, you can write it like this:
_command void wrox_try_prompt_command(_str command=) name_info(COMMAND_ARG,) { command = prompt(command, Command); // ... rest of command }

This time prompt() auto-completes command names, because name_info() specifies a command argument. The second part of the name_info() expression specifies the valid context for the command and should be a combination of VSARG2_ values from slick.sh. Some of the common ones are shown in Table 16-5.

Table 16-5
Argument Value
VSARG2_CMDLINE VSARG2_EDITORCTL VSARG2_READ_ONLY VSARG2_REQUIRES_EDITORCTL VSARG2_REQUIRES_AB_SELECTION VSARG2_REQUIRES_SELECTION

Description The command is supported on the command line. The command is supported in an editor control. The command is allowed in read-only mode. The command requires an editor control. The command requires a selection in the active buffer. The command requires a selection.

329

Part III: Advanced SlickEdit


For example, consider the wrox-save-line-sel command given in Chapter 8. The purpose of the command is to save the given line selection as a pair of bookmarks. The definition has a name_info() expression specified like this:
_command void wrox_save_line_sel(_str bookmark = SELECTION) name_info(,VSARG2_REQUIRES_AB_SELECTION) { // ... }

The second part of the name_info() expression is VSARG2_REQUIRES_AB_SELECTION, which indicates that the command requires a selection in the active buffer. If you have a buffer open, but no selection, SlickEdit displays the message Command is disabled for this object. Only when the conditions are valid will SlickEdit execute the command. Both parts of the name_info() expression are optional, as is the whole expression. If you leave either part out, it simply means that SlickEdit is less able to provide help with the arguments and context of your command. This is often not a big deal for user-written macros, but it is certainly a good feature for many of the SlickEdit-provided commands. The VSARG2_ constants cover a variety of standard contexts for commands. For scenarios that arent covered by these standard contexts, you can write a callback function to determine whether a command is valid. The callback functions name should be the commands name prefixed by _OnUpdate_. For example, a callback for wrox-save-line-sel would be declared:
int _OnUpdate_wrox_save_line_sel() { // ... }

The callback should return MF_ENABLED if the command is allowed and MF_GRAYED if the command is not allowed. (These constants are declared in slick.sh.)

Global Variables
If you declare a variable outside any function, it is global and is shared across the entire Slick-C environment. If you want to share a global variable across multiple Slick-C modules, its best to declare it in a header file, then #include that header file in any module that needs to reference the global variable. You still need to define and initialize the global variable in a specific module. That module owns the global variable.

Static Variables
If you declare a variable outside a function but use the static keyword in the declaration, the variable is static but not global. A static variable is visible to any code in the module (i.e., the current .e file). If you declare a static variable with the same name in two different files, each has its own copy of the variable. Use static variables for global data within a module, and use global variables for global data that need to be shared across different modules.

Macro Variables
Macro variables refer to Slick-C variables containing configuration settings to control SlickEdit features. Most of the macro variables names start with def_.

330

Chapter 16: Slick-C Macro Programming


Technically, macro variables are just global Slick-C variables. Most of them are declared in slick.sh. Some commands work specifically with macro variables, by filtering on the def_ naming convention. For example, list-config lists the contents of macro variables but not other global variables.

Event Tables
Event tables are special declarations that are used primarily to bind commands to shortcut keys. There is a default event table, called default_keys. There is also an event table for each language mode, such as c_keys, java_keys, and xml_keys. Definitions for specific modes override the defaults in default_keys. There are also event tables for certain special modes in the editor, shown in Table 16-6.

Table 16-6
Event Table Name
argument_completion_keys auto_complete_keys fileman_keys grep_keys process_keys

Description Argument completion. When Auto-Complete active. File Manager. Search Results tool window. Process Buffer.

To specify key bindings for an event table, first specify the desired event table using defeventtab. Then define key bindings using def:
defeventtab html_keys; def A-/= wrox_insert_html_ending_tag;

You should always specify an event table using defeventtab, but if you dont, the default is default_keys. We cover programmatic key binding with event tables more in Chapter 17. More information on event tables can also be found in the Slick-C Macro Programming Guide.

Wor king with Macros


The above sections have covered some of the elements of the Slick-C language and common routines. In this section, we take a look at techniques for working with macros themselves: the mechanics of executing them, terminating them, and debugging them. You should find some of this information useful when you are developing or debugging your own macro code.

331

Part III: Advanced SlickEdit

Executing Slick-C Code


When you are developing macro code, you will want to run it frequently. The normal way to run some Slick-C code is to invoke a command. You can obviously test your macros by running them on the command line or by binding commands to keys. If you have several different commands and functions, it may not be feasible to set up key bindings for them all, but command retrieval on the command line is often an effective way to test macro code repeatedly. If you have a set of lines in the buffer, containing SlickEdit commands, you can execute them by selecting them and invoking execute-selection (Alt+equals). Its not exactly a graphical debugger, but its pretty handy for quick macro development. If you are working on a command and wish to execute it, the execute-selection command is not the fastest way. You need to have the command name by itself on a line in the buffer to use execute-selection, and this is not usually the case. (For one thing, if you put it in the same .e file as the command youre working on, the file becomes invalid to compile.) Instead, you can try this macro:
_command void wrox_execute_current_command() name_info(,VSARG2_REQUIRES_EDITORCTL|VSARG2_READ_ONLY) { execute(current_proc()); message(Command [current_proc()] executed successfully.); }

If you bind this command to a key, you can execute the Slick-C command you are editing at any time. For example, I have it bound to Alt+Shift+equals, which is easy to remember because it is similar to Alt+equals (the default binding for execute-selection). This works well for commands that have no arguments.

Terminating a Macro
If your macro goes into an endless loop or is running for too long for any other reason, you can halt it by pressing the macro break key combination: Ctrl+Alt+Shift+F2. For some reason, I found this key combination really hard to remember for years. You might want to write it down somewhere just in case, because if you need it, you really need it.

Writing Messages
A fundamental technique for debugging in all programming languages is outputting debug messages from your code. Slick-C provides several built-in ways to display debug messages. You can display a message in the message area of the editor using the message() function:
message(Hello, World.);

This function can be used in debugging but is also commonly used for ordinary status messages. Be aware that as soon as another routine calls message(), the previous message will be replaced. Therefore, message() is not suitable for complex debugging with a lot of messages. It can be quite handy for simple debugging though.

332

Chapter 16: Slick-C Macro Programming


The messageNwait() function is a variation that pauses after displaying the message and waits for the user to press a key:
messageNwait(Hello, World. Press a key to continue.)

This function is very useful for debugging because it causes a refresh so that you can see where the cursor is and what changes have been made to the file at each point where you call messageNwait(). If you want to display a message more dramatically, you can use _message_box() instead. This pops up a message box with the given message. The user must dismiss the message box by clicking OK before the calling macro continues.
_message_box(Hello, World.);

These functions for displaying a message are occasionally useful for debugging but are also quite valid for normal use in macros. Finally, there is the say() function, which really is just for debugging:
say(Hello, World.);

This function also takes its name from the REXX equivalent. The say() function outputs its messages to the vsapi.dll output window on Windows, as shown in Figure 16-2. On UNIX, it writes to stdout, and on Mac OS X, output is written to a console log, for example, /Library/Logs/Console/501/ console.log.

Figure 16-2

If you see the vsapi.dll window appear while using SlickEdit and you havent put any debug code into macro files yourself, it usually means youve hit some debug code of the SlickEdit team. There are plenty of references to say() in the supplied sources, but most of them are intended to be invoked only in debugging scenarios.

Stack Traces
Consider the command wrox-makestacktrace, shown below. The command calls the wrox_ stacktrace1() function, and this function calls the wrox_stacktrace2() function. The wrox_stacktrace2() function contains an illegal expression, where it attempts to add 1 to a null value. This results in SlickEdit aborting the function and displaying a stack trace.
_command void wrox_makestacktrace() name_info(,) { wrox_stacktrace1(); } void wrox_stacktrace1() { wrox_stacktrace2();

333

Part III: Advanced SlickEdit


} void wrox_stacktrace2() { _str a = arg(1) + 1; }

SlickEdit displays the stack trace in the Slick-C Stack tool window, shown in Figure 16-3.

Figure 16-3

You can programmatically update the Slick-C Stack tool window by calling _UpdateSlickCStack() in your code. You can dump the stack to the console debug output (vsapi.dll, stdout, etc.) at any time by calling _StackDump(). Finally, if you get a stack dump due to an error, the stack dump is also written to a log file (vs.log in your configuration directory). You can navigate to any frame of the stack trace in the Slick-C Stack tool window by moving the cursor to the line and pressing Enter, or by double-clicking. If you note the offset reported in the stack trace, you can also navigate to it directly in the module using the st command with the f option. For example, in Figure 16-3, the first stack frame is in wrox_stacktrace.ex at offset 67. To navigate to the corresponding source line, you can open wrox_stacktrace.e and invoke this command:
st -f 67

Usually the cause of a stack trace is pretty clear from the source code combined with the error message.

Finding Slick-C Objects


If you need to find a particular Slick-C command or function, use the find-proc command (shorthand fp). The command opens the module in which the function is defined and navigates to the definition. You can use this command at any time you dont have to be working in a Slick-C file or workspace. The Slick-C environment stores all global objects in a single name table. The name table holds the names of all functions, commands, variables, and other objects. In macro code, you can find out about objects in the Slick-C global namespace using the find_index() function. For example, you can test whether a command with a given name exists like this:
if (find_index(command, COMMAND_TYPE)) { message(Command command exists.); }

334

Chapter 16: Slick-C Macro Programming


else { message(Command command does not exist.); }

You can find objects matching a given name prefix using the name_match() function. The function takes a prefix for the names you want to match, a flag to indicate first match or next match, and flags to indicate the kinds of objects you are interested in. It returns an index into the global names table, or 0 if nothing is found. You can then use the name_name() and name_type() functions to find out about the symbol given its index. For example, you can use this function to obtain an array of name indexes of objects matching given criteria:
typedef int INTARRAY[]; INTARRAY wrox_find_matching_name_indexes(_str prefix, int name_type_flags) { int result[]; int index = name_match(prefix, 1, name_type_flags); while (index) { result[result._length()] = index; index = name_match(prefix, 0, name_type_flags); } return result; }

This snippet illustrates the usage of the function:


int indexes[]; indexes = wrox_find_matching_name_indexes(cursor_, COMMAND_TYPE|PROC_TYPE); wrox_assert_equals(7, indexes._length()); wrox_assert_equals(cursor-down, name_name(indexes[0])); wrox_assert_equals(cursor-up, name_name(indexes[1])); wrox_assert_equals(cursor-left, name_name(indexes[2])); wrox_assert_equals(cursor-right, name_name(indexes[3])); wrox_assert_equals(cursor-error2, name_name(indexes[4])); wrox_assert_equals(cursor-error, name_name(indexes[5])); wrox_assert_equals(cursor-shape, name_name(indexes[6]));

The names table holds information about objects other than commands and functions. For example, it holds all the global variables too. You can query the value of an integer or string global variable with a given name like this:
int index = find_index(varname, VAR_TYPE); if (!index) { message(Variable varname not found.); return; } if (index) { typeless value = _get_var(index); message(varname=[value]); // integer or string only! }

335

Part III: Advanced SlickEdit


The types of objects you can query in the names table are defined in slick.sh and shown in Table 16-7.

Table 16-7
Type
PROC_TYPE VAR_TYPE EVENTTAB_TYPE COMMAND_TYPE MODULE_TYPE PICTURE_TYPE BUFFER_TYPE OBJECT_TYPE MISC_TYPE IGNORECASE_TYPE

Description Matches global function. Matches global variable. Matches event table. Matches command. Matches module. Matches picture. Matches buffer. Matches object. Matches miscellaneous. Matches case-insensitive search.

You can use the name_match() function with these types to find out more about objects in the Slick-C environment. For example, you can list all loaded modules using this command:
_command void wrox_try_list_modules() name_info(,) { int index = name_match(, 1, MODULE_TYPE); while (index) { insert_line(name_name(index)); index = name_match(, 0, MODULE_TYPE); } }

The commands output includes all modules: user-defined and SlickEdit-supplied. If you want to know the names of all the modules you have loaded, you can get them from the macro variable def_macfiles. This contains a space-delimited list of filenames of all .ex files loaded by the user.

Useful Techniques
The previous section concerned techniques for working with macros themselves: various ways of executing and debugging them. Now we turn our attention to how you can actually put macros to use to perform useful tasks in SlickEdit. In this section, we cover several common techniques for using macros to do things in the editor.

336

Chapter 16: Slick-C Macro Programming

Interacting with the Buffer


One of the most fundamental things you need to do in a Slick-C macro is interact with the buffer. Obviously, all the commands weve looked at elsewhere in the book and in this chapter are accessible to any Slick-C macro. There is no shortage of ways for a macro to move around the buffer and to move and copy text. Sometimes a macro needs to be able to examine the text in the buffer, and macros often need to be able to enter text themselves. A macro can read text from the buffer using the primitive function get_text().The get_text() function returns a chunk of text from the buffer. It takes two arguments: a character count and a seek position, both of which are optional:
get_text(10, 8); // gets 10 characters from position 8 get_text(10); // gets 10 characters from the cursor position get_text(); // gets the character at the cursor position

The default value for the seek position is a special negative value, which causes the function to use the current cursor position. The default value for the character count is 1. Thus, get_text() with no arguments returns the character at the current cursor position. The get_text() function is particularly useful when combined with search(), as explained below. A macro can also retrieve the current line from the buffer using the get_line() function. The function retrieves the line into the variable given as an argument:
_str the_line; get_line(the_line); // retrieves current line into var

To insert text, a macro can use the _insert_text() function:


_insert_text(;); // inserts a semicolon at the cursor position

Alternatively, macros can insert whole lines using the insert_line() function:
insert_line(end;); // adds line after current line

A macro can also delete text from the buffer using the _delete_text() function:
_delete_text(10); _delete_text(-1); _delete_text(-2); // deletes 10 characters // deletes to end of line // deletes to end of buffer

You can also delete the entire current line with _delete_line(). There is also a delete_line() command (no leading underscore), but this is not usually appropriate for general macro use because it is hooked into the auto-unsurround feature.

Searching
Its frequently useful in a macro to search for text in the buffer. You can invoke the find command, which is the same as the slash (/) command on the command line. However, this command is intended for interactive use and is not generally used internally by macro code. If you invoke find in your macro, it

337

Part III: Advanced SlickEdit


may have unintended side effects. For example, find changes the search performed by find-next, and it can change the selection too. Usually, a macro shouldnt affect these features unless that is its specific purpose. Instead, you can invoke the lower-level search() function from macro code, which is not available directly as a command. Invoking search() in your macro code is less disruptive to the users environment because it doesnt affect the same settings that find does. In fact, you can study the implementation of find: It uses search() internally. The search() function is built in and is not implemented in Slick-C. The search() function returns a status that indicates the success of the search. A status of 0 indicates a successful search; other statuses indicate that nothing was found or that there was a problem with the search criteria. To write a macro that does something for each match, follow this pattern in your code:
int status = search(string, options); while (!status) { // do something at the search match status = repeat_search(); }

Many of the same options you would use with find on the command line are also useful with search() in macro code, such as + and to search forward and backward, m to search in the selection, and so forth. A couple of options you should consider using with search() specifically in macro code are h and @. The h option causes search() to find text in hidden lines as well as visible lines. This can make your macros more robust, in case selective display happens to be active when the macro is running. The @ option prevents search() from displaying an error message if nothing is found. If you are testing the result of search() in your macro code, you can decide in the macro whether it is an error if nothing is found. Usually it is not an error, but just another possible scenario for the macro to deal with. If your search uses a regular expression with tagged subexpressions, you can extract the text matching the subexpressions from the editor using get_text() with match_length(), as shown in this example:
int status = search(created date.*(\\:d{4}-\\:d{1,2}-\\:d{1,2}), UI); if (!status) { message(Created date = get_text(match_length(1), match_length(S1))); }

This example code searches for the text created date, followed by a date in ISO format (yyyy-mm-dd). If a match is found, the macro shows the date in the message area. The U option indicates that the search is for a UNIX-style regular expression, and the I option makes it case-insensitive. The macro extracts the date from the editor using the get_text() function. The match_length() function returns character counts and seek positions suitable for get_text(). When match_length() is called with a string representing a tagged subexpression group number, for example, 1, it returns the length of the match on that subexpression. When match_length() is called with an S followed by a group number, it returns the seek position for the match on that subexpression. Thus get_ text(match_length(1), match_length(S1)) means the text in the buffer matched by the first tagged subexpression. Similarly, you can use 2 and S2 for the second subexpression, and so forth. If you specify 0 and S0, you get the entire matched text.

338

Chapter 16: Slick-C Macro Programming


There is a convenient utility function, get_match_text(), which is a shorthand for get_text() with match_length():
message(Created date = get_match_text(1));

You can use save_search() and restore_search() to save and restore the current search data. This allows you to write functions that use search but do not disturb existing searches, so that you can nest one search in another search. Here is an example from the save_search() documentation:
search(test); save_search(string, options, word_re); status = search(xyz); if (status) { messageNwait(Cant find xyz); } restore_search(string, options, word_re); // Repeats search for test repeat_search();

Selections
Macros can allocate and use multiple selections, activating them as required. Several primitive functions exist for managing selections. They are well documented in the online Help, under the category Selection Functions. To get the selection type of the active selection, use the _select_type() function with no arguments. The result is BLOCK, CHAR, or LINE according to the selection type, or a null string if no selection is active. To iterate over a line selection, use the filter_init(), filter_get_string(), and filter_restore_pos() functions like this:
filter_init(); for (;;) { _str line; int status = filter_get_string(line); // fetch next line into variable if (status) { break; // status is non-zero when no more lines } // do something with the line } filter_restore_pos();

Temporary Buffers
A common requirement in more elaborate macros is to have a scratch pad buffer to place results while the macro is working. Well see one application of this in the next section, where we find out how to work with lists of files and directories. The situation arises often in the supplied macro source code, and SlickEdit supplies some functions specifically for creating and managing temporary buffers.

339

Part III: Advanced SlickEdit


One advantage of using a special temporary buffer rather than simply opening a new empty file is that the temporary buffer is not displayed while your macro is running. This snippet illustrates the use of the _create_temp_view(), _delete_temp_view(), and activate_window() functions to work with a temporary buffer:
int temp_view_id; int orig_view_id = _create_temp_view(temp_view_id); // do something with the temporary buffer ... _delete_temp_view(temp_view_id); activate_window(orig_view_id);

You can open an existing file in a temporary buffer with _open_temp_view(). The advantage of this in a macro, rather than opening the file normally using edit(), is that the buffer is hidden. This lets you open a file, do something, and close it, without the user seeing the activity on screen.

Listing Files and Directories


Weve already mentioned that I/O in Slick-C is different from that in most programming languages. Rather than opening a file, reading its contents in some kind of loop, and then closing it, you simply load the file into a buffer and work on it in the buffer. Listing files and directories is similar. Rather than using special I/O functions to iterate through lists of files and directories, SlickEdit provides the built-in function insert_file_list(), which simply inserts names and attributes of files and directories into the buffer. You can then work with the list in the buffer as required. The insert_file_list() function takes a single string argument, which contains the filespec for files to insert, but also can contain several additional options. Most of the options are single letters preceded by + or -, to turn on or off certain features. These are documented in the online Help, and the more common ones are also shown in Table 16-8. In addition, the string argument can include -exclude with a list of file patterns to exclude.

Table 16-8
Option
H

Description Includes hidden files (Windows only). Default is ON in Windows if Explorer is set to show all files. Includes system files. Default is ON in Windows if Explorer is set to show all files. Includes archive files. Default is OFF. Includes directories. Default is OFF. Appends path to filenames. Default is OFF.

S A D P

340

Chapter 16: Slick-C Macro Programming


Table 16-8 (continued)
Option
T U V

Description Recursive: includes files in subdirectories. Default is OFF. Includes UNIX dot files. Default is ON. Verbose output with size, date, attributes. Default is ON.

By default, files are listed with their sizes, dates, and attributes, as with the DOS dir command. You can omit the extra information and list the file names only with V. For example, to list macro source files into the buffer, including their paths but excluding other attributes, you could use this code:
_str macro_filespec = maybe_quote_filename(get_env(VSLICKMACROS) :+ *.e); insert_file_list( +P -V -D macro_filespec);

Often when dealing with lists of files and directories, the desired end result is not to see them listed in a buffer but to actually do something with them. The following simple function lists files and returns them in an array, rather than leaving them in a buffer. This makes it a little more natural for calling macro code to iterate through the list of files. The function takes a single argument, almost identical to that for insert_file_list().
STRARRAY wrox_list_files(_str command) { int filelist_view_id; int orig_view_id = _create_temp_view(filelist_view_id); _str result[]; insert_file_list(-V command); top(); up(); while (!down()) { _str filename; get_line(filename); filename = strip(filename); if (filename == ) { break; } result[result._length()] = maybe_quote_filename(filename); } _delete_temp_view(filelist_view_id); activate_window(orig_view_id); return result; }

This function uses a couple of the techniques weve looked at. First, it creates a temporary buffer. Then it lists files into the temporary buffer using the supplied criteria. Notice that it adds V to the criteria, to limit the output to filenames only, suppressing other attributes. This function is not intended to list other attributes.

341

Part III: Advanced SlickEdit


The main part of the function iterates through each line in the temporary buffer, adding the contents of the line to the result array. Before an item is added to the result array, the function calls maybe_quote_ filename() on it to ensure that it is quoted if it contains spaces. This is one reason the macro wouldnt work with additional data such as size, date, and attributes. They would be surrounded by quotes, which would not be appropriate. If you need a version of wrox_list_files() that includes size, date, and attributes, you can expand on this function, possibly using a struct to store the results.

Choosing Files
When you want to allow the user to choose one or more files for your macro to process, you can present a customized File Open dialog using the Slick-C _OpenDialog() function. The function takes several arguments, documented in the online Help. Heres an example:
_command void wrox_try_open_dialog() name_info(,) { _str files = _OpenDialog( -modal _open_form, // form and mode Choose files to list, // title *.e;*.sh, // initial exts All Files (*.*),C/C++ Files (*.c;*.cpp;*.h),Slick-C Files (*.e;*.sh), OFN_ALLOWMULTISELECT|OFN_FILEMUSTEXIST, // flags , // default ext , // initial filename // initial directory ); while (files != ) { _str file; parse files with file files; insert_line(file); } }

This command shows some of the options to _OpenDialog() in action. It prompts the user to select one or more files, and then lists their names in the buffer. By using different arguments, you can specify defaults and limit the types of files to be selected. You can also specify a callback that the _OpenDialog() function will call before presenting a list, so that you can screen the files being offered to the user. There are many examples of _OpenDialog() in the supplied macro source.

Useful Macro Files


Most of the supplied macro source deals with specific SlickEdit functionality. When you are interested in a particular feature, it is usually not hard to find the source file(s) containing code pertaining to that feature. For example, CVS-related code is unsurprisingly located in cvs.e, cvsquery.e, and cvsutil.e. The commands and functions supporting the Ruby language are in ruby.e. There are several files that contain useful global declarations or general-purpose functions. Weve already discussed most of these files and many of their declarations in this chapter. You may find it useful to peruse some of these files in more detail, for example, to discover additional code not described in this book. Table 16-9 lists some of the most useful general-purpose macro files in the supplied source.

342

Chapter 16: Slick-C Macro Programming


Table 16-9
File
builtins.e

Description Built-in functions and properties. Includes operations for arrays and hashes, some basic window and menu functions, global properties, and low-level (primitive) functions. All of these functions and properties are implemented natively. The builtins.e file only declares them: There is no Slick-C implementation. Declares many macro variables, provides default values. Defines many standard commands, e.g., undo, redo, nosplit-insert-line, begin-line, top-of-buffer. Defines many standard functions, e.g., abs(), strip_filename(), maybe_quote_filename(), path_exists(), _create_temp_view(), _delete_temp_view(). Defines more standard commands, e.g., scroll-up, scroll-down, center-line, sort-on-selection, asc, chr, execute-selection, goto-line, select-mode, block-insert-mode. Quite useful for seeing how these work.

main.e stdcmds.e

stdprocs.e

util.e

Callbacks
Callbacks are Slick-C functions you write that SlickEdit will call whenever certain events occur. For example, you can have a callback that is invoked whenever a project is opened. You create callbacks by writing Slick-C functions following a certain naming convention. Callback functions are named _event_name(), where: _event_ is the name of the callback event, and
name is a name you give to the function to make it unique and to indicate its purpose.

Callback event names start with an underscore, and almost always end with one too. For example, here is a callback function from Chapter 5, which pops all bookmarks whenever a workspace is closed:
void _wkspace_close_popallbkms() { pop_all_bookmarks(); }

The event name for this callback is _wkspace_close_, and what the callback does is indicated by the popallbkms part of the function name. The _wkspace_close_ callback takes no arguments. Some callbacks can be provided with arguments giving more information about the event. For example, there is a _buffer_renamed_ event that occurs when a buffer is renamed. Callbacks for _buffer_renamed_ are provided with four arguments: Buffer ID. Old name.

343

Part III: Advanced SlickEdit


New name. Flags.

You can write a callback to be called whenever a buffer is renamed, using this signature:
void _buffer_renamed_wrox_example(buf_id, old_name, new_name, buf_flags) { // your code here ... }

Table 16-10 shows some of the callback events available in SlickEdit 12.0.2, with a description for each and a list of the arguments provided to the callback. A more complete listing is in Appendix C.

Table 16-10
Name
_actapp_

Event Application activated (such as getting focus). New buffer opened.

Arguments Whether getting focus.

_buffer_add_

Buffer ID, buffer name, buffer flags. Buffer ID, buffer name, new name, buffer flags. Buffer ID, buffer name, filename, buffer flags. Buffer ID, buffer name, filename, buffer flags. (none) (none) New directory. (none) (none) Buffer ID, old name, new name, buffer flags. Key binding table, key. (none) (none)

_buffer_renamed_

Buffer renamed.

_cbquit_

About to quit file.

_cbquit2_

After quit file.

_cbsave_ _cbstop_process_ _cd_ _diffOnExit_ _diffOnStart_ _document_renamed_

File saved. Stopping build. Directory changed. End of DIFFzilla operation. Start of DIFFzilla operation. Document name changed.

_eventtab_modify_ _gotfocus_ _lostfocus_

Key bound. Received focus. Lost focus.

344

Chapter 16: Slick-C Macro Programming


Table 16-10 (continued)
Name
_onexit__ _postbuild_ _prebuild_

Event Exit. Build completed. Build about to start.

Arguments (none) Build arguments. Build arg 1 (see source in compile.e).

_prjclose_

Closing project (but fired only if not saving state during auto restore see source in wkspace.e). Active configuration changed. Project properties edited. Opening project. Project saved. Closing project. File added to project. Switching buffer.

(none)

_prjconfig_ _prjedit_ _prjopen_ _prjupdate_ _project_close_ _project_file_add_ _switchbuf_

(none) (none) (none) (none) Project name. Project name, filename. Old buffer name, option, old pos, old buffer ID. (none) Project name, filename. (none)

_wkspace_close_ _workspace_file_add_ _workspace_opened_

Closing workspace. File added to workspace. Opening workspace.

SlickEdit looks up and invokes callbacks using the call_list() function defined in files.e in the supplied macro source. By examining references to call_list(), you can find all the places in SlickEdit where callbacks are invoked, what they are called, and what arguments are supplied. For example, when you use the name command to rename a buffer, eventually during the execution of this command, the name_file2() function is called, defined in files.e. The name_file2() function looks like this:
int name_file2(_str new_name) { call_list(_buffer_renamed_,p_buf_id,p_buf_name,new_name,p_buf_flags); p_buf_name= new_name; docname(); return(0); }

345

Part III: Advanced SlickEdit


The function does three things: It calls all callbacks whose names start with _buffer_renamed, passing the buffer ID, the old buffer name, the new buffer name, and the buffer flags. It changes the buffer name (p_buf_name) to the new name. It resets the document name by calling docname(). (The document name is used when the display name of a buffer is not a valid filename, e.g., for http:// files.)

If you want to understand the context and parameters of a particular callback better, you need to study the Slick-C code invoking the callback. You can search for a callback identifier from Table 16-10 using Find in Files, or you can search references to the call_list() function to find all places where callback events are dispatched. One interesting way to study the behavior of callbacks is to set up tracing for them. For example, if you load this code, it will output a message to the vsapi.dll window whenever the _switch_buffer event occurs:
void _switchbuf__trace() { say(_switchbuf_ called); }

You can generate similar trace code for other events. In the Example Macros section below, we give a macro that can generate trace calls like this for all callbacks defined in SlickEdit.

Example Macros
This chapter has contained a small amount of definitions and theory about Slick-C, but most of the focus has been on practical use of Slick-C for macro programming. In this section, we give several examples of more elaborate macros. These examples put the techniques together to make complete applications. As with the rest of this book, these examples are supposed to be practical and useful. (Well, most of them.) But the main point of them is to show how you can customize and extend SlickEdit for your own needs. In years of using SlickEdit, Ive written many macros specifically for work I was doing at the time. In some jobs, Ive worked with obscure scripting file formats with no tool support. I wrote SlickEdit macros to provide the support I needed. In another job, I worked for a client whose C++ coding style standard was, I believe, unique in the world. I created SlickEdit macros to beautify my code into his style. Any time you find yourself doing repetitive editing, consider whether it can be automated with Slick-C. You will often find that writing a Slick-C macro takes less time than editing the tedious way. Its more fun, too. And, as with everything, the more you do of it, the faster and better you become. SlickEdit is the kind of tool that really rewards long-time use and investment. As with other source code presented in this book, the full source for these examples is on the accompanying CD-ROM, under /Author/Chapter16. Updates and bug fixes are also available online.

346

Chapter 16: Slick-C Macro Programming

Example: Counting Duplicate Lines


SlickEdit has a nice command for removing adjacent duplicate lines in a selection: remove-duplicates. Occasionally, as well as removing the duplicates you need to know how many there were. The macro command below removes duplicates and appends the counts for each line to the end of the line:
_command void wrox_count_duplicates(_str ignore_case = ) name_info(,VSARG2_REQUIRES_EDITORCTL|VSARG2_REQUIRES_AB_SELECTION) { if (_select_type() :!= LINE) { message( Command needs a line mark ); return; } ignore_case = upcase(ignore_case) == I; // initialize variables int entry = 0; _str key[]; int data[]; key[entry] = ; data[entry] = 0; int max_keylen = 0; int max_datalen = 0; // go through marked lines filter_init(); for (;;) { _str line; int status = filter_get_string(line); if (status) { break; } boolean matched = ignore_case ? strieq(key[entry], line) : key[entry] :== line; if (matched) { // duplicate: increment count data[entry]++; if (length(data[entry]) > max_datalen) { max_datalen++; } } else { // new entry: add to table, start count at 1 if (data[entry] > 0) { entry++; } key[entry] = line; if (length(line) > max_keylen) { max_keylen = length(line); } data[entry] = 1; } }

347

Part III: Advanced SlickEdit


filter_restore_pos(); // delete the selection delete_selection(); cursor_up(); // insert the aggregate (formatted neatly) int i; for (i = 0; i < key._length(); i++) { insert_line(wrox_left(key[i], max_keylen) :+ :+ wrox_rightstr(data[i], max_datalen)); } }

This macro uses the filter_selection() functions to iterate through the selection. It stores the lines themselves in the key[] array and the counts in the data[] array. When outputting the revised lines, it uses the wrox_leftstr() and wrox_rightstr() functions from above in this chapter to pad the results. Another nice feature is that if there are no duplicate lines, then the macro adds no counts it effectively leaves the data unchanged. Suppose you run this command with a selection containing these data:
one two two three three three ten ten ten ten ten ten ten ten ten ten

The result looks like this:


one 1 two 2 three 3 ten 10

Like SlickEdits remove-duplicates command, this command takes an optional string parameter which, if I, causes the macro to compare lines case-insensitively.

Example: Inserting HTML End Tag


SlickEdit has considerable HTML and XML support these days, and more is added with every release. For example, when you type a start tag such as <ul> or <li>, SlickEdit automatically adds the end tag, usually in the correct place and indented to your preferences. However, for whatever reason, I still find

348

Chapter 16: Slick-C Macro Programming


that I often delete the end tags inserted by SlickEdit, then need to type them in again, perhaps in a different location. Some IDEs and other products automatically insert closing tags when you type the </ of a closing tag, but SlickEdit doesnt do that (yet). Therefore, I have a macro I wrote some time ago thats still useful:
static int wrox_optional_hmtl_tags:[] = { base => 1, basefont => 1, bgsound => 1, br => 1, frame => 1, hr => 1, img => 1, input => 1, isindex => 1, link => 1, meta => 1, nextid => 1, param => 1, plaintext=> 1, spacer => 1, wbr => 1 }; _command void wrox_insert_html_ending_tag() name_info(,MACRO_ARG2|MARK_ARG2) { _str tagexp = <(/?(\:c|[0-9]|-|_|:)+)([^>]*)>; int nesting = 0; int status = 0; int start_line = p_line; int start_col = p_col; push_bookmark(); status = search(tagexp, U<-); // search backwards for HTML/XML tag if (!status && p_line == start_line && p_col == start_col) { // search didnt move us status = repeat_search(); // doesnt count, search again } _str nesting_stack[]; _str tag; while (!status) { tag = get_text(match_length(1), match_length(S1)); _str endchar = get_text(match_length(3), match_length(S3)); if (wrox_leftstr(tag, 1) == /) { // end tag nesting_stack[nesting++] = wrox_rightstr(tag, length(tag) - 1); // add it to nesting stack } else if (wrox_rightstr(endchar, 1) == /) { // self-contained tag like <tag/> // ignore } else { // start tag if (wrox_optional_hmtl_tags:[lowcase(tag)] == 1) { // end-tag is optional if (nesting > 0 && tag == nesting_stack[nesting - 1]) { // matched start: pop it nesting--; }

349

Part III: Advanced SlickEdit


} else { // otherwise end-tag not optional if (nesting == 0) { // a start tag with zero nesting; were done break; } else { if (tag == nesting_stack[nesting - 1]) { // matched nested end-tag nesting--; } else { // unmatched message(Found unmatched tag < :+ tag :+ >); return; } } } } status = repeat_search(); } // end while if (status) { message(Couldnt find a tag.); return; } int tag_line = p_line; int tag_col = p_col; pop_bookmark(); _str line; get_line(line); line = strip(line); if (p_line != tag_line) { // match is on different line from cursor: insert_line(); // add a new line for end tag p_col = tag_col; } _insert_text(</ :+ tag :+ >); // insert the end tag }

The macro tries to insert the appropriate closing tag at the current location. It searches backward for opening and closing tags, keeping a stack of tags it has found. When it encounters a closing tag, it pushes it on the stack. When it encounters an opening tag, it pops the stack and matches it with the top of the stack. If it finds an unexpected opening tag, it reports an error. When it encounters an opening tag and theres nothing left to pop, thats the tag that needs to be ended. The macro inserts a closing tag in the buffer. If the start tag is on the same line as the cursor position, the macro inserts the closing tag at the cursor position. Otherwise, it adds a new line and inserts the ending tag indented to the same level as the start tag. XML rules are very strict: In XML, all opening tags must be matched with closing tags. HTML, particularly older HTML, is more lax. Some tags are often specified as opening tags with no closing tags. Common examples of tags like this are <br> and <img>. The macro has special processing to be tolerant of these tags if they are not closed. Suppose you start with a file like this:
<html> <head> <title>Title</title>

350

Chapter 16: Slick-C Macro Programming


</head> <body> <p>Paragraph.</p> <p>Paragraph. <img src=xxx>xxx <table > <tr> <td> <ul> <li>one

If your cursor is after the one on the last line and you invoke wrox-insert-html-ending-tag eight times, the macro will fill in the ending tags, indented correctly, like this:
<html> <head> <title>Title</title> </head> <body> <p>Paragraph.</p> <p>Paragraph. <img src=xxx>xxx <table > <tr> <td> <ul> <li>one</li> </ul> </td> </tr> </table> </p> </body> </html>

To be effective, this macro should be bound to a key. I usually have it bound to Alt+slash, in HTML and XML modes.

Example: Moving Lines Up and Down


I often find that I want to change the order of lines in the buffer. The usual way to do this is to use copy and paste, or perhaps to mark a line selection and move it. These methods are a little awkward for reordering a lot of lines. The macros below can be used to move lines up or down conveniently in the buffer. If there is a character or line selection, the macros move the selection; otherwise, they move the current line. For a character selection, the macros first convert it to a line selection, using the wrox-to-lineselection command:
_command void wrox_to_line_selection() name_info(,) { push_bookmark(); begin_select(); push_bookmark();

351

Part III: Advanced SlickEdit


end_select(); if (p_col == 1) { cursor_up(); } select_line(); pop_bookmark(); select_line(); pop_bookmark(); }

The move commands themselves are given below:


_command void wrox_move_line_up(_str commandline=1) name_info(,) { int n = (int) commandline; int i; int orig_col = p_col; if (_select_type() == CHAR) { message(selection changed); wrox_to_line_selection(); } if (_select_type() == LINE) { begin_select(); cursor_up(n + 1); move_to_cursor(); } else { _str line; get_line(line); _delete_line(); cursor_up(n + 1); insert_line(line); } p_col = orig_col; // restore column position } _command void wrox_move_line_down(_str commandline=1) { int n = (int) commandline; int i; int orig_col = p_col; if (_select_type() == CHAR) { message(selection changed); wrox_to_line_selection(); } if (_select_type() == LINE) { end_select(); cursor_down(n); move_to_cursor(); } else { _str line; get_line(line); _delete_line(); cursor_down(n - 1); insert_line(line);

352

Chapter 16: Slick-C Macro Programming


} p_col = orig_col; } // restore column position

The commands work very similarly. First they test to see if there is a character selection. If there is, they convert it to a line selection. Then there are two cases, one for a line selection and the other to work with the current line. In each case, there is logic to move the cursor to the appropriate new location and move the line(s) there. The commands each take an optional number argument, which can be used to say how far to move the lines. The default is to move only one line up or down. You can bind the commands to keys for convenient use. The keys Alt+Up and Alt+Down are bound to prev-paragraph and next-paragraph in the CUA emulation. If you prefer, you can use those keys for wrox-move-line-up and wrox-move-line-down:
defeventtab default_keys; def A-Up=wrox_move_line_up; def A-Down=wrox_move_line_down;

Alternatively, select some key combinations that are not already used.

Example: Callback Traces


The code in this example requires code in wrox_list_files.e and wrox_hashes.e to be loaded. Above in the chapter, we covered SlickEdit callbacks and showed how you could add trace callbacks to understand when callbacks are called. The trace callbacks followed a simple pattern:
void _switchbuf__trace() { say(_switchbuf_ called); }

You can use a SlickEdit macro to generate this code for all SlickEdit macros by scanning the supplied macro source for callback invocations. First, define a function wrox_list_callbacks() like this:
#define CALL_LIST_PATTERN call_list\(([])(\:v)\1 STRARRAY wrox_list_callbacks() { _str macro_filespec = maybe_quote_filename(get_env(VSLICKMACROS)*.e); // NOTE: on Mac OS X VSLICKMACROS may not include a trailing slash ... (!) _str files[] = wrox_list_files(+P -D macro_filespec); int i; _str callbacks:[]; for (i = 0; i < files._length(); i++) { _str filename = files[i]; int temp_view_id; int orig_view_id = _create_temp_view(temp_view_id); get(filename); // loads file contents into temp buffer top(); int status = search(CALL_LIST_PATTERN, U@>); while (!status) { _str callback = get_text(match_length(2), match_length(S2));

353

Part III: Advanced SlickEdit


callbacks:[callback] = 1; status = search(CALL_LIST_PATTERN, U@>); } _delete_temp_view(temp_view_id); activate_window(orig_view_id); } return wrox_hash_keys(callbacks); }

The function first lists all macro source files into an array, using the wrox_list_files() function from above in this chapter. Then, it loads a copy of each macro source file into a temporary buffer created by the _create_temp_view() function. The real work is in the loop, which uses a simple regular expression to search for each invocation of call_list(). For each invocation, the function adds the prefix pattern [the first argument to call_list()] to the set stored in the callbacks hash table. After the loop, the function returns the keys of the callbacks hash table. The result of the function is an array with all the callback event names. With this function in place, you can proceed to define a couple of commands to generate the trace functions:
_command void wrox_make_callback_trace(_str callback=) name_info(,VSARG2_REQUIRES_EDITORCTL) { insert_line(void callback_trace() {); insert_line( say(\callback called\);); insert_line(}); insert_line(); } _command void wrox_foreach_callback(_str command=) name_info(COMMAND_ARG,VSARG2_REQUIRES_EDITORCTL) { command = prompt(command, Command); _str callbacks[] = wrox_list_callbacks(); int i; for (i = 0; i < callbacks._length(); i++) { execute(command callbacks[i]); } }

To generate macro source for callback trace functions using this code:

1. 2.

Open a new empty buffer. Invoke this command on the command line:

wrox-foreach-callback wrox-make-callback-trace

The wrox-foreach-callback command obtains the list of callbacks using the wrox_list_callbacks() function, then invokes the given command for each callback event. The wrox-make-callback-trace command prints out a simple trace function like that shown above for each callback event. You can easily modify the wrox-make-callback-trace command to customize the trace function generated. For example, you could have the trace function print the arguments passed to the callback. The ideas in this set of macros can be easily extended to very specific searches and edits over your own code base. This can be a great way to automate some large sets of simple changes.

354

Chapter 16: Slick-C Macro Programming

Example: WROX Function Names


The code in this example requires code in wrox_list_files.e to be loaded. Throughout this book, all the example macros have been contained in files with names beginning with
wrox_. The command and function names themselves (and even the global variables) also begin with wrox_. This has been done to ensure that there is no clash with supplied Slick-C macro names. As

explained above, if you inadvertently load a macro file named the same as an existing Slick-C module, or containing definitions with the same name as existing commands or functions, you can alter SlickEdit functionality in ways you did not intend. However, it is not particularly convenient to have a large number of commands beginning with wrox_. The advantage is that you know where the commands came from (and whom to blame if they dont work). The disadvantages are that the commands are unnecessarily long to type, and auto-complete is not as effective. If you decide to incorporate some or all of the commands presented in this book into your own installation of SlickEdit, you may wish to consider dropping the wrox_ prefix, in order to make the commands easier to use. Of course, you wouldnt want to have to edit all the source files by hand to do this. Also, you need to be careful that none of the shortened command names actually do conflict with supplied SlickEdit definitions. The macro in this section can automate this conversion task:
#define WROX_FUNCTION_NAME wrox_(\:v)\( #define WROX_DEF def (.*)= *wrox_(\:v); #define WROX_TYPES (PROC_TYPE | VAR_TYPE | COMMAND_TYPE) _command void wrox_convert_wrox_names(_str path = ) name_info(DIR_ARG,VSARG2_REQUIRES_EDITORCTL) { path = prompt(path, Path to WROX source files); push_bookmark(); insert_line(#include slick.sh); _str macro_filespec = path/*.e; _str files[] = wrox_list_files(+P +T -D macro_filespec); int i; int file_count = 0; for (i = 0; i < files._length(); i++) { _str filename = files[i]; if (pos(wrox_try, filename) > 0) { continue; // skip wrox_try files: theyre for testing/demo purposes only } int temp_view_id; int orig_view_id = _create_temp_view(temp_view_id); get(filename); // loads file contents into temp buffer top(); if (!search(defmain)) { // skip Slick-C batch macro files pop_bookmark(); _delete_temp_view(temp_view_id); continue; } file_count++; int status = search(WROX_FUNCTION_NAME, U@>); while (!status) {

355

Part III: Advanced SlickEdit


_str short_name = get_text(match_length(1), match_length(S1)); if (find_index(short_name, WROX_TYPES)) { // check whether short name already in use message(short_name (filename) already exists!); pop_bookmark(); return; } status = search(WROX_FUNCTION_NAME, U@>); } // if we get here all names in the file are OK top(); deselect(); search(#include ); // skip down to first #include line search($[ \t]*^, U>); // skip down to following blank line select_line(); // start mark here bottom(); select_line(); // mark to rest of file activate_window(orig_view_id); bottom(); push_bookmark(); copy_to_cursor(); // copy/append data into this file deselect(); replace(WROX_FUNCTION_NAME, \1(, U*>); // remove wrox_ from function names pop_bookmark(); replace(WROX_DEF, def \1=\2;, U*>); // remove wrox_ from keyboard defs insert_line(); _delete_temp_view(temp_view_id); } pop_bookmark(); message(Files processed: file_count); }

The command takes a directory argument. It searches for .e files under that directory using the wrox_list_files() function. It skips any file containing a defmain(). These are Slick-C batch macros and are not to be converted. For each of the remaining files, it first checks that it is OK to remove the wrox_ prefix from all of the commands and functions having the prefix. Its OK to remove the prefix only if no command or function already exists with the shortened name: We dont want to redefine any pre-existing commands or functions. If any name clash is found, the macro aborts with a message about the name clash. If there are no name clashes, the macro appends the definitions from the source file into the current buffer. It then uses replace() to change the command and function names in definitions, invocations, and key bindings. Once the macro is complete, the current buffer should have all the WROX command and function definitions and key bindings from the selected directory. You should be able to load the file and have all the commands available with shorter names. Be careful about doing this. At the time of writing, all of the wrox_ commands and functions do not clash with SlickEdit commands and functions. However, in any new release or update, SlickEdit may add or rename commands or functions, creating a clash. The approach outlined here is inherently risky because the checks for name clashes occur only when you generate the new macro source file, not when you load it. If you want to be safe, you should retain some kind of namespace convention to avoid clashes.

356

Chapter 16: Slick-C Macro Programming

Example: N-Queens
The final example is not practical, but I couldnt resist throwing it in. Now you can solve the N-queens problem right in your editor. Simply load the code below (from the CD-ROM), open an empty buffer, type wrox-queens n, and press Enter. Dont try this with n too big, or you will need Ctrl+Alt+Shift+F2! I did it with n up to 22. In case you are curious about the performance of Slick-C, it turns out that it runs just a little slower than Perl, which is among the fastest of the dynamic scripting languages.
static static static static int q_pos[]; boolean q_col[]; boolean q_diag1[]; boolean q_diag2[];

void wrox_queens_init(int size) { q_pos._makeempty(); q_col._makeempty(); q_diag1._makeempty(); q_diag2._makeempty(); int i; for (i = 0; i < size; i++) { q_pos[i] = -1; q_col[i] = false; } for (i = 0; i < 2 * size + 1; i++) { q_diag1[i] = false; q_diag2[i] = false; } } int wrox_queens_size() { return q_pos._length(); } int wrox_queens_col(int row) { return q_pos[row]; } void wrox_queens_place(int row, int col) { q_pos[row] = col; q_col[col] = true; int size = wrox_queens_size(); q_diag1[col - row + size] = true; q_diag2[col + row] = true; } int wrox_queens_unplace(int row) { int col = q_pos[row]; q_pos[row] = -1; q_col[col] = false; int size = wrox_queens_size(); q_diag1[col - row + size] = false; q_diag2[col + row] = false; return col;

357

Part III: Advanced SlickEdit


} boolean wrox_queens_ok(int row, int col) { int size = wrox_queens_size(); return !(q_col[col] || q_diag1[col - row + size] || q_diag2[col + row]); } boolean wrox_queens_solve() { int row = 0; int col = 0; int size = wrox_queens_size(); while (row >= 0 && row < size) { while (col < size && !wrox_queens_ok(row, col)) { col++; } if (col < size) { wrox_queens_place(row, col); row++; col = 0; } else { row--; if (row >= 0) { col = wrox_queens_unplace(row) + 1; } } } return row == size; } void wrox_queens_print() { int size = wrox_queens_size(); int i; for (i = 0; i < size; i++) { insert_line(wrox_rightstr(*, wrox_queens_col(i) + 1)); } } _command void wrox_queens(int size=4) name_info(,VSARG2_REQUIRES_EDITORCTL) { wrox_queens_init(size); int start_time = (int) _time(B); if (wrox_queens_solve()) { int end_time = (int) _time(B); wrox_queens_print(); int elapsed_seconds = (end_time - start_time) / 1000; message(Board size size solved, took elapsed_seconds seconds.); } else { message(Board size size not solved.); } }

358

Chapter 16: Slick-C Macro Programming

Summar y
This chapter was long, and could have been a lot longer. There are several features we havent mentioned. For example, Slick-C has C-style pointers, but they arent covered in this book. I find that they are not necessary for most user macros. We also dont cover GUI programming with Slick-C. We look at it briefly in the next chapter, but not in great detail. In my experience, users of SlickEdit use Slick-C to get a job done and are not generally too interested in spending time on a fancy interface. On the other hand, the SlickEdit team does use pointers, and GUI programming, in creating SlickEdit features. You can find out anything you need to know about SlickEdit by reading the supplied macro source. The supplied macro source contains about 750,000 lines of code, and many people write to the Community Forums to ask how it all works. Of course, there is no way to distill the entire 750,000 lines into an easy guide. There is a lot to say about Slick-C. The main aim of this chapter has been to give you an introduction to some of its most useful features, some of the common ways to get things done, and get you started writing your own macros. I hope this chapter has provided enough material to give you a useful start. I encourage you to read the supplied source to learn more. (Just dont try to read it all at once.) Join the Community Forums too. Ask questions. Share your macros and ideas.

359

Customization
Throughout this book, a major theme has been to show you many ways in which you can customize and extend SlickEdit for your own needs and preferences. In the previous chapter, we went into detail about Slick-C, which is the main power tool for customization in SlickEdit. In this chapter, we continue the theme of customization. Well look at how you can fine-tune the behavior of common keyboard commands by creating your own wrapper versions for them. This is easy to do and provides an effective way in many cases of getting the editor to behave just the way you want it to. SlickEdit supports a large number of programming languages out of the box, but new languages seem to appear just about every day. There are programming languages not supported by SlickEdit, from the ancient and obscure to some of the latest cutting-edge open-source languages. Well see how you can get a certain amount of support for these languages nevertheless, using SlickEdits features for defining new modes and lexers. In the previous chapter, we looked at several ways to use Slick-C to automate tasks in the editor and to create new features of your own. You may be surprised to learn that the capabilities of Slick-C are not limited to traditional programming, but also cover GUI programming. You can customize most of SlickEdits user interface, that is, forms and menus, using GUI tools provided in the editor. You can also create your own GUI elements for use with SlickEdit using these tools, or directly in code. Well take a look at a couple of relatively simple but useful examples of editing forms and working with menus. Finally, to be a truly expert user of SlickEdit, you need to be able to take control of your configuration. That means controlling it in code, so that your configuration settings are intentional and repeatable. All SlickEdit configuration settings can be accessed and controlled from Slick-C. Well cover several examples and show how you can determine the Slick-C code required for specific configuration changes you want to make.

Part III: Advanced SlickEdit

Keyboard Customization
Sometimes the standard behavior of SlickEdit keys is not what you want. Most of the time, various behaviors are available, such as those for Enter, Delete, and other keys, as discussed in Chapter 2. Occasionally, you may find you want completely different behavior from what SlickEdit provides. In this case, you can write your own macros and replace the SlickEdit commands bound to the keys. We saw an example of this in Chapter 6, where we replaced SlickEdits prev-word and next-word commands with wrox-prev-whitespace-word and wrox-next-whitespace-word, bound to Ctrl+Left and Ctrl+Right. Other times, the behavior for a key may be almost what you want, but not quite. In these cases, you can study the supplied source for the command bound to the key, to see whether configuration options are available. If you dont find a suitable configuration option, you may opt to write your own version of the command. A good approach to this can be to write a wrapper command that delegates to the original command but provides additional behavior.

Example: Page-Down
For example, you may have noticed that when you press Page-Down and reach the bottom of the file, you can sometimes end up with only a few lines of the buffer on screen, the bottom line of the buffer being partway up the window. In this situation, you might like Page-Down to realign the buffer in the window so that the bottom line of the buffer is at the bottom of the window. Realizing that the line-to-bottom command effectively does this very realignment, you might write a replacement page-down command:
_command void wrox_page_down_realign() name_info(,VSARG2_REQUIRES_EDITORCTL|VSARG2_READ_ONLY) { if (p_line != p_Noflines) { page_down(); } else { line_to_bottom(); } }

You can bind this command to Page-Down by including these lines in the macro file when you load it:
defeventtab default_keys; def PGDN=wrox_page_down_realign;

This will get the command working in ordinary buffers. Recall from Chapter 13 that some modes of SlickEdit require special attention for user-defined commands on standard keys. Because Page-Down is a commonly used key in DIFFzilla, you will need to modify diffedit.e as explained in that chapter, to include wrox-page-down-realign as a supported command.

Example: Joining Lines


The WROX emulation binds the useful command join-line to Alt+J. The join-line command has special handling for comments, to remove delimiters so that they flow correctly after joining lines. For ordinary lines, the behavior is simpler. It removes any leading spaces from the line below and joins it to

362

Chapter 17: Customization


the current line. If the cursor is at or beyond the end of the current line, the line is joined at the cursor position. Otherwise, it is joined at the end of the current line. I find I often use join-line with data or text files, and in this case when I join lines, I need to make sure the contents of the two lines are still separated by white space. To do this with the original join-line, I need to move the cursor to one character after the end of the first line before invoking join-line. Needless to say, this is inconvenient. A better solution is to write a wrapper for join-line:
_command void wrox_join_line_with_space() name_info(,VSARG2_REQUIRES_EDITORCTL) { push_bookmark(); int orig_col = p_col; end_line(); if (p_col > orig_col) { cursor_right(); } else { p_col = orig_col; } join_line(); pop_bookmark(); }

You can bind this command to Alt+J by including these lines in the macro file when it is loaded:
defeventtab default_keys; def A-J=wrox_join_line_with_space;

Example: Tabbing Behavior


In this example, well change the behavior of Tab and Shift+Tab. The normal behavior of the Tab key in SlickEdit depends on the file type, the position of the cursor, and user extension settings. Generally, when editing code, if the cursor is in the beginning part of the line (before the first non-whitespace), the Tab key indents the line according to syntax rules. When the cursor is not in the leading whitespace, or for files that are not source code, the Tab key adds space or tabs up to the next tab stop. Rather than following arbitrary tab stops, I find a more useful behavior for the Tab (and Shift+Tab) keys is to follow the positions of items in the line above. That is, the Tab key moves the cursor under the next non-whitespace character on the line above, and the Shift+Tab key moves the cursor under the character after the previous whitespace character on the line above. This works well for typing data into columns, or even code where you have some items, for example, array initializations, lined up in columns. Another example is when you have line comments starting in the same column on several adjacent lines. Having Tab and Back-Tab configured to follow the fields above makes it very quick to jump to the correct column for the next line comment. The example macros below show how to achieve this. These macros are not intended for text files using real tab characters. For such files, the relationship between column positions on one line and another is complicated and depends on tab settings.
_command void wrox_tab_matchtabs() { if (p_line < 2) { // no line above ctab();

363

Part III: Advanced SlickEdit


return; } cursor_up(); _str line_above; get_line(line_above); cursor_down(); _str remainder_above = strip(substr(line_above, p_col), T); if (length(remainder_above) <= 1) { // no more non-whitespace above ctab(); return; } int first_space = pos([ \t], remainder_above, 1, U); // Unix regexp if (first_space == 0) { // no more spaces; skip to end first_space = length(remainder_above); } int first_nonspace = pos([^ \t], remainder_above, first_space, U); p_col += first_nonspace - 1; } _command void wrox_backtab_matchtabs() { if (p_line < 2) { // no line above cbacktab(); return; } cursor_up(); _str line_above; get_line(line_above); cursor_down(); _str remainder_above = substr(line_above, 1, p_col - 1); if (length(strip(remainder_above)) <= 1) { // no more non-whitespace above cbacktab(); return; } int last_nonspace = lastpos([^ \t], remainder_above, p_col, U); // Unix regexp if (last_nonspace == 0) { // all spaces; normal backtab cbacktab(); return; } int last_space = lastpos([ \t], remainder_above, last_nonspace, U); p_col = last_space + 1; }

You can bind these commands to Tab and Shift+Tab by including these lines in the macro file when you load it:
defeventtab default_keys; def TAB= wrox_tab_matchtabs; def S-TAB= wrox_backtab_matchtabs;

For many programming languages, SlickEdits default binding for the tab key is the smarttab command. The smarttab command indents the current line if the cursor is in the white space at the beginning (and the line needs to be indented); otherwise, it calls the root event table behavior for the Tab key. These

364

Chapter 17: Customization


macros are compatible with this behavior. Youll get the indenting behavior if it applies; otherwise, youll get the tab-matching behavior of these macros. The wrox_tab_matchtabs and wrox_backtab_matchtabs commands are inspired by the matchtabs setting in the EPM editor, another descendent of the E line that SlickEdit came from. This is reflected in their names. By the way, all this customization of the Tab and Shift+Tab keys might leave you wondering how you type in a tab character. When file formats require tab characters, you have to enter them. Makefiles are a classic example. However, SlickEdit handles Makefiles specially via its Makefile mode, thus when you type Tab on a blank line or after a make target, you get a tab character. To force a tab character in other files, you can use quote-key (Ctrl+Q) followed by the Tab key. Im of the school of thought that believes you shouldnt put tab characters into source code because they cause more harm than good. Different editing tools treat tabs differently, and using tabs can make it hard to share files across tools. Spaces are universal and unambiguous. Because tools such as SlickEdit indent automatically, there is no extra typing overhead to using spaces. Obviously, if you think differently, you can configure SlickEdit to use tab characters its up to you.

Custom Language Suppor t


SlickEdit supports a large number of languages out of the box. As of SlickEdit 12, there are about 70 modes and 80 lexers defined. You can easily add color syntax highlighting and some other features for languages not supported with the base product.

Example: Portable Game Notation Files


Lets start with a simple example. Portable Game Notation (PGN) is a file format used to represent chess games. Its used for storing games and loading them into chess programs. An example of a file in PGN format is shown here:
[Event F/S Return Match] [Site Belgrade, Serbia JUG] [Date 1992.11.04] [Round 29] [White Fischer, Robert J.] [Black Spassky, Boris V.] [Result 1/2-1/2] 1.e4 e5 2.Nf3 Nc6 3.Bb5 {This opening is called Ruy Lopez.} a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 d6 8.c3 O-O 9. h3 Nb8 10.d4 Nbd7 11.c4 c6 12.cxb5 axb5 13.Nc3 Bb7 14.Bg5 b4 15.Nb1 h6 16.Bh4 c5 17.dxe5 Nxe4 18.Bxe7 Qxe7 19.exd6 Qf6 20.Nbd2 Nxd6 21.Nc4 Nxc4 22.Bxc4 Nb6 23.Ne5 Rae8 24.Bxf7+ Rxf7 25.Nxf7 Rxe1+ 26.Qxe1 Kxf7 27.Qe3 Qg5 28.Qxg5 hxg5 29.b3 Ke6 30.a3 Kd6 31.axb4 cxb4 32.Ra5 Nd5 33. f3 Bc8 34.Kf2 Bf5 35.Ra7 g6 36.Ra6+ Kc5 37.Ke1 Nf4 38.g3 Nxh3 39.Kd2 Kb5 40.Rd6 Kc5 41.Ra6 Nf2 42.g4 Bd3 43.Re6 1/2-1/2

You can find out more about this format at http://en.wikipedia.org/wiki/Portable_ game_notation.

365

Part III: Advanced SlickEdit


The file begins with specific tag pairs, giving keyword/value information about the game. Examples of tags are Event, Site, and Date. The game itself is specified as movetext, which consists of move number indicators and moves in algebraic notation. Semicolons mark the remainder of a line as a comment. Braces can also be used to mark comments, which can run to multiple lines, but cannot be nested.

Color Syntax Highlighting


We can get SlickEdit to display some of the elements of PGN files using color syntax highlighting. Well create a mode for PGN files, and an associated lexer. Follow these steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.

Invoke setupext (Tools Options File Extension Setup) to open the Extension Options dialog. SlickEdit displays the dialog. Click New to create a new extension. SlickEdit displays the New Extension dialog. Enter pgn for the Extension. Leave Refer to blank. You can use this when you add additional extensions sharing the mode of an existing one, such as the way .h files use C mode. Click OK. SlickEdit closes the New Extension dialog and creates the new mode. Click the Advanced tab. Click Color Coding. SlickEdit prompts you to confirm whether you want to start a new lexer for this extension. Click Yes. SlickEdit displays the Enter New Lexer Name dialog. Enter Portable Game Notation for the New Lexer Name. Click OK. SlickEdit displays the Color Coding Setup dialog. Click the Tokens tab. Click the Keywords category. Click the New button next to the token list. SlickEdit displays the Enter New Keywords dialog. Enter the words Event, Site, Date, Round, White, Black, and Result, separated by spaces. Click OK. SlickEdit adds the seven tokens as keywords in the PGN language. Click the Strings tab. Click the checkbox for \ represents a double quote. SlickEdit does not color code strings unless something is checked on this tab. Click the Comments tab. Click New Line comment. Enter ; for Use delimiter. Click New Multi-line comment.

366

Chapter 17: Customization


22. 23. 24. 25.
Enter { for the Start delimiter. Enter } for the End delimiter. Click OK. SlickEdit closes the Color Coding Setup dialog and creates the lexer. Click OK. SlickEdit closes the Extension Options dialog.

Note that when adding tokens, you can add as many as you want at once, separated by spaces. This is great for pasting in a list of keywords. If you have a keyword that contains a space character, you can enter it in double quotes. When you open a .pgn file now, there should be some degree of syntax highlighting. The comment color coding in particular is a powerful visual cue, even for a simple file format like this one. You can use a similar technique to create color syntax highlighting support for file formats you encounter. For example, you may have particular data file formats specific to your work. By adding color syntax highlighting, you can often make these files easier to read.

Example: Groovy Language


Lets do an example with a real programming language. The Groovy programming language is gaining popularity as a dynamic language on the Java platform. Groovy combines the productivity and powerful features of dynamic languages such as Ruby with the breadth and reach of the JVM platform. You can find out more about Groovy at http://groovy.codehaus.org. Heres an example of a Groovy script:
if (args.length == 0) { println(I need a number.) System.exit(-1) } size = Integer.parseInt(args[0]) Board b = new Board(size) long start = new Date().getTime() if (b.solve()) { long elapsed = new Date().getTime() - start for (i in 0..<size) { int col = b.getCol(i) for (j in 0..<col) { print( ) } println(*) } println( + elapsed/1000 + seconds.) }

You can also define classes in Groovy, similarly to Java. Heres a partial example of a class:
class Board { int size

367

Part III: Advanced SlickEdit


private private private private int[] pos boolean[] col boolean[] diag1 boolean[] diag2

Board(int size) { this.size = size this.pos = new int[size] for (i in 0..<size) { pos[i] = -1 } this.col = new boolean[size] this.diag1 = new boolean[2 * size + 1] this.diag2 = new boolean[2 * size + 1] } void place(int row, int col) { pos[row] = col this.col[col] = true diag1[col - row + size] = true diag2[col + row] = true } }

In this section, well set up limited syntax support for Groovy in SlickEdit. Well be able to provide pretty good (though not perfect) color syntax highlighting. Well also be able to provide some navigation assistance. We wont be able to provide tagging support or complete color syntax highlighting. Full tagging requires support from within the SlickEdit engine and cannot be added for arbitrary languages. Some Groovy features are beyond SlickEdits color highlighting capabilities. For example, Groovy GStrings can contain blocks of code, but theres no way to get SlickEdits string coloring to recognize this in a user-defined language. However, it turns out that even partial support is considerably more useful than no support at all. Most IDE support for dynamic languages is a lot less than for statically typed languages. It is virtually impossible to provide full syntax assistance with dynamically typed languages. SlickEdits basic text features such as word completion are extremely useful for such languages.

Color Syntax Highlighting


The procedure for setting up a Groovy mode and lexer is very similar to what we already covered for PGN files. The main difference with Groovy is that there are a few more things to specify. Here, well provide the steps to do it with the configuration GUI. Further on in the chapter, there is code that sets up the configuration automatically. To set up color syntax highlighting for Groovy, follow these steps:

1. 2.

Invoke setupext (Tools Options File Extension Setup) to open the Extension Options dialog. SlickEdit displays the dialog. Click New to create a new extension. SlickEdit displays the New Extension dialog.

368

Chapter 17: Customization


3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Enter groovy for the Extension. Leave Refer to blank. Click OK. SlickEdit closes the New Extension dialog and creates the new mode. Click the Advanced tab. Click Color Coding. SlickEdit prompts you to confirm whether you want to start a new lexer for this extension. Click Yes. SlickEdit displays the Enter New Lexer Name dialog. Enter Groovy for the New Lexer Name. Click OK. SlickEdit displays the Color Coding Setup dialog. Click the Tokens tab. Click the Keywords category. Click the New button next to the token list. SlickEdit displays the Enter New Keywords dialog. Enter the keywords for Groovy, separated by spaces:

as assert boolean break case catch char class continue def default do double else extends false finally float for if implements import in instanceof int interface long new null package private property return short static switch this throw throws true try void while

15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.

Click OK. SlickEdit adds the tokens as keywords in the Groovy language. Ensure that the Case sensitive option is checked. Click the Strings tab. Click the checkbox for \ represents a double quote. SlickEdit does not color code strings unless something is checked on this tab. Click the checkbox for Search for end quote across multiple lines, for both double-quoted strings and single-quoted strings. Click the Language tab. Click the checkbox for Color identifiers followed by ( as a function. This will result in method names being highlighted as they are in Java. Click the Comments tab. Click New Line comment. Enter // for Use delimiter. Click New Multi-line comment. Enter /* for the Start delimiter. Enter */ for the End delimiter. Click OK. SlickEdit closes the Color Coding Setup dialog and creates the lexer. Click OK. SlickEdit closes the Extension Options dialog.

369

Part III: Advanced SlickEdit


The result is partial support for Groovy syntax highlighting. Groovy, like Ruby, has powerful extended string constructs. Unfortunately, most of these constructs are impossible to support with SlickEdits current customization features. It will require dedicated support in the editor, as it did for Ruby. However, even this level of support is surprisingly useful and often sufficient for coding in Groovy.

Improved Navigation
In addition to syntax highlighting for Groovy language, it would be nice to have some improved navigation, beyond that provided by default in the fundamental mode. We wont be able to get tagging support, because SlickEdit doesnt have a Groovy parser and therefore wont tag Groovy files. But we can do some things. For example, we can provide rudimentary navigation between methods. For most programming languages, SlickEdit uses prev-tag (Ctrl+Up) and next-tag (Ctrl+Down) to navigate between procs. We can do something similar for Groovy. Its possible to support prev-tag and next-tag, as well as several other tagging features, in a user-defined language. To support these features, implement ext_proc_search() and/or vsext_list_tags() as described in tags.e. These procedures require some fairly complex parsing for some programming languages. The approach taken here for Groovy is a bit simpler, but not as powerful. The trick to navigating between procs or sections of code in SlickEdit is to come up with a regular expression search that is reasonably reliable at identifying the start of a proc or section of code. After considering a few things, I came up with these commands:
_command void wrox_groovy_prev_proc() name_info(,VSARG2_REQUIRES_EDITORCTL) { int cur_line = p_line; int cur_col = p_col; int status = search(^ \:w, -<UH@CO); if (!status) { if (p_line == cur_line && p_col == cur_col - 2) { p_line--; status = search(^ \:w, -<UH@CO); } } if (!status) { cursor_right(2); } } _command void wrox_groovy_next_proc() name_info(,VSARG2_REQUIRES_EDITORCTL) { int status = search(^ \:w, +<UH@CO); if (!status) { cursor_right(2); } } defeventtab groovy_keys; def C-Up=wrox_groovy_prev_proc; def C-Down=wrox_groovy_next_proc;

370

Chapter 17: Customization


The regular expression used by these macros is ^ \:w. This matches any identifier starting on column 2. This is a rather lame attempt at parsing Groovy source code, because Groovy places no such restrictions on source code indentation. But I found that it worked pretty effectively with my own Groovy files. The trouble with parsing Groovy more accurately is that a lot of syntax elements are optional. For example, semicolons are optional at the ends of lines. Also, braces are used for both method definitions and for closures, which are like blocks of code that can be passed around like objects. This makes parsing Groovy with simple regular expressions quite difficult; thus we have to make do with an expedient heuristic. Of course, the particular code above relies on my personal coding convention, which uses two spaces to indent method names in a class. If your code style is different, you will have to make some changes. The search options are -<UH@CO and +<UH@CO. The - and + parts instruct the search to be backward and forward, respectively. The < part makes the cursor end up at the beginning of the matched text. The U indicates a UNIX-style regular expression. The H makes the search include hidden lines. The @ prevents an error message appearing if nothing is found. Finally, the CO restricts the search to matching text color coded as other, which excludes strings and comments. The wrox-groovy-prev-proc has extra logic to cope with the common scenario where the cursor starts at the beginning of a method.

Setting Up the Extension and Event Table


The key binding definitions bind the commands to Ctrl+Up and Ctrl+Down, in the groovy_keys event table. This event table is not automatically created for the Groovy mode. By default the mode uses a default event table called _ext_keys. We can set up the event table when we define the extension, if we do it programmatically. So now well switch approaches, and instead of doing the steps to set up the new extension and lexer through the GUI, as just shown, well do it all through Slick-C. The supplied macro source contains many examples of language extensions set up programmatically. You can learn more about setting up extension-specific support by reading some of the supplied files. For example, the file ada.e contains support for the Ada programming language. Well use a single Slick-C module called wrox_groovy.e, which contains the navigation routines and key bindings above. It also includes a defload() section, which is run at the time the module is loaded (compiled). This routine does all the work necessary to set up the extension and lexer. (It also places the necessary lines in the lexer definition for color coding support.) The defload() routine looks like this:
defload() { _str setup_info=MN= :+ MODE_NAME :+ ,TABS=+2,MA=1 74 1,KEYTAB=groovy-keys,WW=1,IWT=0,ST=0,; _str compile_info=; _str syntax_info=2 1 1 1 0 1 0; _str be_info=({)|(}); int kt_index=0; create_ext(kt_index,EXTENSION,,MODE_NAME,setup_info,compile_info, syntax_info,be_info,,A-Za-z0-9_$,MODE_NAME); // Add Groovy lexer data to user.vlx. edit(maybe_quote_filename(get_env(VSLICKCONFIG) :+ user.vlx)); int status = search([Groovy]);

371

Part III: Advanced SlickEdit


if (!status) { quit(); return; // quit if file already has [Groovy] section } bottom_of_buffer(); insert_line(); insert_line([Groovy]); insert_line(idchars=a-zA-Z 0-9_$); insert_line(case-sensitive=y); insert_line(styles=xhex dqbackslash dqmultiline sqmultiline idparenfunction); insert_line(keywords= as assert boolean break case catch char class continue); insert_line(keywords= def default do double else extends false finally float); insert_line(keywords= for if implements import in instanceof int interface); insert_line(keywords= long new null package property return short static); insert_line(keywords= switch throw throws true try void while); insert_line(linecomment=//); file(); }

The defload() routine has two main parts. The first part creates the extension, mode, and event table by calling the create_ext() function. The second part adds all the lexer data to the user lexer file user.vlx. The specifics of the lines to add to the user lexer file were determined by first setting up the lexer manually and seeing what SlickEdit put in the file. The advantage of placing the lexer definitions into Slick-C code is that it can be run easily for a new SlickEdit installation, or if you reset your configuration. We take this approach to configuration further in the Programmatic Configuration section below. To install Groovy support, including the navigation routines, the extension setup, and the color coding rules, load the wrox_groovy.e module. You may need to restart SlickEdit afterward to pick up the changes to the user lexer file user.vlx. At this point you should have reasonable color coding and navigation in Groovy files.

Customizing Menus and Dialogs


As well as the Slick-C programming language, SlickEdit also provides an entire GUI development framework. You can customize virtually any GUI element in SlickEdit, and you can create your own.

Customizing a Dialog
As mentioned in Chapter 6, the Windows 3.1 or fast Open dialog can be preferable to the standard Open dialog for opening files with SlickEdit. The main problem with it is that it is too small. In newer versions of SlickEdit, more and more of the supplied dialogs are resizable. In a future version, we may be able to resize the Fast Open dialog with the mouse. In the mean time, we can resize it with the Form Editor. The _edit_form form is used whenever you invoke gui-open to open a file (provided you are using the fast Open dialog). For other Open dialogs, such as _OpenDialog() invoked from macros, the very similar _open_form form is used. If you want all Open dialogs to be larger, you need to change both forms.

372

Chapter 17: Customization


Before editing a supplied form with the Form Editor, its a good idea to back up the form. To back up the _edit_form form, follow this procedure:

1. 2. 3.

Open an empty file called edit_form_original.e. Insert this line at the top:

#include slick.sh

Invoke insert-object (Macro Insert Form or Menu Source). SlickEdit displays the Insert Form/Menu Source dialog, shown in Figure 17-1.

Figure 17-1

4. 5.

Select _edit_form. Click OK. SlickEdit closes the dialog and inserts the form source code into the buffer.

You can use this file to restore the original form at any time. To restore the form, open the file and invoke load (F12). To open the Form Editor for a form, when the form is open and has focus, press Ctrl+Shift+Space. SlickEdit puts the form into edit mode and displays its properties in a separate window. The Open dialog is shown in edit mode in Figure 17-2. The properties for the form are shown in Figure 17-3.

Figure 17-2

373

Part III: Advanced SlickEdit

Figure 17-3

In Figure 17-3, the Open dialog starts with a width of 7,110 and a height of 5,355. To see more files and directories, you can increase the width and height by 4,000 units each, provided your screen is large enough. (The Open dialog seems to have been designed for a very small screen.) To do this, follow these steps in the Form Editor:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Add 4,000 units to the width and height properties of the form. SlickEdit resizes the form on screen so that you can see what it will look like. (You can resize with the mouse too, if you prefer. However, its hard to get precise units with the mouse.) Add 4,000 units to the y properties of all the controls under the file and directory lists. You can alter the properties of a group of controls by holding down Control or Shift to multiselect them. Add 4,000 units to the y property of the Advanced button. The Open dialog opens with the advanced controls hidden, and the height of the form when initially shown is actually based on the position of the Advanced button. Add 4,000 units to the x properties of all the controls to the right of the directory list, including the Advanced button. You now have enough space to move the directory list over and increase the sizes of the file and directory lists. Add 2,000 units to the x properties of the Directories and _opencd labels, the directory list control, the Drives label, and the drives control. Add 2,000 units to the width properties of the directory list control and the drive list control. Add 2,000 units to the width of the File name control, file list control, and file types control. When you are finished making changes to the form, click the system menu box in the top-left corner. SlickEdit displays a special system menu for the form in the Form Editor, shown in Figure 17-4. Click Save Form. Close the form and the properties dialog.

374

Chapter 17: Customization

Figure 17-4

SlickEdit stores the form definition in the configuration state file. If you find you are resetting your configuration frequently, you probably dont want to have to resize the form manually every time you do. You can extract the form source to a source file, and load it to reset the form. To do this, follow these steps:

1. 2. 3. 4. 5.

Open an empty file called edit_form_large.e. Insert this line at the top:

#include slick.sh

Invoke insert-object (Macro Insert Form or Menu Source). SlickEdit displays the Insert Form/Menu Source dialog. Select _edit_form. Click OK. SlickEdit closes the dialog and inserts the form source code into the buffer.

You can save this source and load it any time you want to restore your changes to the form. Be aware that a new release of SlickEdit might include changes to the form. If you receive an upgrade to SlickEdit, you can check whether the form code is significantly different from what you have. To do this, extract the form code before changes using Insert Form/Menu Source, then use DIFFzilla to compare the source to your earlier version.

Creating a Pop-up Menu


The fastest way to invoke a SlickEdit command is through a key binding. However, there are many commands and only so many keys. You can place commands that are used less often into menus. This provides a reasonable middle ground between a single key press and typing the whole command on the command line. SlickEdit provides access to many of its commands through the main menu, and through context menus in the editing pane and in various tool windows. When weve presented features in this book, weve given the command name and any key binding or menu path to that command. The command name is given so that you can look up the implementation in the supplied macro source or make use of the command in your own macros. For using the command directly, you will usually either press a key it is bound to, or invoke it via the menu.

375

Part III: Advanced SlickEdit


SlickEdit provides a menu editor that you can use to browse and edit the existing menus, or create your own. To browse the definitions in the main menu, follow these steps:

1.

Invoke open-menu (Macros Menus). SlickEdit displays the Open Menu dialog, shown in Figure 17-5.

Figure 17-5

2. 3.

Select the _mdi_menu entry from the list. This is the main menu. Click Open. SlickEdit displays the Menu Editor, shown in Figure 17-6.

Figure 17-6

You can use the Menu Editor to browse to any menu item. You can review the command associated with the menu item, and other information. You can also customize any existing menu. But any changes you make will be lost if you reset your configuration. If you want to provide menu access to your own commands, rather than changing the existing main menu structure, you can add your own pop-up menu. You can use the Menu Editor to create menus if you want, but here well take a look at how to do it using Slick-C code.

376

Chapter 17: Customization


Well create a pop-up menu for several of the no-arg commands given as examples in this book. The following Slick-C code shows the menu definition:
_menu wrox_popup_menu { WROX commands,,,,; , , , , ; // blank item to be replaced with divider submenu &Selections, , Selections..., ncw; &Save line selection, wrox-save-line-sel, , , Save line selection to bookmarks; &Restore line selection, wrox-restore-line-sel, , , Restore line selection from bookmarks; endsubmenu submenu &Alignment, , Align..., ncw; &Left with above, wrox-align-left-with-field-above, , , Left-align next field with next field above; &Right with above, wrox-align-right-with-field-above, , , Right-align next field with next field above; endsubmenu submenu &Repeat, , Repeat..., ncw; &Last macro n times, wrox-repeat-n-last-macro, , , Repeat last_macro n times; endsubmenu submenu &Other, , Other..., ncw; Toggle &comment, wrox-toggle-comment, , , Toggle comment for line selection or current line; &Execute current command, wrox-execute-current-command, , , Execute current command; Count &duplicates, wrox-count-duplicates, , , Count duplicates; endsubmenu }

If you place this code in an .e file and load it, SlickEdit creates the menu resource. Next, we create a command to display this pop-up menu:
_command void wrox_show_wrox_popup_menu() name_info(,) { int index = find_index(wrox_popup_menu, oi2type(OI_MENU)); if (!index) { message(Cant find wrox_popup_menu); return; } int x = _screen_width()/2; int y = _screen_height()/3; int flags = VPM_CENTERALIGN|VPM_LEFTBUTTON; int child = index.p_child; child++; child.p_caption = -; int menu_handle = _menu_load(index, P); _menu_show(menu_handle, flags, x, y); _menu_destroy(menu_handle); } // middle across // one-third down screen

// put in separator line

377

Part III: Advanced SlickEdit


Finally, well bind the command to Ctrl+W with this code:
defeventtab default_keys; def C-W=wrox_show_wrox_popup_menu;

After you load all this code, when you press Ctrl+W, you should see the WROX commands menu, shown in Figure 17-7.

Figure 17-7

If you prefer the keyboard to the mouse, you can also create a simple command to show the SlickEdit context menu, normally invoked by right-clicking:
_command void wrox_show_context_menu() { int index = find_index(_ext_menu_default, oi2type(OI_MENU)|IGNORECASE_TYPE); if (!index) { message(Cant find _ext_menu_default.); } else { int x = _screen_width()/2; // middle across int y = _screen_height()/3; // one-third down screen int flags = VPM_CENTERALIGN|VPM_LEFTBUTTON; int menu_handle = _menu_load(index, P); _menu_show(menu_handle, flags, x, y); _menu_destroy(menu_handle); } } defeventtab default_keys; def S-F10= wrox_show_context_menu;

This code binds the command to Shift+F10, which is used for the context menu in most Windows applications. The default CUA emulation has the command project-compile bound to Shift+F10. If you prefer to keep project-compile on Shift+F10, you will need to select another key for wrox-show-context-menu.

Programmatic Configuration
If you work with SlickEdit a lot, you probably change many configuration options. If you install on a new machine, or you reset your configuration to fix a problem or for any other reason, you have to remember all your favorite settings and restore them before the editor is back working the way you like it. This can be tedious and time-consuming, and sometimes its hard even to remember all the settings. If

378

Chapter 17: Customization


you experiment a lot, its even more important to have a quick way to restore the editor to your preferred configuration. Fortunately, using Slick-C, its easy to create a script to restore most of your configuration settings. All personal configuration of SlickEdit is stored in the users configuration directory. Most of the configuration data are stored in the state file, which is vslick.sta on Windows and vslick.stu on UNIX. This is a binary format file that contains data such as: Compiled Slick-C code. Menu, dialog, and other resources. Global variable values. Other settings.

Some other configuration data are stored in other files and subdirectories under the user configuration directory. A simple approach to recovering your configuration is simply to save a backup copy of your configuration directory and restore it when necessary. This is certainly a fast and effective way to restore your exact configuration, down to files open and cursor positions. However, it suffers from several limitations: You need to back up the directory at appropriate times, that is, after any significant change to your configuration. There is no way to control, identify, or version the changes you make to the configuration. If your configuration becomes corrupted, the corruption could make it into your backup. At that point, you may have to begin from scratch to recover to a clean configuration. New features or other changes in new releases of SlickEdit may clash with data in your configuration, requiring it to be reset.

This section takes a different approach to configuration. Rather than configuring all options via the GUI and backing up the configuration data as a meaningless binary blob, well specify configuration as Slick-C source code. Weve already seen some examples of this approach. In Chapter 2, we presented the WROX emulation, a set of keyboard bindings that extends the CUA emulation. The bindings were provided as Slick-C source that you load in the editor for them to take effect. Some of the example commands we present in Chapter 16 and in this chapter are accompanied with keyboard binding code. The pop-up menu we defined above in this chapter is another example. By placing configuration into Slick-C, well get these advantages: Configuration choices are clear and explicit, and can be documented. Configuration source can be versioned, like other source files. Its easy to re-apply the entire configuration at any time. You start with a default configuration and run a script.

379

Part III: Advanced SlickEdit


Its easy to experiment and restore the configuration to a known state at any time. You can share configuration data more reliably with others.

This approach does not make the GUI configuration obsolete. The GUI configuration dialogs are all still tremendously useful for experimenting with configuration options and for learning what options are available in the first place, and how they are related. Once you have learned the options you want to change and have experimented to find the settings you prefer, you can express those settings in Slick-C code for applying them in the future.

Loading Key Definitions and Code


Setting configuration data in SlickEdit is a one time job, in that they do not need to be set every time SlickEdit starts or every time a module is loaded into memory and initialized. For this reason, well put the configuration-setting code in one or more batch macros, rather than ordinary modules. An example of a batch macro for configuration is shown below:
defmain() { load(../Chapter02/wrox_emulation.e); load(../Chapter02/wrox_utility.e); load(../Chapter06/wrox_bookmark_select.e); load(../Chapter08/wrox_next_prev_word.e); load(../Chapter09/wrox_comments.e); load(../Chapter10/wrox_align.e); load(../Chapter10/wrox_benchmark.e); load(../Chapter10/wrox_repeat.e); load(../Chapter11/wrox_aliases.e); load(../Chapter11/wrox_directories.e); load(../Chapter12/wrox_url_mappings.e); load(../Chapter16/wrox_assert.e); load(../Chapter16/wrox_count_duplicates.e); load(../Chapter16/wrox_execute.e); load(../Chapter16/wrox_hashes.e); load(../Chapter16/wrox_htmlend.e); load(../Chapter16/wrox_list_files.e); load(../Chapter16/wrox_move_line.e); load(../Chapter16/wrox_names.e); load(../Chapter16/wrox_strings.e); load(wrox_join_line_with_space.e); load(wrox_page_down_realign.e); load(wrox_tabs_matchtab.e); load(wrox_popup_menu.e); load(wrox_show_context_menu.e); load(forms/_edit_form_large.e); load(forms/_open_form_large.e); return 0; }

380

Chapter 17: Customization


This example loads most of the macro files weve had so far in this book. You could run this batch macro after installing SlickEdit, or with a fresh configuration directory, to load all the settings and macros in these files. To run the macro, follow these steps:

1. 2.

Use cd to change the working directory to the (drive and) directory where the wrox_load_modules.e file is located. Enter ./wrox_load_modules on the command line, and press Enter. SlickEdit executes the batch macro.

In the rest of this chapter, we will see how to put other configuration settings into batch macros.

Defining Aliases
When you define a global alias, it is stored in the alias.slk file in your configuration directory. When you define an extension-specific alias, it is stored in an extension-specific alias file, such as c.als, java.als, e.als, and the like. These files are ordinary text files, and you can edit them normally. Thus you can simply edit and version the alias files to manage them, because their contents are transparent. Alternatively, you can define aliases programmatically in the batch macro too. Heres an example of a batch macro to define several of the aliases weve seen in this book:
defmain() { int temp_window_id; int orig_window_id = _create_temp_view(temp_window_id); // fundamental mode alias(hosts C:\Windows\system32\drivers\etc\hosts); alias(cpr Copyright %\m wrox_ year% John Hurst); alias(local C:\cygwin\usr\local\); alias(pdir %\m wrox_project_dir%); alias(bdir %\m wrox_buffer_dir%); select_mode(Slick-C); alias(_command _command void %\c(%\c) name_info(%\c,%\c) {%\m nosplit_insert_line%}); _delete_temp_view(temp_window_id); if (orig_window_id) { activate_window(orig_window_id); } }

This macro uses a temporary buffer to ensure that the first bunch of aliases are defined in fundamental mode, and are thus global aliases. Then it switches to Slick-C mode to define the _command alias, which is an extension-specific alias. Note also that the _command alias expansion is more than one line. Its easy enough to enter multiple lines in the alias editor. One way to get multiline alias expansions when defining them programmatically is to embed a newline command such as nosplit_insert_line into the alias, as shown here. You can also place global aliases in files of your choice. The environment variable VSLICKALIAS can define one or more files containing global alias definitions. Separate the filenames with ; (a semicolon) on Windows and : (a colon) on UNIX. The VSLICKALIAS variable doesnt work for extension-specific aliases.

381

Part III: Advanced SlickEdit

General Configuration Settings


Many of the other settings are first encountered through the GUI dialogs. They can all be set programmatically, although there are a variety of different mechanisms used. In this section, we review some of these mechanisms. Well include examples of many settings, but not all, by any means. See the section Determining Programmatic Configuration below in the chapter to learn how to find out the programmatic interface for a given configuration setting.

Macro Variable Settings


The most straightforward configuration settings are controlled by macro variables. Many macro variable configuration settings are documented in the online Help, and some are mentioned elsewhere in this book. Some macro variable configuration settings are actually not available directly via the GUI, but only via setting the macro variables. You can set macro variables in a batch macro. The code below shows an example:
defmain() { // Two character def_select_style corresponds to two settings in the config: // Extend selection as cursor moves (C = yes, E = no) // Inclusive character selection (I = yes, N = no) // We change to EI because: // E gives more flexible selection locking, and // I is makes character selections easier to use set_var(def_select_style EI); // CUA default is CN // Leave selection after a copy, but not after a paste set_var(def_deselect_copy 0); // CUA default is 1 //set_var(def_deselect_paste 1); // CUA default is 1 // CUA style: typing replaces basic (not locked) selection //set_var(def_persistent_select D); // CUA is D // ************************ // Cursor movement/wrapping // ************************ // undo undoes cursor movement as well as changes set_var(def_undo_with_cursor 1); // CUA default is 0 // allow cursor to move freely beyond the ends of lines // Tools | Options | General, General Tab set_var(def_click_past_end 1); // CUA default is 0 // do not wrap cursor at start/end of line // Tools | Options | Redefine Common Keys (?) set_var(def_cursorwrap 0); // CUA default is 1 // Tools | Options | Redefine Common Keys set_var(def_linewrap 0); set_var(def_restore_cursor 0); set_var(def_updown_col 0);

382

Chapter 17: Customization


// ************* // Miscellaneous // ************* set_var(def_fast_open 1); set_var(def_alt_menu 0); set_var(def_top_bottom_style 1); set_var(def_toolbar_animate 0); }

// // // //

Use Windows 3.1 / fast-open dialog allow def Alt keys for commands preserve column on top/bottom turn off toolbar autohide animation

Font Settings
Fonts are particularly attractive to set programmatically. Most programmers have a favorite programming font and would prefer to use it for most of the SlickEdit UI elements that involve display or editing of code. The GUI for configuring fonts is flexible because it lets you choose a different font for different elements. But this makes it tedious when you simply want to set the same font for a bunch of elements. Fortunately, its rather easy to do this programmatically. Below is a batch macro that sets Bitstream Vera Sans Mono as the font for these UI elements: Selection lists. DIFFzilla editor window. File manager. Hex mode. SBCS editing. Unicode editing.

defmain() { set_var(def_sellist_font Bitstream Vera Sans Mono,10,0,1,); _default_font(CFG_DIFF_EDITOR_WINDOW, Bitstream Vera Sans Mono,10,0,1,); _default_font(CFG_FILE_MANAGER_WINDOW, Bitstream Vera Sans Mono,10,0,1,); _default_font(CFG_HEX_SOURCE_WINDOW, Bitstream Vera Sans Mono,10,0,1,); _default_font(CFG_SBCS_DBCS_SOURCE_WINDOW, Bitstream Vera Sans Mono,10,0,1,); _default_font(CFG_UNICODE_SOURCE_WINDOW, Bitstream Vera Sans Mono,10,0,1,); setall_wfonts(Bitstream Vera Sans Mono,10,0,1, CFG_DIFF_EDITOR_WINDOW); setall_wfonts(Bitstream Vera Sans Mono,10,0,1, CFG_FILE_MANAGER_WINDOW); setall_wfonts(Bitstream Vera Sans Mono,10,0,1, CFG_HEX_SOURCE_WINDOW); setall_wfonts(Bitstream Vera Sans Mono,10,0,1, CFG_SBCS_DBCS_SOURCE_WINDOW); setall_wfonts(Bitstream Vera Sans Mono,10,0,1, CFG_UNICODE_SOURCE_WINDOW); }

Obviously, you need to have the font installed for this macro to work. The selection list font is actually controlled by a macro variable. The other fonts for the other UI elements are set using the _default_font() and setall_wfonts() functions. The _default_font() function is described in the online Help, but the example presented here should be sufficient for most purposes.

383

Part III: Advanced SlickEdit


Extension-Specific Settings
Extension-specific settings are set using the _setext() function. This function can take a wide variety of different options, depending on which aspect of extension-specific settings you wish to change. The batch macro below contains some code to change the indentation settings for C, Slick-C, Java, and Ruby files:
defmain() { _setext(c, _setext(e, _setext(java, _setext(ruby, }

options,2 options,2 options,2 options,2

1 1 1 1

1 1 1 1

0 0 0 0

4 4 4 1

1 1 1 0

1 0 1 0

1 0); 1 0); 1 0); 0);

The possible options and settings for _setext() are quite intricate. The online Help recommends using macro recording to generate calls that set these options. This process is described below, under Determining Programmatic Configuration.

Other Settings
A handful of other settings use their own specific APIs. Below are some examples:
defmain() { _default_option(F,1); _default_option(u,1); _default_option(L,250); display_top(y); }

// // // //

Maximize first window. Draw box around current line Left margin Show Top-of-File line

Again, its not practical to document all of these in detail. Instead, refer to Determining Programmatic Configuration below to find out how to discover these APIs for yourself.

Determining Programmatic Configuration


Some settings, such as those controlled by certain macro variables, are pretty well documented in the online Help. Others, such as fonts, follow a simple pattern, and you can probably adapt the code above to your own requirements easily. For many other settings, you are probably wondering how you can determine what code to write to update the setting. In this section, we review several techniques you can use to find out about how to program SlickEdit configuration.

Using Macro Recording


A direct approach to finding out what Slick-C calls to make to achieve a certain configuration change is to use macro recording. For example, suppose we start with a fresh SlickEdit configuration and want to find out the Slick-C call to change the Open dialog to fast Open. Follow these steps:

1. 2.

Invoke record-macro-toggle (Ctrl+F11). SlickEdit begins recording a macro. Open the General Options configuration dialog (Tools Options General).

384

Chapter 17: Customization


3. 4. 5. 6. 7.
Click the More tab. Click the checkbox for the Windows 3.1 style open dialog. Click OK. Invoke record-macro-toggle (Ctrl+F11). SlickEdit prompts you how to save the macro. Click Cancel.

These steps apply only on Windows. On UNIX there is only one Open dialog. Now open the lastmac.e file in your configuration directory. It contains these lines:
#include slick.sh _command last_recorded_macro() name_info(,VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL) { _macro(R,1); execute(show -modal _config_form); def_fast_open=1; }

By reading this source, you can discover (if you didnt already know) that the Fast Open dialog is controlled by the def_fast_open macro variable. Heres another example, where we alter line wrapping and cursor behavior using Redefine Common Keys:

1. 2. 3. 4. 5. 6. 7. 8.

Invoke record-macro-toggle (Ctrl+F11). SlickEdit begins recording a macro. Open the Redefine Common Options configuration dialog (Tools Options Redefine Common Keys). Uncheck the Cursor wrap option. Uncheck the Up/Down on text option. Uncheck the Line wrap on text option. Click OK. Invoke record-macro-toggle (Ctrl+F11). SlickEdit prompts you how to save the macro. Click Cancel.

Now open lastmac.e. It contains these lines:


#include slick.sh _command last_recorded_macro() name_info(,VSARG2_MARK|VSARG2_REQUIRES_EDITORCTL) { _macro(R,1); execute(show -modal -mdi _rc_keys_form); def_cursorwrap=0; def_updown_col=0; def_updown_screen_lines=1; def_linewrap=0; def_jmp_on_tab=1;

385

Part III: Advanced SlickEdit


def_pull=1; def_hack_tabs=0; def_emulate_leading_tabs=0; }

With some thinking (not too much!), we can determine that the values we changed are:
def_cursorwrap corresponds to the Cursor wrap option. def_updown_col corresponds to the Up/Down on text option. def_linewrap corresponds to the Line wrap on text option.

You should be able to use a similar procedure to determine most configuration settings in SlickEdit.

Using list-source
Another way to find out a lot about SlickEdit configuration is the list-source command. When you invoke this command, SlickEdit opens and updates vusrdefs.e in your configuration directory. This file contains Slick-C code for your current configuration. The first part of the listing contains all the key definitions, first for the default event table and then for mode-specific event tables. The second part of the listing contains Slick-C statements to set macro variables and other settings. On UNIX, the file is called vunxdefs.e. The format is basically the same, but paths are expressed in UNIX format rather than DOS format. The list-keydefs command populates the same key definitions as list-source into an empty buffer called keydefs.e, and the list-config does the same for the configuration settings into an empty buffer called lconfig.e. Sometimes you can find a configuration setting you are looking for by searching for a keyword in the output of list-source. For example, by issuing the command below, you can find all macro variables pertaining to bookmarks.
all/def.*book/u

Another thing you can do with list-source is run it at different times while you experiment with configuration. Use DIFFzilla to compare the new vusrdefs.e with the one last saved on disk, to see what changes. You can then take lines from vusrdefs.e and paste them into your own batch macro. It can be a good idea to save a copy of vusrdefs.e from your emulation before you start any customization, so that you can later review the net effect of your changes. However, if you dont take a snapshot, its easy to create one by starting SlickEdit with a fresh configuration at any time. We cover restoring to the default configuration in Chapter 2. You could simply use vusrdefs.e for managing your configuration. It is a text file, and the format is transparent. One problem with this is that vusrdefs.e contains too much information. It contains all the settings, not just the ones you changed. This is not appropriate for migrating your changes to a different version of SlickEdit, if you want your changes to be applied on top of SlickEdits defaults. Using vusrdefs.e, you will clobber new settings and new defaults when they arrive in new versions.

386

Chapter 17: Customization


Reading Macro Source
One last approach to programmatic configuration is to study the supplied macro source. The file config.e in the macros directory contains code for the General Options configuration dialog, among others. Other configuration is handled in other modules. You can find the appropriate module by studying the form code for the configuration dialog in which you are interested. For example, suppose you want to find which Slick-C file contains code for the Redefine Common Keys dialog. Follow these steps:

1. 2. 3. 4.

Open the Redefine Common Keys dialog (Tools Options Redefine Common Keys). Press Ctrl+Shift+Space. SlickEdit displays the Form Editor. Note that the name of the form is _rc_keys_form. Close the Form Editor. Invoke gui-find-proc (Macro Go to Slick-C Definition). SlickEdit displays the Go to Definition dialog, shown in Figure 17-8.

Figure 17-8

5. 6. 7.

Enter _rc_keys_form for the Symbol. Click OK. SlickEdit displays the Select a tag dialog, shown in Figure 17-9. The sysobjs.e file contains the definition of the form and its GUI components. The config.e file contains the code.

Figure 17-9

387

Part III: Advanced SlickEdit


Thus, the Redefine Common Keys form is also handled in config.e. You can now navigate to references to _rc_keys_form. The important function is the event handler for the OK button, which is a function called _ckok.lbutton_up():
_ckok.lbutton_up() { _macro(m,_macro(s)); def_cursorwrap = _cursorwrap.p_value!=0; _macro_append(def_cursorwrap=_cursorwrap.p_value;); def_updown_col = _updown_col.p_value; _macro_append(def_updown_col=_updown_col.p_value;); def_updown_screen_lines = ctlUpDownWithin.p_value!=0; _macro_append(def_updown_screen_lines=ctlUpDownWithin.p_value;); def_linewrap = _linewrap.p_value!=0; _macro_append(def_linewrap=_linewrap.p_value;); def_jmp_on_tab = _jumpover_tabs.p_value!=0; _macro_append(def_jmp_on_tab=_jumpover_tabs.p_value;); def_pull = _pullchars.p_value!=0; _macro_append(def_pull=_pullchars.p_value;); def_hack_tabs = _hacktabs.p_value!=0; _macro_append(def_hack_tabs=_hacktabs.p_value;); def_emulate_leading_tabs = ctlemulatetabs.p_value!=0; _macro_append(def_emulate_leading_tabs=ctlemulatetabs.p_value;); _config_modify_flags(CFGMODIFY_DEFVAR); p_active_form._delete_window(1); }

By reading this function, you can easily determine which macro variables are set by which options. Initialization (of configuration settings) is generally done in ok.on_create(), and finalization is done in ok.lbutton_up(). Most SlickEdit forms follow this pattern. Reading the macro source requires somewhat more effort and investment than using the macro recording approach, but sometimes the benefits are worth it. Sometimes the macro recording approach is imprecise, because it may output code that is not relevant to what you are trying to achieve. For example, with the Redefine Common Keys example above, the recorded macro outputs code for all the controls on the dialog, not just the ones we changed. In that case, it was easy to see which macro variables we really wanted. In other cases, such as color configuration, recorded macros output many Slick-C statements, not all of which are relevant. Reading the supplied configuration code can give you a clear idea of how the configuration really works and how best to program it. In the end, you decide what investment you want to make into studying the supplied macro source, what level of customization you would like, and what level of repeatability you require.

388

Chapter 17: Customization

Summar y
Thats the end of Chapter 17, and thats the end of the book. SlickEdit is the result of many years of text editor evolution. Its biggest strength is its underlying architecture, which has allowed it to mature over a long time but still have new features added every year. It is remarkably easy to customize and extend, thanks to Slick-C. The last two chapters should have given you a pretty good idea of whats possible with SlickEdit. Actually, anything is possible! Slick-C is a versatile and yet easy programming language. The existing source code is rich and extensive. The biggest challenge is trying to understand it all. I hope that with these two chapters youve got enough of an introduction to see how you can use Slick-C to customize the editor for your own needs. Every company and every developer is different. A powerful tool is one that can be adapted to your needs and the way you like to work. On the other hand, SlickEdit is surprisingly versatile. Features and macros work alike across all major operating systems currently in use, and developers use SlickEdit for languages from Ada to Yacc (and Groovy!) and everything in between. Perhaps you will write some macros that could be useful to others, and post them at the SlickEdit Community Forums (http://community.slickedit.com). See you there!

389

Settings for Different Emulations


This appendix contains several tables listing commands, key definitions, and other settings for several different emulations. The tables are: Command Keys by Category. Key Commands. Macro Variable Settings.

The emulations included are: CUA, or Windows. SlickEdit. Visual C++ 6.0. Visual Studio.

The tables listed here were generated using a Slick-C macro command wrox-make-emulations. The code for this macro is included on the CD-ROM, under Author/Chapter16/wrox_make_ emulations.e. You can use the macro to generate plain text or HTML tables of selected emulations. The tables printed in this book are for SlickEdit version 12.0.2. SlickEdit emulations change in minor ways from release to release.

Appendix A: Settings for Different Emulations

Command Keys by Categor y


Tables A-1 to A-10 list commands by category, showing key bindings for the commands. The categories are: Debugging Commands. Editing Commands. File Commands. Macro Commands. Miscellaneous Commands. Navigation Commands. Project Commands. Search Commands. Toolbar Commands. Window Commands.

In this book, modifier keys have been spelled out, like Alt for the Alternate key and Ctrl for the Control key. In the tables in this appendix, the modifier keys are abbreviated to single letters to save space. Thus the tables list A+ for the Alternate key modifier and C+ for the Control key. Many commands have multiple alternative key bindings. For these, the alternatives are separated by semicolons. Some key bindings are for sequences of keys, where one key must be pressed after another (not at the same time). These sequences are shown with the keys separated by commas. For example, the SlickEdit emulation has two key combinations for the insert-toggle command. You can press the Insert key, or you can press Ctrl+X followed by Ctrl+O. These alternatives are shown in the table as INS; C+X,C+O.

Debugging Commands
Table A-1
Command
activate_autos

CUA C+A+A; C+M+A

SlickEdit C+A+A; C+M+A

Visual C++ 6 C+A+A; C+M+A

Visual Studio C+A+A; C+M+A; C+A+V,A C+A+B; C+M+B C+A+E

activate_ breakpoints activate_ exceptions

C+A+B; C+M+B

C+A+B; C+M+B

C+A+B; C+M+B

392

Appendix A: Settings for Different Emulations


Table A-1 (continued)
Command
activate_locals activate_locals2 activate_members

CUA C+A+L; C+M+L

SlickEdit C+A+L; C+M+L

Visual C++ 6 C+A+L; C+M+L

Visual Studio C+A+L; C+M+L C+A+V,L

C+A+M; C+M+M

C+A+M; C+M+M

C+A+M; C+M+M

C+A+M; C+M+M C+A+V,T

activate_ members2 activate_memory

A+6; M+6

A+6; M+6

A+6; M+6

A+6; M+6; C+A+M,1; C+A+M,2; C+A+M,3; C+A+M,4 A+5; C+A+G; M+5 C+A+H; C+M+H A+4; C+A+V; C+M+V; M+4 A+3; C+A+W, 1; C+M+W; M+3 C+A+W,2 C+A+W,3 C+A+W,4 C+A+Q

activate_ registers activate_threads

A+5; M+5

A+5; M+5

A+5; M+5

C+A+H; C+M+H A+4; C+A+V; C+M+V; M+4 A+3; C+A+W; C+M+W; M+3

C+A+H; C+M+H A+4; C+A+V; C+M+V; M+4 A+3; C+A+W; C+M+W; M+3

C+A+H; C+M+H A+4; C+A+V; C+M+V; M+4 A+3; C+A+W; C+M+W; M+3

activate_ variables activate_watch

activate_watch2 activate_watch3 activate_watch4 debug_add_watch debug_ breakpoints debug_clear_all_ breakpoints debug_restart debug_run_to_ cursor

A+F9; M+F9 C+S+F9 C+S+F5 C+F10

A+F9; M+F9 C+S+F9 C+S+F5 C+F10

A+F9; M+F9 C+S+F9 C+S+F5 C+F10

A+F9; M+F9 C+S+F9 C+S+F5 C+F10

continued

393

Appendix A: Settings for Different Emulations


Table A-1 (continued)
Command
debug_show_next_ statement debug_step_into debug_step_out debug_step_over debug_stop debug_toggle_ breakpoint debug_toggle_ breakpoint_ enabled

CUA A+Pad-star; M+Pad-star F11 S+F11 F10 S+F5 F9 C+F9

SlickEdit A+Pad-star; M+Pad-star F11 S+F11 F10 S+F5

Visual C++ 6 A+Pad-star; M+Pad-star F11 S+F11 F10 S+F5 F9 C+F9

Visual Studio A+Pad-star; M+Pad-star F11 S+F11 F10 S+F5 C+B; F9 C+F9

Editing Commands
Table A-2
Command
adjust_block_ selection append_cut append_to_ clipboard beautify beautify_ selection cap_selection cap_word cbacktab codehelp_ complete

CUA

SlickEdit A+A; M+A

Visual C++ 6 A+A C+S+X C+S+C

Visual Studio A+A C+S+X C+S+C C+K,C+D C+K,C+F

C+S+X C+S+C

C+S+X C+S+C

C+S+A

C+S+F2 C+S+F1 S+TAB

C+S+A

C+S+A

S+TAB C+Space

S+TAB A+Right; C+Space

C+Space

C+Space

394

Appendix A: Settings for Different Emulations


Table A-2 (continued)
Command
comment comment_erase complete_more complete_next complete_prev copy_to_ clipboard copy_to_cursor copy_word ctab cut

CUA

SlickEdit

Visual C++ 6

Visual Studio C+K,C+C C+K,C+U

C+S+Space C+S+dot C+S+comma C+C; C+Ins; M+C

C+S+Space C+S+dot C+S+comma A+V; C+Ins; M+V A+C; M+C C+S+dot C+S+comma C+C; C+Ins; M+C A+C C+S+dot C+S+comma C+C; C+Ins; M+C A+C

C+K

C+X,C+W Tab

C+X; M+X; S+Del C+Del C+E C+Backspace

A+K; M+K; S+Del C+Del C+E C+Backspace

A+K; C+X; M+X; S+Del

A+K; C+X; M+X; S+Del

cut_code_block cut_end_line cut_line cut_sentence cut_word

C+L A+L

C+L A+L

C+S+K

A+W; C+S+K; M+W C+D; DEL C+S+L C+Backspace A+F4; M+F4 C+Del C+Del A+U C+S+L C+Backspace

delete_char delete_line delete_prev_word delete_tile delete_word deselect fill_selection

C+U

A+U; M+U A+F; M+F

A+U

continued

395

Appendix A: Settings for Different Emulations


Table A-2 (continued)
Command
insert_ blankline_above insert_ blankline_below insert_toggle join_line keyin_buf_name keyin_enter keyin_match_paren keyin_space linewrap_delete_ char linewrap_rubout

CUA

SlickEdit

Visual C++ 6

Visual Studio C+Enter C+S+Enter

Ins

Ins; C+X,C+O A+J; M+J A+N; M+N

Ins A+J A+N S+Enter ) S+Space Del

Ins A+J A+N S+Enter ) S+Space Del Backspace

S+Enter ) S+Space Del Backspace

S+Enter ) S+Space

Backspace

Backspace; S+Backspace A+dot; C+A+T; M+dot C+U

list_symbols

A+dot; M+dot

A+dot; M+dot

A+dot; C+A+T; M+dot C+U

lowcase_selection lowcase_word maybe_complete maybe_list_ matches move_text_backtab move_text_tab move_to_cursor nosplit_insert_ line nosplit_insert_ line_above

C+S+L

C+F4; C+S+L C+F2

Space ? S+Tab Tab

Space ? C+X,S+Tab C+X,Tab A+M; M+M

Space ?

Space ?

C+M; Tab

Tab

C+Enter C+S+Enter

C+Enter; Enter C+S+Enter

C+Enter C+S+Enter

396

Appendix A: Settings for Different Emulations


Table A-2 (continued)
Command
overlay_block_ selection paste

CUA

SlickEdit A+O; M+O

Visual C++ 6

Visual Studio

C+V; M+V; S+Ins

C+Y; S+Ins

C+V; M+V; S+Ins A+M+V C+S+Z; C+Y; S+M+Z

C+V; M+V; S+Ins

paste_replace_ word redo

C+S+Y C+Y; S+M+Z S+F9; C+X,R

A+S+Backspace; C+S+Z; C+Y; S+M+Z

reflow_paragraph reflow_selection select_all select_block select_char select_line select_matching_ brace select_next_ condition select_prev_ condition select_whole_word shift_selection_ left shift_ selection_right split_insert_line split_line transpose_chars

A+P; M+P C+X,C+P C+A; M+A C+B F8 C+L A+B; M+B A+Z; M+Z A+L; M+L C+A; M+A C+B A+Z; F8 C+F8 C+S+E C+S+K C+S+J C+W S+F7 S+F8 Enter A+S; M+S; C+X,S C+T continued S+F7 S+F8 S+F7 S+F8 Enter Enter A+Z C+F8 C+S+E C+S+K C+S+J C+W S+F7 C+A; M+A

397

Appendix A: Settings for Different Emulations


Table A-2 (continued)
Command
transpose_lines transpose_words undo

CUA

SlickEdit

Visual C++ 6 A+S+T C+S+T

Visual Studio A+S+T C+S+T M+Z

A+Backspace; C+Z; M+Z

A+Backspace; F9; M+Backspace

A+Backspace; C+Z; M+Backspace; M+Z S+F9

undo_cursor

S+Backspace; S+F9

C+F9; S+Backspace

A+Backspace; C+Z; S+Backspace; S+F9 C+S+Del C+S+U

unsurround upcase_selection upcase_word

C+S+Del C+S+U

C+S+Del C+F3; C+S+U C+F1

C+S+Del C+S+U

File Commands
Table A-3
Command
close_all close_buffer file gui_cd gui_open gui_print new quit safe_exit

CUA A+M+W S+M+W F4 C+D C+O; F7; M+O M+P M+N F3 A+F4; M+F4; M+Q

SlickEdit A+M+W S+M+W F4

Visual C++ 6 A+M+W S+M+W

Visual Studio A+M+W S+M+W

F7; C+X,C+F

C+O; M+O C+P; M+P C+N; M+N

C+O; M+O C+P; M+P C+N; M+N

F3; C+X,K A+X; M+X; C+X,Ctrl+C A+F4; A+X; M+F4; M+Q A+F4; A+X; M+F4; M+Q

398

Appendix A: Settings for Different Emulations


Table A-3 (continued)
Command
save

CUA C+S; F2; M+S; S+F12

SlickEdit F2; S+F12; C+X,C+S

Visual C++ 6 C+S; M+S

Visual Studio C+S; F2; M+S

save_all save_as

C+S+S S+M+S S+M+S S+M+S S+M+S

Macro Commands
Table A-4
Command
end_recording execute_last_ macro_key

CUA

SlickEdit C+X,)

Visual C++ 6

Visual Studio

C+S+F12, 09; C+S+F12, A-Z; C+S+F12, F1F12

C+S+F12, 09; C+S+F12, A-Z; C+S+F12, F1F12 C+X,E

C+S+F12, 09; C+S+F12, A-Z; C+S+F12, F1F12

C+S+F12, 09; C+S+F12, A-Z; C+S+F12, F1F12

last_macro load record_macro_ end_execute record_macro_ toggle start_recording

F12 C+F12 C+F11

F12; C+X,C+L C+F12; C+T C+F11; C+R C+X,(

C+F12 C+S+P C+S+R C+S+P C+S+R

Miscellaneous Commands
Table A-5
Command
abort api_index

CUA

SlickEdit C+G

Visual C++ 6

Visual Studio

A+F1; M+F1

A+F1; M+F1

A+F1; M+F1

A+F1; M+F1 continued

399

Appendix A: Settings for Different Emulations


Table A-5 (continued)
Command
cmdline_toggle collapse_to_ definitions compare config diff doc execute_selection

CUA Esc

SlickEdit C+A; Esc

Visual C++ 6 Esc

Visual Studio Esc C+M,C+O

F6

F6 F5

F6

F6

C+equals

C+equals C+X,C+E

C+equals

C+equals

A+equals; M+equals C+S+O C+S+P

A+equals; M+equals C+S+O C+S+P

A+equals; M+equals C+S+O

A+equals; M+equals

expand_alias expand_extension_ alias format_selection function_ argument_help

A+F8; M+F8 A+comma; M+comma A+comma; M+comma A+comma; C+S+Space; C+T; M+comma

A+F8 A+comma; C+S+Space; M+comma C+A+R

goto_url help hex hide_selection html_preview javadoc_editor list_buffers

F1; S+M+slash C+S+H

F1; S+M+slash C+S+H

F1; S+M+slash C+S+H

F1; S+M+slash

C+M,C+H C+S+W C+S+D C+S+B C+S+D C+S+B; C+X,C+B C+S+D C+S+B C+S+D

400

Appendix A: Settings for Different Emulations


Table A-5 (continued)
Command
list_clipboards

CUA C+S+V

SlickEdit C+S+V; C+X,C+Y

Visual C++ 6 C+S+V

Visual Studio C+S+V

macos_font_config macos_show_colors maybe_active_ search_hist_list plusminus

M+T S+M+C S+M+C

M+T S+M+C C+D

M+T S+M+C C+D C+backslash; C+M,C+M C+Q

C+backslash

C+backslash

C+backslash

quote_key resume resync show_all show_selection softwrap_toggle start_process

C+Q

C+Q C+X,C+Z

C+Q

S+F6

S+F6

S+F6

S+F6 C+M,C+P C+M,C+U C+R,C+R

C+S+M

C+S+M; C+X,C+M C+C

C+S+M

C+S+M

stop_process toggle_all_ outlining view_ specialchars_ toggle view_ whitespace_toggle wh wh2

C+Break

C+Break C+M,C+L

C+S+8

C+S+8

C+R,C+W

C+F1 C+F2

C+F1

C+F1

401

Appendix A: Settings for Different Emulations

Navigation Commands
Table A-6
Command
alias_cd alt_gtbookmark back

CUA

SlickEdit C+X,C+D

Visual C++ 6

Visual Studio

C+S+9 Back-ButtonDown M+Left Home Back-ButtonDown M+Left C+U; Home A+Y; M+Y C+End; M+Down C+End; M+Down; C+X,C+J C+PgDn Back-ButtonDown M+Left Home A+Y C+End; M+Down

C+S+9 Back-ButtonDown M+Left Home A+Y C+End; M+Down

begin_line begin_line_text_ toggle begin_select bottom_of_buffer

bottom_of_window clear_bookmarks cursor_down cursor_error

C+PgDn

C+PgDn C+S+F2

C+PgDn C+K,C+L Down A+1; C+S+G; M+1 Left Right Up End; M+Right

Down A+1; M+1

C+K; Down A+1; M+1

Down A+1; C+S+G; M+1 Left Right Up End; M+Right

cursor_left cursor_right cursor_up end_line

Left Right Up End; M+Right

C+J; Left C+L; Right C+I; Up C+O; End; M+Right A+E; M+E

end_select fast_scroll

Wheel-Down; Wheel-Up C+]

Wheel-Down; Wheel-Up A+T; C+]; M+T

Wheel-Down; Wheel-Up C+E; C+]

Wheel-Down; Wheel-Up C+E; C+S+]; C+] A+F12

find_matching_ paren find_tag

402

Appendix A: Settings for Different Emulations


Table A-6 (continued)
Command
forward

CUA Forward-ButtonDown

SlickEdit Forward-ButtonDown

Visual C++ 6 Forward-ButtonDown C+G

Visual Studio Forward-ButtonDown C+G

gui_goto gui_goto_line list_errors next_bookmark next_buffer next_condition next_doc next_error

C+J C+S+E C+S+E F2 C+N C+B; F8 C+K C+S+Pad-minus C+S+Down A+F10; C+S+Down; M+F10; C+X,C+N C+[ A+Down C+Down C+Tab; C+W; C+X,O A+Right; C+Right C+N; PgDn C+P; PgUp C+comma; C+X,C+H C+F6; C+S+N; C+Tab A+Right; C+Right PgDn PgUp C+comma; C+Pad-star S+F2 C+P A+F8; C+F8; C+V; M+F8 continued C+F6; C+Tab C+S+Down; F4 C+S+Down; F4; F8 C+K,C+N

next_hotspot next_paragraph next_tag next_window

C+[ A+Down C+Down C+F6; C+Tab

C+[ A+Down

C+[ A+Down

next_word

A+Right; C+Right PgDn PgUp C+comma

A+Right; C+Right PgDn PgUp C+comma; C+Pad-star C+K,C+P

page_down page_up pop_bookmark

prev_bookmark prev_buffer

403

Appendix A: Settings for Different Emulations


Table A-6 (continued)
Command
prev_condition prev_doc prev_error

CUA

SlickEdit

Visual C++ 6 C+J

Visual Studio C+J C+Pad-minus

C+S+Up

C+S+Up

C+S+Up; S+F4

C+S+Up; S+F4; S+F8 C+S+[ A+Up

prev_hotspot prev_paragraph prev_tag prev_window

C+S+[ A+Up C+Up C+S+F6; C+S+Tab; C+S+W A+Left; C+Left C+slash C+dot

C+S+[ A+Up C+Up C+S+F6; C+S+Tab; C+S+W A+Left; C+Left C+slash C+dot; C+H

C+S+[ A+Up

C+S+F6; C+S+Tab

C+S+F6; C+S+Tab; C+S+W A+Left; C+Left C+slash; S+F12 C+dot; C+F12; F12 C+Down

prev_word push_ref push_tag

A+Left; C+Left C+slash; S+F12 C+dot; F12

scroll_down scroll_left scroll_page_down scroll_page_up scroll_right scroll_up set_bookmark set_next_error toggle_bookmark top_of_buffer

S+F2 S+F3 C+Wheel-Down C+Wheel-Up C+Wheel-Down C+Wheel-Up S+F4 S+F1

C+Down

C+Wheel-Down C+Wheel-Up

C+Wheel-Down C+Wheel-Up

C+Up A+F2; M+F2

C+Up

C+S+S C+S+J C+Home; M+Up

C+S+S; C+X,N C+S+J C+Home; M+Up; C+X,C+U C+PgUp

C+S+S C+F2 C+Home; M+Up C+K,C+K C+Home; M+Up

top_of_window

C+PgUp

C+PgUp

C+PgUp

404

Appendix A: Settings for Different Emulations

Project Commands
Table A-7
Command
project_add_file project_build

CUA

SlickEdit

Visual C++ 6

Visual Studio A+S+A

C+M

A+F5; C+M; M+F5; C+X,M A+F6; C+F6; M+F6; S+F10

F7

C+S+B

project_compile

S+F10

C+F7; S+F10

C+F7; S+F10

project_debug project_edit project_execute workspace_new workspace_open

F5

F5 A+F7; M+F7

F5 A+F7 C+F5 C+S+N C+S+O

C+F5

C+F5

C+F5

Search Commands
Table A-8
Command
find_in_files find_next

CUA C+S+F C+G; M+G

SlickEdit

Visual C++ 6

Visual Studio C+S+F

C+F

C+Pad-plus; F3; M+G C+Pad-minus; C+S+F3; S+F3; S+M+G A+F3; C+F; M+F; M+F3 C+H

F3; M+G

find_prev

C+S+G; S+M+G

C+S+F; C+S+G; S+M+G

C+S+F3; S+F3; S+M+G

gui_find

C+F; M+F

C+F; M+F

gui_replace i_search quick_search

C+R C+I C+S

C+H C+I C+F3 continued

C+I C+F3

405

Appendix A: Settings for Different Emulations


Table A-8 (continued)
Command
replace_in_files reverse_i_search set_find toggle_so_ backwards toggle_so_ matchcase toggle_so_regex

CUA C+S+R C+S+I M+E

SlickEdit

Visual C++ 6

Visual Studio C+S+H

C+S+I; C+X,C+R

C+S+I M+E

C+S+I M+E A+F3,B A+F3,C A+F3,R

Toolbar Commands
Table A-9
Command
activate_ bookmarks activate_build activate_call_ stack activate_output activate_output_ toolbar activate_ project_classes activate_ project_files activate_ project_toolbar activate_tag_ properties_ toolbar

CUA C+S+N

SlickEdit C+S+N

Visual C++ 6 A+S+F2

Visual Studio C+K,C+W C+A+A

A+7; C+A+C; C+M+C; M+7

A+7; C+A+C; C+M+C; M+7

A+7; C+A+C; C+M+C; M+7

A+7; C+A+C; C+M+C; M+7 C+A+O

A+2; M+2

A+2 C+A+J C+A+L

A+0; M+0 A+F12; M+F12

A+0

406

Appendix A: Settings for Different Emulations

Window Commands
Table A-10
Command
close_window create_tile fullscreen hsplit_window iconize_all iconize_window maximize_mdi move_edge move_mdi move_window one_window restore_mdi size_mdi size_window zoom_window

CUA C+F4; M+W A+F3; M+F3

SlickEdit

Visual C++ 6 C+F4; M+W

Visual Studio C+F4; M+W M+F3 A+S+Enter

A+F3; M+F3

C+H A+M+M M+M A+F10; M+F10 A+F2; M+F2 A+F7; M+F7 C+F7

C+X,2 A+M+M A+M+M M+M A+F10; M+F10 A+F2; M+F2 A+F7; M+F7 C+F7 C+X,1 A+M+M M+M A+F10; M+F10 M+F2 M+F7

A+F5; M+F5 A+F8; M+F8 C+F8 C+S+Z C+S+Z; C+Z

A+F5; M+F5

A+F5; M+F5 M+F8

407

Appendix A: Settings for Different Emulations

Key Commands
Table A-11 lists the commands bound to keys in the different emulations.

Table A-11
Key Space C+Space C+S+Space S+Space ) * ? Back-Button-Down Backspace Del Down End Enter Esc F1 F2 F3 CUA
maybe_ complete codehelp_ complete complete_more

SlickEdit
maybe_ complete codehelp_ complete complete_more

Visual C++ 6
maybe_ complete codehelp_ complete function_ argument_help keyin_space keyin_match_ paren rexx_star maybe_list_ matches back linewrap_ rubout linewrap_ delete_char cursor_down end_line split_insert_ line cmdline_ toggle help next_bookmark find_next

Visual Studio
maybe_ complete codehelp_ complete function_ argument_help keyin_space keyin_match_ paren rexx_star maybe_list_ matches back linewrap_ rubout linewrap_ delete_char cursor_down end_line split_insert_ line cmdline_ toggle help save find_next

keyin_space keyin_match_ paren rexx_star maybe_list_ matches back linewrap_ rubout linewrap_ delete_char cursor_down end_line split_insert_ line cmdline_ toggle help save quit

keyin_space keyin_match_ paren rexx_star maybe_list_ matches back linewrap_ rubout delete_char

cursor_down end_line nosplit_ insert_line cmdline_toggle help save quit

408

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key F4 F5 F6 F7 F8 F9 CUA
file project_debug compare gui_open select_char debug_ toggle_ breakpoint debug_step_ over debug_step_ into load forward

SlickEdit
file config compare gui_open next_buffer undo

Visual C++ 6
next_error project_debug compare project_build select_char debug_ toggle_ breakpoint debug_step_ over debug_step_ into push_tag forward

Visual Studio
next_error project_debug compare

next_error debug_ toggle_ breakpoint debug_step_ over debug_step_ into push_tag forward

F10 F11 F12 Forward-ButtonDown Home Ins LButton-doubleclick LButton-Down LButton-triple-click Left MButton-Down Mouse-Move PgDn PgUp

debug_step_ over debug_step_ into load forward

begin_line_ text_toggle insert_toggle mou_select_ word mou_click mou_select_ line cursor_left mou_paste _mouse_move page_down page_up

begin_line_ text_toggle insert_toggle mou_select_ word mou_click mou_select_ line cursor_left mou_paste _mouse_move page_down page_up

begin_line_ text_toggle insert_toggle mou_select_ word mou_click mou_select_ line cursor_left mou_paste _mouse_move page_down page_up

begin_line_ text_toggle insert_toggle mou_select_ word mou_click mou_select_ line cursor_left mou_paste _mouse_move page_down page_up

continued

409

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key RButton-Down Right Tab Up Wheel-Down Wheel-Up A+0 CUA
mou_click_ menu_block cursor_right move_text_tab cursor_up fast_scroll fast_scroll

SlickEdit
mou_click_ menu_block cursor_right ctab cursor_up fast_scroll fast_scroll

Visual C++ 6
mou_click_ menu_block cursor_right move_text_tab cursor_up fast_scroll fast_scroll activate_ project_ toolbar

Visual Studio
mou_click_ menu_block cursor_right move_text_tab cursor_up fast_scroll fast_scroll activate_ project_ toolbar cursor_error activate_ output_ toolbar activate_ watch activate_ variables activate_ registers activate_ memory activate_ call_stack adjust_block_ selection

A+1 A+2

cursor_error

cursor_error

cursor_error activate_ output_ toolbar

A+3 A+4 A+5 A+6 A+7 A+A A+B A+C A+E

activate_ watch activate_ variables activate_ registers activate_ memory activate_ call_stack

activate_ watch activate_ variables activate_ registers activate_ memory activate_ call_stack adjust_block_ selection select_block copy_to_ cursor end_select

activate_ watch activate_ variables activate_ registers activate_ memory activate_ call_stack adjust_block_ selection

copy_to_ cursor

copy_to_ cursor

410

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key A+F A+J A+K A+L A+M A+N A+O CUA SlickEdit
fill_ selection join_line cut select_line move_to_ cursor keyin_buf_name overlay_block_ selection reflow_ paragraph root_keydef split_line find_ matching_paren deselect copy_to_ clipboard cut_word safe_exit begin_select select_char function_ argument_help list_symbols function_ argument_help list_symbols safe_exit begin_select select_char function_ argument_help list_symbols safe_exit begin_select select_char function_ argument_help list_symbols deselect deselect root_keydef root_keydef keyin_buf_name keyin_buf_name join_line cut cut_sentence join_line cut cut_sentence

Visual C++ 6

Visual Studio

A+P A+R A+S A+T A+U A+V A+W A+X A+Y A+Z A+comma A+dot

continued

411

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key A+equals A+Backspace A+Down A+F1 A+F2 A+F3 A+F3,B A+F3,C A+F3,R A+F4 A+F5 A+F6 A+F7 A+F8 A+F9 A+F10 A+F12 CUA
execute_ selection undo next_paragraph api_index move_edge create_tile

SlickEdit
execute_ selection undo next_paragraph api_index move_edge create_tile

Visual C++ 6
execute_ selection undo next_paragraph api_index set_bookmark gui_find

Visual Studio
execute_ selection undo_cursor next_paragraph api_index

toggle_so_ backwards toggle_so_ matchcase toggle_so_ regex safe_exit restore_mdi delete_tile project_build project_ compile move_mdi size_mdi move_mdi prev_buffer project_edit format_ selection debug_ breakpoints maximize_mdi activate_tag_ properties_ toolbar mou_click_copy prev_word mou_click_copy prev_word mou_click_copy prev_word project_edit format_ selection debug_ breakpoints maximize_mdi find_tag safe_exit restore_mdi safe_exit restore_mdi

debug_ breakpoints maximize_mdi

debug_ breakpoints next_error

A+LButton-Down A+Left

mou_click_copy prev_word

412

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key A+Pad-star A+Right A+Up A+M+M A+M+V A+M+W A+S+A A+S+T A+S+Backspace A+S+Down A+S+Enter A+S+F2 A+S+Left A+S+Right A+S+Up C+A C+B C+C
activate_ bookmarks cua_select cua_select cua_select select_all cua_select cua_select cua_select cmdline_ toggle next_buffer cua_select cua_select cua_select select_all cua_select cua_select cua_select select_all cua_select cua_select cua_select

CUA
debug_show_ next_statement next_word

SlickEdit
debug_show_ next_statement next_word

Visual C++ 6
debug_show_ next_statement next_word

Visual Studio
debug_show_ next_statement codehelp_ complete prev_paragraph iconize_all

prev_paragraph iconize_all

prev_paragraph iconize_all

prev_paragraph iconize_all paste_replace_ word

close_all

close_all

close_all

close_all project_add_ file

transpose_ lines

transpose_ lines redo cua_select fullscreen

select_block

select_block

debug_toggle_ breakpoint copy_to_ clipboard

copy_to_ clipboard

stop_process

copy_to_ clipboard

continued

413

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+D CUA
gui_cd

SlickEdit
delete_char

Visual C++ 6
maybe_active_ search_hist_ list find_matching_ paren gui_find gui_goto gui_replace i_search prev_ condition next_condition

Visual Studio
maybe_active_ search_hist_ list find_matching_ paren gui_find gui_goto gui_replace i_search prev_ condition

C+E

cut_end_line

cut_end_line

C+F C+G C+H C+I C+J C+K C+K,C+C C+K,C+D C+K,C+F C+K,C+K C+K,C+L C+K,C+N C+K,C+P C+K,C+U C+K,C+W C+L C+M C+M,C+H

gui_find find_next hsplit_window i_search gui_goto_line

find_next abort push_tag cursor_up cursor_left

copy_word

cursor_down

comment beautify beautify_ selection toggle_ bookmark clear_ bookmarks next_bookmark prev_bookmark comment_erase activate_ bookmarks select_line project_build cursor_right project_build cut_line move_text_tab hide_selection cut_line

414

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+M,C+L C+M,C+M C+M,C+O C+M,C+P C+M,C+U C+N C+O C+P C+Q C+R C+R,C+R C+R,C+W CUA SlickEdit Visual C++ 6 Visual Studio
toggle_all_ outlining plusminus collapse_to_ definitions show_all show_ selection next_buffer gui_open prev_buffer quote_key gui_replace page_down end_line page_up quote_key record_macro_ toggle softwrap_ toggle view_ whitespace_ toggle save i_search record_macro_ end_execute deselect begin_line_ text_toggle prev_buffer next_window save function_ argument_help lowcase_ selection paste select_whole_ word cut start_ recording save transpose_ chars lowcase_ selection paste select_whole_ word cut new gui_open gui_print quote_key new gui_open gui_print quote_key

C+S C+T C+U C+V C+W C+X C+X,(

paste

cut

continued

415

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+X,) C+X,1 C+X,2 C+X,AZ C+X,B C+X,E C+X,K C+X,M C+X,N C+X,O C+X,R C+X,S C+X,Tab C+X,S+Tab C+X,C+B C+X,C+C C+X,C+D C+X,C+E C+X,C+F C+X,C+H C+X,C+J C+X,C+L CUA SlickEdit
end_recording one_window hsplit_window case_indirect find_buffer last_macro quit project_build set_next_error next_window redo split_line move_text_tab move_text_ backtab list_buffers safe_exit alias_cd dos gui_open pop_bookmark bottom_of_ buffer load

Visual C++ 6

Visual Studio

416

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+X,C+M C+X,C+N C+X,C+O C+X,C+P C+X,C+R C+X,C+S C+X,C+U C+X,C+W C+X,C+X C+X,C+Y C+X,C+Z C+Y C+Z C+comma C+dot C+slash C+[ C+backslash C+] C+equals C+Backspace
redo undo pop_bookmark push_tag push_ref next_hotspot plusminus find_matching_ paren diff cut_line

CUA

SlickEdit
start_process next_error insert_toggle reflow_ selection reverse_i_ search save top_of_buffer copy_word nothing list_ clipboards resume paste zoom_window pop_bookmark push_tag push_ref next_hotspot plusminus find_matching_ paren diff cut_line

Visual C++ 6

Visual Studio

redo undo pop_bookmark push_tag push_ref next_hotspot plusminus find_matching_ paren diff delete_prev_ word

redo undo_cursor pop_bookmark push_tag push_ref next_hotspot plusminus find_matching_ paren diff delete_prev_ word

continued

417

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+Break C+Del C+Down C+End C+Enter
cut_code_block cut_code_block

CUA

SlickEdit

Visual C++ 6
stop_process delete_word

Visual Studio
stop_process delete_word

next_tag bottom_of_ buffer nosplit_ insert_line

next_tag bottom_of_ buffer nosplit_ insert_line

scroll_down bottom_of_ buffer nosplit_ insert_line

scroll_down bottom_of_ buffer insert_ blankline_ above wh

C+F1 C+F2 C+F3 C+F4 C+F5 C+F6 C+F7 C+F8 C+F9

wh wh2

upcase_word lowcase_word

wh toggle_ bookmark quick_search

upcase_ selection close_window lowcase_ selection project_ execute project_ compile move_window

quick_search

close_window

close_window

project_ execute next_window

project_ execute next_window

project_ execute next_window

move_window

project_ compile select_line debug_toggle_ breakpoint_ enabled debug_run_to_ cursor

project_ compile select_line debug_toggle_ breakpoint_ enabled debug_run_to_ cursor

size_window debug_toggle_ breakpoint_ enabled debug_run_to_ cursor record_macro_ toggle record_macro_ end_execute

prev_buffer undo_cursor

C+F10 C+F11 C+F12

debug_run_to_ cursor record_macro_ toggle record_macro_ end_execute

load

push_tag

418

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+Home C+Ins C+LButton-Down C+Left C+MButton-Down C+Pad-minus C+Pad-plus C+Pad-star C+PgDn C+PgUp C+RButton-Down C+Right C+Tab C+Up C+Wheel-Down C+Wheel-Up C+S+Del C+S+Down C+S+End C+S+Enter
bottom_of_ window top_of_window mou_move_to_ cursor next_word next_window prev_tag scroll_page_ down scroll_page_up unsurround next_error cua_select nosplit_ insert_line_ above bottom_of_ window top_of_window mou_move_to_ cursor next_word next_window prev_tag scroll_page_ down scroll_page_up unsurround next_error cua_select nosplit_ insert_line_ above

CUA
top_of_buffer copy_to_ clipboard mou_click_copy prev_word

SlickEdit
top_of_buffer copy_to_ clipboard mou_click_copy prev_word

Visual C++ 6
top_of_buffer copy_to_ clipboard mou_click_copy prev_word mou_select_ word find_prev find_next pop_bookmark bottom_of_ window top_of_window mou_move_to_ cursor next_word next_window scroll_up scroll_page_ down scroll_page_up unsurround next_error cua_select nosplit_ insert_line_ above

Visual Studio
top_of_buffer copy_to_ clipboard mou_click_copy prev_word mou_select_ word prev_doc

pop_bookmark bottom_of_ window top_of_window mou_move_to_ cursor next_word next_window scroll_up scroll_page_ down scroll_page_up unsurround next_error cua_select insert_ blankline_ below

continued

419

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+S+F1 C+S+F2 C+S+F3 C+S+F5 C+S+F6 C+S+F9
debug_restart prev_window debug_ clear_all_ breakpoints debug_restart prev_window debug_ clear_all_ breakpoints execute_last_ macro_key execute_last_ macro_key execute_last_ macro_key cua_select cua_select cua_select cua_select cua_select cua_select cua_select cua_select next_doc mou_copy_to_ cursor cua_select prev_window prev_error activate_autos activate_ breakpoints mou_copy_to_ cursor cua_select prev_window prev_error activate_autos activate_ breakpoints mou_copy_to_ cursor cua_select prev_window prev_error activate_autos activate_ breakpoints mou_copy_to_ cursor cua_select prev_window prev_error activate_build activate_ breakpoints

CUA

SlickEdit
cap_word cap_selection

Visual C++ 6

Visual Studio

clear_ bookmarks find_prev debug_restart prev_window debug_ clear_all_ breakpoints find_prev debug_restart prev_window debug_ clear_all_ breakpoints

C+S+F12,09 C+S+F12,AZ C+S+F12,F1F12 C+S+Home C+S+Left C+S+Pad-minus C+S+RButton-Down

C+S+Right C+S+Tab C+S+Up C+A+A C+A+B

420

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+A+C C+A+E C+A+G C+A+H C+A+J CUA
activate_ call_stack

SlickEdit
activate_ call_stack

Visual C++ 6
activate_ call_stack

Visual Studio
activate_ call_stack activate_ exceptions activate_ registers

activate_ threads

activate_ threads

activate_ threads

activate_ threads activate_ project_ classes

C+A+L C+A+M C+A+M,1 C+A+M,2 C+A+M,3 C+A+M,4 C+A+O C+A+Q C+A+R C+A+T C+A+V

activate_ locals activate_ members

activate_ locals activate_ members

activate_ locals activate_ members

activate_ project_files activate_ members activate_ memory activate_ memory activate_ memory activate_ memory activate_ output debug_add_ watch goto_url

list_symbols activate_ variables activate_ variables activate_ variables

list_symbols

continued

421

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+A+V,A C+A+V,L C+A+V,T C+A+W C+A+W,1 CUA SlickEdit Visual C++ 6 Visual Studio
activate_autos activate_ locals2 acticate_ members2 activate_watch activate_watch activate_watch activate_watch activate_ watch2 activate_ watch3 activate_ watch4

C+M+A C+M+B C+M+C C+M+H C+M+L C+M+M C+M+V C+M+W C+S+8

activate_autos activate_ breakpoints activate_ call_stack activate_ threads activate_ locals activate_ members activate_ variables activate_watch

activate_autos activate_ breakpoints activate_ call_stack activate_ threads activate_ locals activate_ members activate_ variables activate_watch

activate_autos activate_ breakpoints activate_ call_stack activate_ threads activate_ locals activate_ members activate_ variables activate_watch view_ specialchars_ toggle alt_ gtbookmark

activate_autos activate_ breakpoints activate_ call_stack activate_ threads activate_ locals activate_ members activate_ variables activate_watch view_ specialchars_ toggle alt_ gtbookmark

C+S+9

422

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+S+A C+S+B C+S+C C+S+D C+S+E C+S+F C+S+G C+S+H C+S+I C+S+J C+S+K C+S+L C+S+M C+S+N C+S+O C+S+P
list_buffers append_to_ clipboard javadoc_ editor list_errors list_buffers append_to_ clipboard javadoc_ editor list_errors

CUA

SlickEdit

Visual C++ 6
cap_selection list_buffers append_to_ clipboard javadoc_ editor select_ matching_brace

Visual Studio
cap_selection project_build append_to_ clipboard javadoc_ editor select_ matching_brace find_in_files

find_in_files find_prev hex

find_prev find_prev hex cursor_error hex

cursor_error replace_in_ files reverse_i_ search select_prev_ condition select_next_ condition delete_line

reverse_i_ search toggle_ bookmark cut_word

reverse_i_ search toggle_ bookmark cut_word

reverse_i_ search select_prev_ condition select_next_ condition delete_line

lowcase_ selection start_process activate_ bookmarks expand_alias expand_ extension_ alias replace_in_ files set_next_error

lowcase_ selection start_process activate_ bookmarks expand_alias expand_ extension_ alias

start_process next_window

start_process workspace_new

expand_alias record_macro_ end_execute

workspace_open record_macro_ end_execute

C+S+R C+S+S

record_macro_ toggle set_next_error set_next_error

record_macro_ toggle save_all

continued

423

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key C+S+T C+S+T,09 C+S+T,AZ C+S+T,F1F12 C+S+U C+S+V C+S+W C+S+X C+S+Y C+S+Z C+S+comma C+S+dot C+S+[ C+S+] M+0 CUA SlickEdit Visual C++ 6
transpose_ words execute_last_ macro_key execute_last_ macro_key execute_last_ macro_key upcase_ selection list_ clipboards prev_window append_cut upcase_ selection list_ clipboards prev_window append_cut paste_ replace_word zoom_window complete_prev complete_next prev_hotspot zoom_window complete_prev complete_next prev_hotspot redo complete_prev complete_next prev_hotspot redo complete_prev complete_next prev_hotspot find_ matching_paren activate_ project_ toolbar cursor_error cursor_error cursor_error activate_ output_ toolbar activate_watch activate_watch activate_watch activate_watch cursor_error upcase_ selection list_ clipboards html_preview append_cut upcase_ selection list_ clipboards prev_window append_cut

Visual Studio
transpose_ words

M+1 M+2

M+3

424

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key M+4 M+5 M+6 M+7 M+A M+B M+C M+E M+F M+G M+J M+K M+L M+M M+N M+O
iconize_ window new gui_open copy_to_ clipboard set_find gui_find

CUA
activate_ variables activate_ registers activate_ memory activate_ call_stack select_all

SlickEdit
activate_ variables activate_ registers activate_ memory activate_ call_stack adjust_block_ selection select_block copy_to_ cursor end_select fill_ selection

Visual C++ 6
activate_ variables activate_ registers activate_ memory activate_ call_stack select_all

Visual Studio
activate_ variables activate_ registers activate_ memory activate_ call_stack select_all

copy_to_ clipboard set_find gui_find

copy_to_ clipboard set_find gui_find

find_next join_line cut select_line move_to_ cursor keyin_buf_name overlay_block_ selection reflow_ paragraph

find_next

find_next

iconize_ window new gui_open

iconize_ window new gui_open

M+P M+Q

gui_print

gui_print

gui_print

safe_exit

safe_exit

safe_exit

continued

425

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key M+R M+S M+T
save macos_font_ config

CUA

SlickEdit
root_keydef split_line find_matching_ paren deselect

Visual C++ 6

Visual Studio

save macos_font_ config

save macos_font_ config

M+U M+V M+W M+X M+Y M+Z M+comma M+dot M+equals M+Backspace M+Down M+F1 M+F2 M+F3 M+F4 M+F5
bottom_of_ buffer api_index move_edge create_tile safe_exit restore_mdi undo function_ argument_help list_symbols execute_ selection paste

copy_to_ clipboard cut_word safe_exit begin_select select_char function_ argument_help list_symbols execute_ selection undo bottom_of_ buffer api_index move_edge create_tile delete_tile project_build

paste

paste

close_window cut

close_window cut

close_window cut

undo function_ argument_help list_symbols execute_ selection undo bottom_of_ buffer api_index set_bookmark gui_find safe_exit restore_mdi

undo function_ argument_help list_symbols execute_ selection

bottom_of_ buffer api_index move_edge create_tile safe_exit restore_mdi

426

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key M+F6 M+F7 M+F8 M+F9 M+F10 M+F12 CUA SlickEdit
project_ compile move_mdi size_mdi move_mdi prev_buffer project_edit format_ selection debug_ breakpoints maximize_mdi activate_tag_ properties_ toolbar begin_line debug_show_ next_statement end_line top_of_buffer undo_cursor begin_line debug_show_ next_statement end_line top_of_buffer undo_cursor begin_line debug_show_ next_statement end_line top_of_buffer linewrap_ rubout cut cua_select cua_select keyin_enter begin_line debug_show_ next_statement end_line top_of_buffer undo_cursor move_mdi size_mdi

Visual C++ 6

Visual Studio

debug_ breakpoints maximize_mdi

debug_ breakpoints next_error

debug_ breakpoints maximize_mdi

M+Left M+Pad-star M+Right M+Up S+Backspace S+Del S+Down S+End S+Enter S+F1 S+F2 S+F3 S+F4 S+F5

cut cua_select cua_select keyin_enter

cut cua_select cua_select keyin_enter scroll_up scroll_down scroll_left scroll_right

cut cua_select cua_select keyin_enter

prev_bookmark find_prev prev_error debug_stop find_prev prev_error debug_stop

debug_stop

debug_stop

continued

427

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key S+F6 S+F7 S+F8 CUA
resync shift_ selection_left shift_ selection_ right undo_cursor project_ compile debug_step_out save cua_select paste mou_extend_ selection cua_select cua_select cua_select cua_select move_text_ backtab cua_select macos_show_ colors find_prev save_as close_buffer redo

SlickEdit
resync shift_ selection_left shift_ selection_ right redo project_ compile debug_step_out save cua_select paste mou_extend_ selection cua_select cua_select cua_select cua_select cbacktab

Visual C++ 6
resync shift_ selection_left shift_ selection_ right undo_cursor project_ compile debug_step_out push_ref cua_select paste mou_extend_ selection cua_select cua_select cua_select cua_select cbacktab

Visual Studio
resync shift_ selection_left prev_error

S+F9 S+F10 S+F11 S+F12 S+Home S+Ins S+LButton-Down S+Left S+PgDn S+PgUp S+Right S+Tab S+Up S+M+C S+M+G S+M+S S+M+W S+M+Z

undo_cursor project_ compile debug_step_out push_ref cua_select paste mou_extend_ selection cua_select cua_select cua_select cua_select cbacktab

cua_select macos_show_ colors find_prev save_as close_buffer

cua_select macos_show_ colors find_prev save_as close_buffer redo

cua_select macos_show_ colors find_prev save_as close_buffer redo

428

Appendix A: Settings for Different Emulations


Table A-11 (continued)
Key S+M+/ S+M+Down S+M+End S+M+Home S+M+Left S+M+Right S+M+Up CUA
help cua_select cua_select cua_select cua_select cua_select cua_select

SlickEdit
help cua_select cua_select cua_select cua_select cua_select cua_select

Visual C++ 6
help cua_select cua_select cua_select cua_select cua_select cua_select

Visual Studio
help cua_select cua_select cua_select cua_select cua_select cua_select

Macro Variable Settings


Table A-12 lists macro variable settings for the different emulations.

Table A-12
Variable
def_advanced_ select def_alt_menu def_brief_word def_buflist def_click_past_ end def_cursor_ beginend_select def_cursorwrap def_deselect_copy def_deselect_ paste

CUA P 1 0 3 0

SlickEdit P 0 0 3 1

Visual C++ 6 P 1 0 3 0 1

Visual Studio P 1 0 3 0 1 1 0 1

1 1 1

0 1 0

1 1 1

continued

429

Appendix A: Settings for Different Emulations


Table A-12 (continued)
Variable
def_from_cursor def_gui def_hack_tabs def_ispf_flags def_jmp_on_tab def_keys def_leave_ selected def_line_insert def_linewrap def_list_binary_ files def_modal_tab def_next_word_ style def_one_file def_persistent_ select def_preplace def_process_tab_ output def_pull def_restore_ cursor def_scursor_style def_select_style def_switchbuf_cd

CUA 0 1 0 0 1 windows-keys 1 A 1 true 1 E +w D 1 1 1 1 0 CN false

SlickEdit 0 1 0 0 1 0 A 0 true 0 E Y 1 1 1 0 0 EI false

Visual C++ 6 0 1 0 0 1 vcpp-keys 1 B 0 true 1 B +w D 1 1 1 1 0 CN false

Visual Studio 0 1 0 0 1 vsnet-keys 1 B 0 true 1 B +w D 1 1 1 1 0 CN false

430

Appendix A: Settings for Different Emulations


Table A-12 (continued)
Variable
def_top_bottom_ style def_updown_col def_updown_ screen_lines def_vcpp_bookmark def_vcpp_word def_word_continue def_word_delim

CUA 0 1 true 0 0 false 0

SlickEdit 0 0 true 0 0 false 0

Visual C++ 6 0 1 true 1 1 false 0

Visual Studio 0 1 true 1 1 false 0

WROX Emulation Key Commands


Table A-13 lists the key bindings defined in the WROX emulation, and in other macros presented in this book. These bindings are defined on top of the CUA emulation.

Table A-13
Key Alt+A Alt+B Alt+C Alt+D Alt+E Alt+F Alt+J Alt+L Alt+M Alt+N WROX
adjust-block-selection select-block copy-to-cursor cut end-select fill-selection join-line select-line move-to-cursor keyin-buf-name

continued

431

Appendix A: Settings for Different Emulations


Table A-13 (continued)
Key Alt+O Alt+P Alt+Q Alt+Shift+Q Alt+R Alt+S Alt+U Alt+V Alt+W Alt+X Alt+Y Alt+Z Alt+quote Ctrl+semicolon Ctrl+F3 Ctrl+Shift+F2 Shift+F1 Shift+F2 Shift+F3 Shift+F4 Tab Shift+Tab Ctrl+Shift+0 Ctrl+Shift+9 Ctrl+0 Ctrl+9 WROX
overlay-block-selection reflow-paragraph what-is where-is root-keydef split-line deselect copy-to-clipboard cut-word safe-exit begin-select select-char duplicate-line push-bookmark quick-search quick-reverse-search scroll-up scroll-down scroll-left scroll-right ctab cbacktab alt-bookmark

alt-gtbookmark

432

Appendix A: Settings for Different Emulations


Table A-13 (continued)
Key Alt+Home Alt+PgUp Alt+PgDn Alt+T,K Alt+T,B Alt+T,A Alt+T,C Alt+T,D Alt+T,H Alt+T,L Alt+T,P Alt+T,W Alt+T,F Alt+T,T Alt+T,O Alt+T,U Alt+T,V Alt+T,J Alt+T,R Alt+T,X Alt+T,S Alt+T,Y F5 Alt+Shift+A WROX
center-line line-to-top line-to-bottom activate-bookmarks activate-build activate-call-stack activate-tbclass activate-defs activate-deltasave activate-files-files activate-files-project activate-files-workspace activate-find-symbol activate-ftp activate-open activate-output activate-preview activate-projects activate-references activate-regex-evaluator activate-search activate-symbols-browser config wrox-make-anchor (Chapter 1)

continued

433

Appendix A: Settings for Different Emulations


Table A-13 (continued)
Key Alt+Left Ctrl+Left Alt+Right Ctrl+Right Ctrl+Shift+slash Alt+Enter Alt+Shift+L Alt+Shift+R Alt+Shift+equals Alt+slash Alt+Up Alt+Down Tab Shift+Tab Shift+F10 Ctrl+W PgDn Alt+J WROX
prev-word wrox-prev-whitespace-word (Chapter 6) next-word wrox-next-whitespace-word (Chapter 6) wrox-toggle-comment (Chapter 9) wrox-start-of-next-line (Chapter 10) wrox-align-left-with-field-above (Chapter 10) wrox-align-right-with-field-above (Chapter 10) wrox-execute-current-command (Chapter 16) wrox-insert-html-ending-tag (Chapter 16) wrox-move-line-up (Chapter 16) wrox-move-line-down (Chapter 16) wrox-tab-matchtabs (Chapter 17) wrox-backtab-matchtabs (Chapter 17) wrox-show-context-menu (Chapter 17) wrox-show-wrox-popup-menu (Chapter 17) wrox-page-down-realign (Chapter 17) wrox-join-line-with-space (Chapter 17)

434

Regular Expression Syntax


Table B-1 shows the complete syntax for regular expression features in the three variants supported by SlickEdit. Chapter 7 contains a shorter version of this table. Chapter 7 also contains explanations for some of the items in this table.

Table B-1
Definition Match beginning of line. Match end of line. Match any character except newline. Maximal match of zero or more occurrences of X. Maximal match of one or more occurrences of X. Maximal match of zero or one occurrences of X. Match exactly n1 occurrences of X. Maximal match of at least n1 occurrences of X. Maximal match of at least 0 occurrences but not more than n2 occurrences of X. UNIX
^

SlickEdit
^

Brief
% < $ > ? X\:@ X\:+ X\:0,1 X\:n1 X\:n1? X\:n1, X\:,n2

. X* X+ X? X{n1} X{n1}? X{n1,} X{,n2}

? X@ X# X:0,1 X:n1

X:n1, X:0,n2

continued

Appendix B: Regular Expression Syntax


Table B-1 (continued)
Definition Maximal match of at least n1 occurrences but not more than n2 occurrences of X. Maximal match of zero or more of any character except newline. Minimal match of zero or more occurrences of X. Minimal match of one or more occurrences of X. Minimal match of zero or one occurrences of X. Minimal match of at least n1 occurrences of X. Minimal match of at least 0 occurrences but not more than n2 occurrences of X. Minimal match of at least n1 occurrences but not more than n2 occurrences of X. Minimal match of zero or more of any character except newline. Search fails if expression X is matched. Matches X or Y. Matches subexpression X but does not define a tagged expression. Matches subexpression X and specifies a new tagged expression. No more tagged expressions are defined once an explicit tagged expression number is specified as shown below. See Chapter 7. Matches subexpression X and specifies to use tagged expression number d, where 0 d 9. No more tagged expressions are defined by the subexpression syntax (X) once this subexpression syntax is used. Matches any one of the characters specified by charset. A hyphen (-) character may be used to specify ranges. Matches any character not specified by charset. A hyphen (-) character may be used to specify ranges. UNIX
X{n1,n2}

SlickEdit
X:n1,n2

Brief
X\:n1,n2

.*

?@

X\:*

X*? X+? X?? X{n1,}? X{,n2}?

X* X+ X:*0,1 X:*n1, X:*0,n2

X\:0,? X+ X\:0,1? X\:n1,? X\:,n2?

X{n1,n2}?

X:*n1,n2

X\:n1,n2?

.*?

?*

(?!X) X|Y (?:X)

~X X|Y (X) X|Y \(X\)

(X)

{X}

{X}

(?dX)

{#dX}

{@dX}

[charset]

[charset]

[charset]

[^charset]

[~charset] [^charset]

[~charset]

436

Appendix B: Regular Expression Syntax


Table B-1 (continued)
Definition Character set subtraction. Matches all characters in charset1 except the characters in charset2. Character set intersection. Matches all characters in charset1 that are also in charset2. Matches up to 31-bit Unicode hexadecimal character specified by hhhh. (Only valid in character set) Matches characters in UnicodeCategorySpec, where UnicodeCategorySpec uses the standard general categories specified by the Unicode Consortium. (Only valid in character set) Matches characters not in UnicodeCategorySpec. (Only valid in character set) Matches characters in UnicodeIsBlockSpec, where UnicodeIsBlockSpec is one of the standard character blocks specified by the Unicode Consortium. (Only valid in character set) Matches characters not in UnicodeIsBlockSpec. Matches hexadecimal character hh, where 0 hh 0xff. Matches decimal character nnn, where 0 nnn 255. Defines a back reference to tagged expression number d. See Chapter 7. Specifies cursor position if match is found. See Chapter 7. Matches newline character sequence. Useful for matching multiline search strings. What this matches depends on whether the buffer is a DOS (ASCII 13,10 or just ASCII 10), UNIX (ASCII 10), Macintosh (ASCII 13), or userdefined ASCII file. UNIX
[charset1[charset2]]

SlickEdit
[charset1[charset2]]

Brief
[charset1[charset2]]

[charset1& [charset2]] \x{hhhh}

[charset1& [charset2]] \x{hhhh}

[charset1& [charset2]] \x{hhhh}

\p{Unicode CategorySpec]

\p{Unicode CategorySpec]

\p{Unicode CategorySpec]

\P{Unicode CategorySpec] \p{UnicodeIs BlockSpec]

\P{Unicode CategorySpec] \p{UnicodeIs BlockSpec]

\P{Unicode CategorySpec] \p{UnicodeIs BlockSpec]

\P{UnicodeIs BlockSpec]

\P{UnicodeIs BlockSpec]

\P{UnicodeIs BlockSpec]

\xhh

\xhh

\xhh

\dnnn

\nnn

\dnnn

\d

\gd

\d

\c

\c

\c

\n

\n

\n

continued

437

Appendix B: Regular Expression Syntax


Table B-1 (continued)
Definition Matches carriage return (ASCII 13). Matches tab character. Matches backspace character. Matches form feed character. Matches any 2-byte DBCS character. This escape is only valid in a match set ([...\od...]). [^\od] matches any single byte character excluding end-of-line characters. When used to search Unicode text, this escape does nothing. Turns on multiline matching. This enhances the match character set, or matches any character primitives to support matching end-of-line characters. For example, \om.+ matches the rest of the buffer. Turns off multiline matching (default). You can still use \n to create regular expressions that match one or more lines. However, expressions like .+ will not match multiple lines. This is much safer and usually faster than using the \om option. Declares character after slash to be literal. Matches predefined expression corresponding to char. See Table B-2.
\f \od

UNIX
\r \t

SlickEdit
\r \t \b \f \od

Brief
\r \t \b \f \od

\om

\om

\om

\ol

\ol

\ol

\char \:char

\char :char

\char \:char

Predefined Expressions
Table B-2 lists the predefined expressions that can be used in the special regular expression escape sequence \:char (or :char with SlickEdit regexes). This table also appears in Chapter 7.

Table B-2
Description Matches an alphanumeric character. Matches an alphabetic character. Character A C

438

Appendix B: Regular Expression Syntax


Table B-2 (continued)
Description Matches blanks. Matches a digit. Matches a filename part. Matches a hex number Matches an integer. Matches a floating number. Matches a path. Matches a quoted string. Matches a C variable. Matches a word. Character B D F H I N P Q V W

439

SlickEdit Callbacks
Table C-1 lists the complete set of SlickEdit callbacks at the time of writing. Callbacks are covered in detail in Chapter 16. The list of callbacks here was generated using the macro presented in that chapter. You can use the macro to get an up-to-date list, or adapt it for your own needs.

Table C-1
Name
_actapp_

Event Application activated (such as getting focus). Before writing state file. New buffer opened.

Arguments Whether getting focus.

_b4wrst_ _buffer_add_

Buffer ID, buffer name, buffer flags. Buffer ID, buffer name, new name, buffer flags.

_buffer_renamed_

Before buffer renamed.

_cbmdibufferhidden_

MDI buffer hidden. continued

Appendix C: SlickEdit Callbacks


Table C-1 (continued)
Name
_cbmdibuffer_unhidden_

Event MDI buffer unhidden. Some windows are marked KEEP_ ON_QUIT, which means they are never quit, even when the user explicitly quits them. An example of this would be the Find Results window. If a user manages to pull the Find Results into an editor window, quitting it will simply hide the buffer, because it gets reused by the Find dialog. Before file closed.

Arguments

_cbquit_

Buffer ID, buffer name, filename, buffer flags. Buffer ID, buffer name, filename, buffer flags.

_cbquit2_

After file closed.

_cbsave_ _cbstop_process_ _cd_ _diffOnExit_ _diffOnStart_ _document_renamed_

File saved. Stopping build. Directory changed. End of DIFFzilla operation. Start of DIFFzilla operation. Filename or buffer name changed. Key bound. FTP busy. FTP idle. Color coding lexer changed. Lexer name as stored in .vlx file. Buffer ID, old name, new name, buffer flags. Key binding table, key. New directory.

_eventtab_modify_ _ftpQBusy_ _ftpQIdle_ _lexer_updated_

_lostfocus_ _MenuAddFileHist_

Lost focus. Adding filename to File History on File Menu. Adding workspace filename to Project History on Project Menu. Filename.

_MenuAddWorkspaceHist_

Filename.

442

Appendix C: SlickEdit Callbacks


Table C-1 (continued)
Name
_on_load_module_ _on_popup_

Event Before loading module. Before an editor window popup/context menu is displayed. Before any pop-up menu is displayed. Before unloading module. Build completed. Build about to start. Called after _project_name is set to blank, when closing project. Active project configuration changed. Project properties edited. Opening project. Project saved. File added to project. Only called when another tool or tool window adds a file to a project (e.g., the Project tool window, Add Files). Save/restore. Save/restore global. Switching buffer.

Arguments Module name. Menu name, menu handle.

_on_popup2_

Menu name, menu handle.

_on_unload_module_ _postbuild_ _prebuild_ _prjclose_

Module name. Build arguments. Build arg.

_prjconfig_

_prjedit_ _prjopen_ _prjupdate_ _project_file_add_

Handle to open project.

Project name, filename.

_sr_ _srg_ _switchbuf_

Old buffer name, option, old pos, old buffer ID.

_vi_switchmode_ _wkspace_close_ _workspace_file_add_ _workspace_open_ _workspace_opened_

Switching mode in vi emulation. Closing workspace. File added to workspace. Before workspace opened. After workspace opened. Project name, filename. Workspace filename.

443

Whats on the CD-ROM


This appendix provides you with information on the contents of the CD that accompanies this book. For the latest and greatest information, please refer to the ReadMe file located at the root of the CD. Here is what you will find: System Requirements. Using the CD with Windows, Linux, UNIX, and Macintosh. Whats on the CD. Troubleshooting.

System Requirements
Make sure that your computer meets the minimum system requirements listed in this section. If your computer doesnt match up to most of these requirements, you may have a problem using the contents of the CD. For Windows Vista, Windows 2000, Windows NT4 (with SP 4 or later), or Windows XP: At least 256 MB of total RAM installed on your computer. 170 MB disk space. A CD-ROM drive.

For Linux kernel 2.6 and compliance with LSB 3.1 or later: At least 256 MB of total RAM installed on your computer. 200 MB disk space. A CD-ROM drive.

Appendix D: Whats on the CD-ROM


For AIX 5 and later: At least 256 MB of total RAM installed on your computer. 250 MB disk space. A CD-ROM drive.

For HP-UX 11 and later: At least 256 MB of total RAM installed on your computer. 270 MB disk space. A CD-ROM drive.

For IRIX 6.5 and later: At least 256 MB of total RAM installed on your computer. 280 MB disk space. A CD-ROM drive.

For Solaric SPARC 7 and later: At least 256 MB of total RAM installed on your computer. 240 MB disk space. A CD-ROM drive.

For Solaris x86: At least 256 MB of total RAM installed on your computer. 240 MB disk space. A CD-ROM drive.

For Macintosh OS X v10.4: At least 256 MB of total RAM installed on your computer. 190 MB disk space. A CD-ROM drive. X11 for Mac OS X.

446

Appendix D: Whats on the CD-ROM

Using the CD with Windows


To access the content from the CD, follow these steps:

1.

Insert the CD into your computers CD-ROM drive. The license agreement appears.

The interface wont launch if you have autorun disabled. In that case, click Start >Run (For Windows Vista, Start >All Programs >Accessories >Run). In the dialog box that appears, type D:\Start.exe. (Replace D with the proper letter if your CD drive uses a different letter. If you dont know the letter, see how your CD drive is listed under My Computer.) Click OK.

2. 3.

Read through the license agreement, and then click the Accept button if you want to use the CD. The CD interface appears. The interface allows you to install the programs and run the demos with just a click of a button (or two).

Using the CD with Linux and UNIX


To install the items from the CD to your hard drive, follow these steps:

1. 2. 3.

Log in as root. Insert the CD into your computers CD-ROM drive. If your computer has Auto-Mount enabled, wait for the CD to mount. Otherwise, follow these steps:

a.

Command-line instructions: At the command prompt, type:

mount /dev/cdrom /mnt/cdrom. (This mounts the cdrom device to the mnt/cdrom directory. If your device has a different name, change cdrom to that device name e.g., cdrom1.) To prevent filename casing issues on HP-UX, use the -o cdcase option when mounting.

b. 4.

Graphical: Right-click on the CD-ROM icon on the desktop, and choose Mount CD-ROM. This mounts your CD-ROM.

At an xterm or full-screen prompt, change to the applicable UNIX platform directory on the CD-ROM (where <cdrom> is your CD-ROM mount point):
AIX <cdrom>/SlickEdit/aix/RS6000. HP-UX <cdrom>/SlickEdit/hpux/hp9000. IRIX <cdrom>/SlickEdit/irix. Linux <cdrom>/SlickEdit/linux/x86.

447

Appendix D: Whats on the CD-ROM



Solaris Sparc <cdrom>/SlickEdit/solaris/sparc.

Solaris x86 <cdrom>/SlickEdit/solaris/x86.

5. 6.

Start the installation at the prompt: ./vsinst. To remove the CD from your CD-ROM drive, follow these steps:

a. b.

Command line instructions: At the command prompt, type:

umount /mnt/cdrom. Graphical: Right-click on the CD-ROM icon on the desktop, and choose UMount CD-ROM. This mounts your CD-ROM.

Using the CD with the Mac OS


To install the items from the CD to your hard drive, follow these steps:

1. 2. 3. 4. 5.

Ensure that X11 is fully installed on your system (see the Note below). Insert the CD into your CD-ROM drive. Browse to the SlickEdit/mac folder on the product CD. Double-click slickedit.dmg. A disk image is mounted, with Finder displaying the contents. Double-click slickedit.pkg, and the installation process begins.

The default installation path is /Applications. After installing SlickEdit, if you want to use SlickEdit keyboard shortcuts instead of X11 shortcuts, you will need to disable X11 keyboard shortcuts. See Mac OS X in the Help system for instructions. SlickEdit runs as an X11 application; thus X11 must be installed prior to installing SlickEdit. To check if X11 is installed, select Finder Applications Utilities. A file named X11.app should exist at this location. Otherwise, you will need to install X11 from your OS X installation CD: 1. Using installation disk 1, run the Optional Installs.mpkg utility. 2. At the Install Type phase, expand the Applications tree, and select X11. 3. Continue with the X11 installation.

Whats on the CD
The following sections provide a summary of the software and other materials youll find on the CD.

Author-Created Materials
All author-created materials from the book, including code listings and samples, are on the CD in the folder named Author.

448

Appendix D: Whats on the CD-ROM

Applications
The CD also contains a 30-day trial version of SlickEdit 2007 for Windows, Linux, UNIX, and Mac OS X. Installation instructions for each platform are given above. When you run SlickEdit for the first time, you will be prompted to request a trial license. Click the Launch Browser button to open the SlickEdit Trial Registration Web page. Fill in the requested information, and click the I Agree button. The trial license key will be e-mailed to the address you specified. When it arrives, paste it into the text area under Step 2 on the Request a Trial License dialog. Click the Activate button, and SlickEdit is ready to use. Shareware programs are fully functional, trial versions of copyrighted programs. If you like particular programs, register with their authors for a nominal fee and receive licenses, enhanced versions, and technical support. Freeware programs are copyrighted games, applications, and utilities that are free for personal use. Unlike shareware, these programs do not require a fee or provide technical support. GNU software is governed by its own license, which is included inside the folder of the GNU product. See the GNU license for more details. Trial, demo, or evaluation versions are usually limited either by time or functionality (such as being unable to save projects). Some trial versions are very sensitive to system date changes. If you alter your computers date, the programs will time out and will no longer be functional.

Troubleshooting
If you have difficulty installing or using any of the materials on the companion CD, try the following solutions: Turn off any anti-virus software that you may have running Installers sometimes mimic virus activity and can make your computer incorrectly believe that it is being infected by a virus. (Be sure to turn the anti-virus software back on later.) Close all running programs The more programs youre running, the less memory is available to other programs. Installers also typically update files and programs; if you keep other programs running, installation may not work properly. Reference the ReadMe Please refer to the ReadMe file located at the root of the CD-ROM for the latest product information at the time of publication.

Customer Care
If you have trouble with the CD-ROM, please call the Wiley Product Technical Support phone number at (800) 762-2974. Outside the United States, call 1 (317) 572-3994. You can also contact Wiley Product Technical Support at http://support.wiley.com. John Wiley & Sons will provide technical support only for installation and other general quality-control items. For technical support on the applications themselves, consult the programs vendor or author. To place additional orders or to request information about other Wiley products, please call (877) 762-2974.

449

Index
A
activate-bookmark, 128 activate-build, 283 activate-files-files, 127 activate-files-project, 118 Active Project, 44 add, 206207 Add Jar File, 63 Add Source Files dialog, 52 Add Tag File dialog, 91, 93, 99, 103 Add Tags Database dialog, 99, 103 Add Tree dialog, 45, 52, 91, 92, 99, 100, 103 Add Wildcard, 45, 52, 94, 95 adjust-block-selection, 201 AdoTemplate, 103 aliases, 229240 in code, use of, 232234 and configuration directory, 31, 240, 381 defining, macro for, 381 directory aliases, 232 dynamic directory aliases, 234235 escape sequences, 233234 extension-specific aliases, 235236 file aliases, 230232 file and directory, to open files, 116117 file extension for, 240 functions of, 229230 global aliases, 230, 231 with macros, 233234 with parameters, 239240 surround-with aliases, 238 syntax expansion with, 237238 aligning data. See data alignment all/expr[/options], 141 allnot/expr[/options], 141 *.als, configuration directory, 31, 240 alt-bookmark, 128, 129 alt-gtbookmark, 128, 129 Alt key combinations, menu access with, 21 key binding commands, 12 animation, tool windows, 40 Ant Java project, management with, 65 project file, example, 65 appearance, 2425 current line, box around, 24 current line highlighting, 24 fonts, 2526 left margin size, 25 line behavior, 2629 special characters, display of, 25 Top of file line, 25 vertical line column, 24 window, first, maximize, 24 append append-cut, 154 append-to-clipboard, 154 to clipboard, 155 arguments auto-complete, 1011 callbacks, listing of, 441443 command arguments, 328330 and commands, 10 Slick-C, 318, 327330 variable arguments, 327 arrays, in Slick-C, 320321 ASCII file, byte offset 124 assertions, functions of, 307308 auto-complete, 186190 command-line arguments, 1011 compared to word completion, 190

Index

auto-complete (continued)
auto-complete (continued) configuring, 189190 in programming, 188189 timeout, default, 186 compared to word completion, 186188 auto-hide docking groups, 36 pin icon for, 36 auto-list compatible, Context Tagging problems, 111112 Auto-List Members, troubleshooting, 107, 109 Auto-Parameter, troubleshooting, 107, 109 Auto-Tag, 75, 96 auto-updated tag databases converting from global tag database, 93 functions of, 89, 90 refresh of, 90, 93 separate workspace for, 9495, 100102 and shared tag database, 90, 9394 auto-updated tag files contents of, 89 use of, 93 auto-validation, XML, 257 block comments. See multiline comments block editing, 208213 block insert mode, 211212 pros/cons of, 209 XML data, creating from test file 209213 block insert mode block editing example, 211212 columns, entering data, 203204 implementing, 204 and macros, 204 block selections, 159160, 200201 copying, 201 deleting, 201 moving, 200 navigating, 202 overwriting, 201202 sorting within, 204 blocks of code color, changing, 176 deleting, 184185 bookmarks, 127130 Bookmarks tool window, activating, 39 configuring, 129130 named bookmarks, 128129 pushed bookmarks, 83, 127128 bottom-of-buffer, 120, 121, 202 bottom-of-window, 120 branches Concurrent Version System (CVS), 282283 release branch, creating, 282283, 290 Subversion, 290291 Brief regular expressions, 137139 syntax, listing of, 435438 buffer(s) block selections, 202 buffer-to-window, associating, 34 defined, 7 moving between, 35 names of, 7 navigation among, commands, 125127 navigation in, commands, 120123 one file per window setting, 34 ring, creating, 125126 Slick-C interaction with, 337

B
backspace hack tabs, 28 pull chars, 28 settings, 2829 tabs, converting to spaces, 28 backup(s), configuration settings, 31, 379 Backup History tool window activating, 39 viewing with DIFFzilla, 269270 bash shell, 96 batch macros invoking, 311 See also Slick-C macros begin-select, 156, 161, 202 bin alias, 232 binary files, display of, 254 binary search, 144 Bitstream Vera, 26

452

Slick-C temporary buffers, 340341 sorting, 204 use of term, 7 bugs detection. See debug; unit tests build dependency, projects, 44 build systems GNU C/C++ project, 60 Java project, 6162 options, 51, 60 Build tool window activating, 39 building project, 5253 functions of, 9 builtins.e, 343 byte offset navigation to, commands, 124 Byte Order Mark (BOM), 124, 255

C
C# global tag database for, 104 indentation, 179 cache, Tag files cache size, 111 calculations, 206207 invoice, example, 206207 callbacks callback traces, example macro, 353354 events, listing of, 344345 invoking, 345 listing of, 441443 Slick-C, 343346 capturing groups. See tagged expressions case command-line search, 143 Match case search, 134 selection, 156, 162 toggle for, 133 C/C++ c-mode, 174 compiler definition, creating, 9698 file extensions, 173 global tag database with header files for, 9293 header files. See C/C++header files indentation, 178179

JavaDoc comments, 195 pointer style, choosing, 178 Preprocessing options, 105, 179 preprocessor, tagging difficulties, 104105, 107108 proprocessing definitions, adding, 107108 Visual C++. See Visual C++6 C/C++header files C/C++, global tag database with, 9293 extensionless, configure in library, 108109, 175 Extensionless C++ Files dialog, 108 navigation to, 119 CD-ROM, 445449 applications on, 449 system requirements, 445448 troubleshooting, 449 center-line, 123 c/exp1/exp2[/options], 141142 character offset, showing in message line, 124 character selection, 155, 157158 Choose Include Directory dialog, 98 classpath, Java project, 63 Class tool window activating, 39 use of, 8687 clear-bookmarks, 128 clipboard, 153155 append to, 155 commands, listing of, 154 moving and copying, 154 multiple, 154 selections, 153 CMD shell, path, specifying, 96 code blocks. See blocks of code coding styles, 177 omitting, comments, 192 code editing, 173197 auto-complete, 186190 color syntax highlighting, 175177 comments, 192196 control structures, 180185 embedded languages, 190192 indentation, 177180

453

Index

code editing

code editing (continued)


code editing (continued) SlickEdit in-memory representations, 255 syntax assistance, suppressing, 185 See also Context Tagging color syntax, search with, 144 color syntax highlighting, 173, 175177, 366367 Color Coding Setup dialog settings, 176177 color schemes, 176 Groovy, 368370 lexer settings, 174 program elements, 175176 screen elements, 176 search of, 135 columns, 202204 block editing, 208213 enter data, block insert mode, 203204 filling data, 203 navigation to, commands, 124 command(s), 192196 and arguments, 1011 basic functions, 9 binding to keys, 1114 color, changing, 176 command arguments, 328330 command keys, 392407 hyphens versus underscores in, 9, 328 invoking, 10 key commands, listing of, 408429 Slick-C, 11, 328330, 332 SlickEdit, 11 command keys debugging, 392394 editing, 394398 file, 398399 macro, 399 navigation, 402404 project, 405 search, 405406 toolbar, 406 window, 407 command-line, 1011 commands, types entered on, 11 dos commands, use of, 11 history on, 11 message area as, 8 operating system, 11 search and replace 141146 selective display, 149 toggle to edit buffer, 10 comments functions of, 192 JavaDoc comments, 195 line comments, 192194 multiline comments, 192, 194 settings, 195196 commit sets, 279282, 285 adding files to, 281282 creating, 280 Common User Access (CUA) emulation. See CUA (Common User Access) emulation comparison, 259266 DIFFzilla settings, 266 directories, 265 running standalone, 266 sections within file, 262265 two files, 260261 compile errors, navigation among, 53 compiler(s) default compiler, 96 definiton and tag database, creating, 9698 selecting, 97 unlisted, new definition, creating, 9798 Compiler groups, contents of, 89 complete-more, 167, 188 complete-next, 167, 190 complete-prev, 166, 190 Concurrent Version System (CVS), 271293 accessing, 272 branches and tags, 282283 browse history, 283284 changes, committing, 278 changes, review of, 275277 checking out module, 275 commit sets, group changes with, 279282 Concurrent Version System (CVS), 271272 existing project, checking, 274275 files, adding to, 277

454

functions of, 271272 key bindings, 284285 merge conflicts, 278279 reference guide to, 272 shortcuts, 285 Update Directory, 276277 working copy, checking, 272274 config alias, 232 configuration for appearance, 2425 backups, 31, 379 bookmarks, 129130 changes, saving, 30 default, reverting to, 3031 directory. See configuration directory emulations, 1921 for fonts, 2526 line behavior, 2629 macro variables, changing settings with, 2223 non-default configuration, use of, 3132 Slick-C, placement into. See programmatic configuration target configurations, 60 configuration directory and aliases, 31, 240 contents, deleting, 30 files/subdirectories, listing of, 31 functions of, 30 location of, 16, 30 macros, storage location, 16 non-default, changing to, 3132 state file, 30 and updates, 30 Context Tagging auto-tagging, 75 Class tool window, 8687 definitions, navigating to, 8182 Defs tool window, 8588 errors, control of, 74 files to tag, 74 functions of, 73 list members, configuring, 78 members, listing, 7678 parameter information, 7880

Preview tool window, 81 problems. See Context Tagging troubleshooting pushed bookmarks, 83 push-tag, 93 references, navigating to, 8283 standard libraries, 7374 symbols, finding, 8485 Symbols tool window, 8788 tag databases, 74, 89104 tag files, managing, 8889 workspace tagging, 44, 74 Context Tagging troubleshooting, 105109 Auto-List Members, 107, 109 Auto-Parameter, 107, 109 C/C++ tagging difficulties, 104105, 107108 and complex code, 111112 file extension alias, creating, 109 Go to definition, 105106, 109 Go to Reference, 107, 109 and large projects, 110, 111 Maximums, exceeding limit, 110 and qualified symbols, 106 References performance, 111 solutions, 107109 and symbol names, duplicates, 110 tag file cache size, 111 tag files, adding symbols, 108 tag files, rebuilding, 109 and unqualified symbols, 105106 Control key (Ctrl) key binding commands, 12 settings, 2829 control structures, 180185 adding to code, 182183 deleting, 184185 dynamic surround, 183184 Slick-C, 324326 syntax expansion, 181182 copying, with locked selections, 161 copy-selective-display, 146, 147 copy-to-clipboard, 154 troubleshooting, 16 copy-to-cursor, 156, 161, 201 Courier New, 26

455

Index

Courier New

CUA (Common User Access) emulation


CUA (Common User Access) emulation, 1920 Alt key combinations, 21 command keys, listing of, 392407 key commands, listing of, 408429 macro variable settings, listing of, 429431 stream model, 26 Current Context toolbar, 35 cursor block selections, 201 color, changing, 176 current line, box around, 24 cursor wrap, 27 navigation commands, 120 selection, 156, 161 tab characters, jump over, 27 undo-cursor, 152 cursor-down, 120 cursor-down n, 124 cursor-error command, to open files, 119 cursor-left, 120 cursor-left n, 124 cursor-right, 124 cursor-right n, 124 cursor-up, 120 cursor-up n, 124 customization dialogs, 372375 keyboard, 362365 language support, 365372 menus, 375378 programmatic configuration, 378388 custom projects, 7072 definitions, location for storage, 71 project template files, 71 Slick-C macro, 7172 XML file, editing, 71 cut, 154, 201 cut and paste, clipboard, 154155 cut-end-line, 153 cut-line, 153 CxxTest, 5458 downloading/installing, 57 running tests, 5960 test runner, 5758 test suites, 5457 CygWin bash shell, single quotes as, 96 installing, 47

D
data alignment, 222226 alignment commands, 223224 with macro, 225226 databases. See tag databases data editing, 199227 block editing, 208213 block selections, 200201 calculations, 206207 columns, entering data, 202204 data alignment, 222226 data generation, 205206 large files, 226227 macro record and playback, 213219 search and replace, 220222 sorting, 204 data generation, 205206 enumerate, 205 debug, 332333 command keys, 392394 Debug and Release, 60 GNU C/C++ project, bugs detection, 5460 See also Slick-C macros declarations event tables, 331 Slick-C, 326327 def_complete_flags, 170 def_complete_vars, 170 definit, 310 definitions Defs tool window, 8586 navigating to, 8182 Slick-C, 326327 defload, 310 Defs tool window activating, 39 use of, 8586

456

delete with block selections, 201 bookmarks, 128 code block, 184185 Delete key, settings, 2829 dependency checking, automatic, 60 deselect, 156, 161162, 207 dialogs, customization, 372375 DIFFzilla Backup History, viewing, 269270 comparison with. See Comparison macro, use with, 263264 settings, 266 unsupported commands, 261 Digital Mars, C/C++ compiler definition, creating, 9798 directory comparing, 265 configuration/settings. See configuration directory listing, Slick-C, 340342 workspaces, 44 directory alias dynamic directory aliases, 234235 to open files, 116117 predefined, SlickEdit, 232 display lines on screen, number of, 33 resolution and programming, 33 screen elements, color syntax highlighting, 176 window, 3440 DLL assemblies, global tag database for, 103 do ( ), Slick-C, 325 docked tool windows, 3638 auto-hide, 36 converting to floating, 38 docking groups, 36 order of tabs, changing, 38 documentation, comments, 192 document mode, 253254 select-mode, 254 Document Type Definition (DTD), XML, 255258 dos commands, 11 Doxygen, 195

driver program, GNU C/C++ project, 4849 duplicate-line, 153 dynamic directory aliases, 234235 dynamic languages global tag databases for, 91 standard libraries, 90 tag databases for, 90 tagging source files, 90 See also Groovy; Perl; Ruby dynamic surround disabling, 184 invoking, 183184

E
edit buffer, toggle to command line, 10 edit command in macros, 117 to open files, 117 Edit Expression, 70 editing command keys, 394398 editing pane, 78 remote, FTP/SSH, 302305 See also code editing; data editing; text editing embedded languages, 190192 here documents, 191192 Web programming, 190191 emulations, 1921 changing, 20 command keys, 392407 CUA (Common User Access), 1920 key bindings, 11 key commands, 408429 macro variable settings, 429431 Slick-C, listing of, 20 SlickEdit customizability, 56 WROX, 21, 431434 End key, settings, 29 end-select, 156, 161, 202 Enter key, settings, 2829 enumerate, data generation, 205 errors Edit Expression, 70

457

Index

errors

errors (continued)
errors (continued) error parsing, 6870 Error Regular Expressions, 6870 Matched Error Expression, 70 navigation among, 53, 62, 67 next-error, 53, 59, 67 prev-error, 53, 59, 67 Escape key toggle, edit buffer to command line, 10 tool windows, closing, 36, 39 escape sequences, aliases, 233234 event(s), callbacks, listing of, 441443 event tables Groovy, 371372 key bindings, 331 Slick-C, 331 execute-selection, 332 executing project GNU C/C++ project, 5354 Java project, 62 Ruby project, 6667 expand-alias, 235 /expr [/options], 141142 expressions predefined, listing of, 438439 selection, 156, 161 See also regular expressions extensibility, of SlickEdit, 56 extensionless files UNIX shell scripts, 175 See also C/C++header files Extension Options dialog Auto-complete settings, 189190 comments settings, 195196 tab/indendation settings, 177 extensions, files. See file extensions comparing, 260261 extensions. See file extensions listing, Slick-C, 340342 sections, comparison of, 262264 tag files, 4445 use of term, 7 file aliases, 230232 defining, 230231 to open files, 116117 file extensions alias, creating, 109 alias files, 240 for C/C++, 173 .e, macros, storing, 1718 edit settings, 174 extensionless files, 108109, 174 Extension Options dialog, 108109, 175 extension-specific aliases, 235236 settings, macro for, 384 Slick-C header files, 311 tag database, troubleshooting, 109 FileMan, 297 file manager, 298302 commands, 299300 grouping files, 300 invoking, 298 macros, use of, 301302 to open files, 119 selecting files, 300301 tasks, automating, 301302 filepos.slk, configuration directory, 31 Files tool windows activating, 39 to open files, 117119 File Tabs, toolbar, 78 file templates, 241252 creating, 242246 functions of, 241 instantiating, 241242 instantiating in macros, 248252 managing, 248 substitution parameters, 242, 246248, 250 file tree, Open tool window, 117

F
Fast Open Dialog, 114115 file(s) add file, 45 browse history, 283284, 291 command keys, 398399

458

fill-selection, 202203, 207 filters, selection, 157, 163 find ( ), Slick-C, 337338 find and replace. See Find and Replace tool window; search and replace Find and Replace tool window, 133137 Find, 134135 Find in Files, 135136 grep, 136 Look in selection box, 134 output results, editor window, 136 Replace, 137 Replace in Files, 137 Search Results tool window, 136 values of checkboxes, 134 find/exp[/options), 141142 find-in-files, 132133 keyboard shortcut, 132 find-matching-paren, 120 find-next incremental search, 133 keyboard shortcut, 132 repeat searches with, 132 find-prev incremental search, 133 keyboard shortcut, 132 repeat searches with, 132 Find Symbol tool window activating, 39 use of, 84 FishEye, 281 floating point numbers, Slick-C, 315 floating tool windows, 3638 choosing/closing, 36 converting to docked type, 3738 fonts changing, 2526 default font, 26 screen elements related to, 26 settings, macro for, 383 Web sources for, 26 for ( ), Slick-C, 325 FTP/SSH, 302305 FTP Client, 304305

FTP tool window, 39, 305 set-up for, 302304 full screen, enabling, 35 functions, Slick-C, 311312 of arrays, 321 callbacks, 343346 commands, 311 and declarations, 326327 ordinary functions, 311312 primitive functions, 309, 312 use of, 326327 Functions definitions, selective display, 148 fundamental mode accessing, 174 key bindings in, 13 syntax assistance, suppressing, 185

G
games, Portable Game Notation (PGN), 365366 generic project type, 65, 71 global aliases file alias added to, 231232 functions of, 230 global tag databases building, 89 for C# source files, 104 for C/C++ with header files, 9293 Context Tagging features, confirming, 99100 converting to auto-updated tag database, 93 for DLL assemblies, 103 editing files in, 90 file management, 90 functions of, 89 for Java Jar files, 98100 for Java source files, 98100 naming, 92 for Ruby, 91 testing working of, 103 global variables, Slick-C, 330 GNU C/C++, installing, 47 GNU C/C++ project, 4760 building project, 5253 build systems, 60 creating project, 4952

459

Index

GNU C/C++ project

GNU C/C++ project (continued)


GNU C/C++ project (continued) driver program, 4849 executing project, 53 files for, 4748 GNU C Options dialog, 53 target configurations, 60 unit tests, 5460 goto-bookmark, 128 goto-col n, 124 Go to definition, troubleshooting, 105106, 109 goto-line n, 124 goto-parent, 120 Go to Reference, troubleshooting, 107, 109 grep Find and Replace tool window, 136 options, 85 search for symbols, 85 Groovy, 367372 color syntax highlighting, 368370 event tables, 371372 extension, defining, 371 information source on, 367 navigation, 370371 gui-enumerate, 205 gui-find, 132133 keyboard shortcut, 132 gui-make-tags, 92, 96, 100, 101, 109 gui-open, 114 gui-replace, 132133 keyboard shortcut, 132 gui-set-var, 2223 gui-sort, 204 Hex Source Window, 25 hidden lines, search through, 143 hide-all-comments, 146, 147 hide-code-book, 146 hide-dotnet-regions, 146, 147 hide-selection, 146 history browsing, CVS, 283284 browsing, Subversion, 291 on command line, 11 Home key, settings, 29 hotspots aliases, syntax expansion, 237238 if( ), 181 hsplit-window, 34 HTML end tag, inserting, macro for, 348351 html-mode, 174 indentation, 180 JavaScript within, 191 HTTP resources, downloading of, 258 hyphens, in commands, 9

I
if ( ) hotspots, 181 Slick-C, 324 #include, navigate to header files, 119 incremental search options, changing, 133 steps in, 132133 indentation, 177180 C#, 179 C/C++, 178179 Extensions Options, Indent tab settings, 177 HTML, 180 Java, 179 insert-toggle, 215 installation emulation, selection of, 19 program installation directory, 30 user configuration directory, 30 integers, Slick-C, 314315

H
hash tables functions of, 321 Slick-C, 321322 header files C languages. See C/C++header files Slick-C, 311 here documents, 191192 hex mode color, changing, 176 switching to, 254

460

Integrated Development Environments (IDEs) features of, 34 functions of, 3 i-search incremental search, steps in, 132133 keyboard shortcut, 131

J
Java aliases for, 236 auto-updated tag database workspace, creating, 100102 compiler definitions, SlickEdit support, 102 indentation, 179 JAR files, adding to workspace, 102 JAR files, global tag database for, 98100 Jar files compared to source files, 98 libraries, tagging, 98 library, standard, 98 mode, 174 project with SlickEdit. See Java project source files, global tag database for, 100 JavaDoc comments, 195, 312 Java project, 6165 Ant, management with, 65 building project, 6162 creating project, 61 executing project, 62 Java Options dialog, 6263 JDK, installing, 61 unit tests, 6264 JavaScript, web programming, 191 JdbcTemplate, 99100 joining lines, common key settings, 29

event tables, 331 in fundamental mode, 13 listing, 1314 macros, binding to keys, 1516 setting, 1213 Subversion, 292293 syntax expansion, 181182 tool windows, toggle with, 39 WROX emulation, 21 See also command keys keyboard menus, accessing with, 21 search, commands, 131132 tool windows, activating, 3840 use versus mouse, 8 use versus toolbars, 35 keyboard customization, 362365 joining lines, 362363 page-down, 362 tabbing, 363365 key commands listing of, 408429 WROX emulation, 431434

L
language groups, contents of, 89 leading spaces, treating as tabs, 28 left margin, sizing, 25 lexers functions of, 174, 175 settings, 174 l/expr[/options], 141 libraries C/C++, tagging of, 9293 for dynamic languages, 90 global library tree, 90 Java, tagging of, 98 .NET runtime, tagging, 102104 path to, specifying, 92 Ruby, tagging of, 91 run-time, tag files, creating, 9697 standard, tagging of, 7374 third-party libraries, 95

K
key bindings, 1114 Bind Key dialog, 13 Concurrent Version System (CVS), 284285 Ctrl/Alt/Shift combinations, 13 dialog, features of, 1213 display, what-is command, 12 emulations, 11

461

Index

libraries

line(s)
line(s), 2629 highlighting, current line, 24 joining, 29 joining, macro for, 362363 line model, 26 moving up/down, macro for, 351353 navigation to, commands, 124 selection, 157, 160 settings, Redefine Common Keys dialog, 27 sorting within, 204 splitting, 29 as statements, 26, 159 stream model, 26 trailing spaces, stripping, 28 vertical line column, 24 wrapping. See line wrapping line commands, listing of, 153 line comments, 192194 applying, 193194 defined, 192 deleting, 193 wrapping, 193 Line Hex, 254 line model, 26 lines, navigation to, 124 line selection, 158159 line-to-bottom, 123 line-to-top, 123 line wrapping, 2728 cursor wrap, 27 line comments, 193 settings, 2728 soft wrapping mode, 28 word wrap mode, 28 list-buffers, 125, 127 list-clipboards, 154 list-keydefs, 1314 List Macros dialog, 15 list members, configuring, 78 list-source, programmatic configuration, 386 list-symbols, 105107 locked selections deselecting, 161162 moving among, 161 moving and copying, 161 select commands, 155157 long integers, Slick-C, 315 Look in selection box, Find and Replace tool window, 134 lookup tables, creating with alias, 239240 lowcase-selection, 156, 162 Lucinda Console, 26

M
ma alias, 232 McConnell, Steve, 34 macro(s), 1418 aborting, 16 binding to keys, 1516 and block insert mode, 204 command keys, 399 custom project, 72 custom projects, 7172 data alignment with, 225226 with DIFFzilla, 263264 edit command in, 117 in file manager, 301302 List Macros dialog, 15 loading macro, 1718 macros/directory macro source, 18 naming, 15, 16 next-word, use of, 122 programmatic configuration, macro source information, 387388 push bookmarks, use of, 128 recording, 1416 record-macro-end-execute, 14, 16 record-macro-toggle, 1416 saving, 15 source code, location of, 16 use of term, 14 writing macro, 1617 macro record and playback, 213219 data editing tips, 217220 and large files, 226227 macro, invoking, 216 pros/cons of, 213214

462

syntax assistance with, 218219 XML data, creating from test file, 214216 macros aliases with, 233234 file templates, instantiating in, 248252 keyboard customization, 362365 Slick-C. See Slick-C macros macro variables, 2223 functions of, 22, 330 settings, listing of, 429431 settings, macro for, 382383 set-var command, 23 Set Variable dialog, 2223 Slick-C, 330331 word completion options, 169171 main.e, 343 makefile build option, 60 and tab character, 365 make-tags, 102 Matched Error Expression, 70 match groups. See tagged expressions Maximums, exceeding limit, 110 members listing, 7678 list members, configuring, 78 menus accessing, Alt key combinations, 21 accessing, with keyboard, 21 pop-up, creating, 375378 merge, 266269 3 Way Merge, example of use, 266269 Concurrent Version System (CVS) conflicts, 278279 Subversion conflicts, 289290 message ( ), 332333 message area, functions of, 89 Microsoft Visual Studio, SlickEdit functionality with, 44 modes document mode, 253254 fundamental, changing to, 174 fundamental, key bindings in, 13 for programming languages, 13

selecting, 174 settings, 174 of SlickEdit, 174 modules, Slick-C, 309310 definit, 310 defload, 310 mouse, use versus keyboard, 8 move-to-cursor, 156, 161, 200 moving, with locked selections, 161 Multi-File Diff Output, 265 Multi-level mode, selective display, 149 multiline comments, 192, 194 defined, 192 inserting */, 194 JavaDoc, 195 My SlickEdit Config directory, 16

N
named bookmarks commands, 128 as set bookmarks, 128 uses of, 128129 navigation, 113130 bookmarks, 127130 in buffer, 120123 among buffers, 125127 to byte offset, 124 to columns, 124 command keys, 402404 cursor movement, commands, 120 to header files, 119 to lines, 124 opening files, 114119 pages, movement on, commands, 120 windows, positioning, 123 among words, 120 .NET DLL assembly, global tag database for, 103 New Project dialog, 49, 65 New Project Information dialog, 51 next, 124 next-bookmark, 128 next-buffer, 125, 126 next-buff-tab, 125

463

Index

next-buff-tab

Next Diff
Next Diff, 260 next-error, 53, 59, 62, 67 next-tag, 120 next-window, 125, 126 next-word, 120, 121, 122 numbers color, changing, 176 in Slick-C, 314315

P
page-down, 120 keyboard macro, 362 pages, navigation commands, 120 page-up, 120 paragraphs, selection, 156, 161 parameter information, 7880 configuring, 80 parsing Slick-C strings, 318320 unit tests, error parsing, 6870 Pascal, pascal-mode, 174 passes, auto-complete, 186187 paste, 154 troubleshooting, 16 pattern matching open dialog, 115116 and regular expressions, 137140 Perl, CxxTest tool, 57 PHP files, 191 plusminus, 136, 146 pointer style, C/C++, 178 pop-all-bookmarks, 127 pop-bookmark, 127 pop-up menu, creating, 375378 Portable Game Notation (PGN), 365366 color syntax highlighting, 366367 predefined expressions, listing of, 438439 prefix, search for, 143144 preprocessing C languages. See C/C++ selective display directives, 148 Slick-C, 311 prev-bookmark, 128 prev-buffer, 125, 126 prev-buff-tab, 125 Prev Diff, 260 prev-error, 53, 59, 62, 67 Preview tool window activating, 39 Context Tagging, 81 and source files, 100 symbol information in, 93

O
objects listing of, 336 Slick-C, finding, 334336 one file per window setting buffer-to-window, associating, 34 for split windows, 35 one-window, 34 Open dialog, 114116 Fast Open Dialog, 114115 file name combo box, 115 pattern matching, 115116 size issue, 116 opening files, 114119 cursor-error command, 119 edit command, 117 file and directory aliases, 116117 File Manager, 119 Files tool window, 117119 gui-open command, 114 header files, navigating to, 119 Open dialog, 114116 Open tool window, 117 Project tool window, 117 Open tool window activating, 39 to open files, 117 operating systems commands, 11 SlickEdit functionality, 5, 7 orientation, tool windows, 38 Output tool window, activating, 39 overlay-block-selection, 201202 overwrite mode, 215

464

prev-tag, 120 prev-window, 125 prev-word, 120, 121 primitive functions, 309, 312 procedures, selection, 156, 161 program installation directory, 30 programmatic configuration, 379388 aliases, defining, 381 definitions/code, loading, 380381 extension-specific settings, 384 font settings, 383 list-source, use of, 386 macro recording for determining, 384386 macro source, reading, 387388 macro variable settings, 382383 setting code, macro for, 380381 programming auto-complete, 188189 coding styles, 177 programming languages SlickEdit modes, 13 See also Slick-C; dynamic languages; embedded languages; specific languages programming language support, 365372 Groovy language example, 367372 Portable Game Notation (PGN) example, 365366 project(s), 4972 Active Project, 44 Add Source Files dialog, 52 Add Tree, 45, 52 Add Wildcard, 52 build dependency, 44 build system options, 51, 60 Build tool window, 5253 command keys, 405 console application, example, 46 custom project, steps in, 7072 defined, 4344 dependency checking, 60 errors, navigation among, 53 generic project type, 65, 71 GNU C/C++ project with SlickEdit. See GNU C/C++ project Java project with SlickEdit. See Java project

New Project dialog, 49 New Project Information dialog, 51 preconfigured in SlickEdit, 70 project definition, 45 Project Properties dialog, 5153 projects files, placement of, 50 project type, determining, 44 project type, selecting, 50 Ruby with SlickEdit. See Ruby project storing, file for, 43 tag files, 45 target configurations, 6061 workspaces for, 4344 project-build, 52, 61 project-edit, 97, 108 project-execute, 53, 59 Project Properties dialog, 5153, 97 executing project, 53 functions of, 51 GNU C/C++ project, 5152 opening, 51 Project tool window activating, 39 to open files, 117 properties, Slick-C, 312314 documentation on, 312 functions of, 312 listing of, 312313 pserver, Concurrent Version System (CVS), accessing, 272 pushed bookmarks, 83 commands, 128 functions of, 127, 152 in macros, 128 push-ref, 127 troubleshooting, 107, 111 push-tag, 93, 94, 127 troubleshooting, 105106

Q
quick-reverse-search, keyboard shortcut, 131 quick-search key binding commands, 12

465

Index

quick-search

quick-search (continued)
quick-search (continued) keyboard shortcut, 131 use of, 132 quote-key, 185 replace-in-files, 132133, 137 See also search and replace replace/exp1/exp2[/options], 141 resolution, display, 33 reverse-i-search incremental search, 133 keyboard shortcut, 131 ring, buffers, 125126 Ruby downloading/installing, 65 global tag database for, 91 here documents, 192 libraries, tagging, 91 project with SlickEdit. See Ruby project Ruby project, 6570 creating project, 66 error navigation, 67 executing project, 6667 unit tests, 6770

R
record-macro-end-execute, 14, 16, 216217 record-macro-toggle, 1416, 214, 216 Redefine Common Keys common key settings, 2829 line wrapping, settings, 2728 white space, settings, 28 redo, 152 refactor-option, 97 references, navigating to, 8283 References tool window activating, 39 improving performance, 111 troubleshooting, 111 updates, 111 Regex Evaluator tool window, 305 regular expressions backslash in, 139 Brief, 137139 defined, 137 Error Regular Expressions, 6870 examples of, 141 Regex Evaluator tool window, 305 Regular Expression Evaluator tool window, activating, 39 search and replace with, 137141, 221 SlickEdit, 137139 syntax, listing of, 435438 and tagged expressions, 140 UNIX, 137139 remote editing, FTP/SSH, 302305 Remove Tag File, 93 remove-training-spaces, 28, 157, 162 Reorder windows, 126 replace keyboard shortcut, 132 Replace, 137

S
saving, selections, 163164 say ( ), 333 SBCS/DBCS Source Window, 25 screen. See display scripting language here documents, 191192 See also Slick-C scroll buffer, positioning, commands, 123 scroll-down, 123 scroll-left, 123 scroll-right, 123 scroll-up, 123 search command keys, 405406 quick-search, key bindings, 1213 Slick-C, 338339 search and replace, 131150, 220222 color, search match, 176 color syntax searching, 135, 144145 command-line search/replace, 141146 data editing pros/cons, 220221 default search options, configuring, 149150

466

Find and Replace tool window, 133137 incremental search, 132133 keyboard search, 131132 long search, terminating, 132 quick-search, 132 with regular expressions, 137141, 221 selections, 162 selective display, 146149 with tagged expressions, 140 XML data, creating from test file, 221222 Search Results tool window activating, 39 functions of, 136 options, choosing, 136 seek, 124 seek +n, 124 seek n, 124 seek -n, 124 selections block selection, 159160, 200201 character selection, 157158 character sequence model, 153 clipboard operations, 153 code block, 160161 color, changing, 176 configuring, 164165 deselecting, 161162 filtering, 163 functions of, 153 lines, 160 line selection, 158159 locked selections, 155157 moving among, 161 moving and copying, 161 paragraphs, 161 procedure/function/method, 161 reuse of, 163164 saving, 163164 searching and replace, 162 select commands, 155157 Slick-C macros, 339 sorting, 204 words, 160

selective display, 146149 command-line, 149 custom capability, 148149 Functions definitions, 148 Multi-level mode, 149 predefined commands, 146147 Preprocessor directives, 148 select-mode, 174 set-bootmark, 128 set-var command, 23 Set Variable dialog, 2223 shared tag database, and auto-updated tag databases, 90, 9394 Shift key, key binding commands, 12 shift-selection-left, 156, 162 shift-selection-right, 157, 162, 203 show-all, 141, 146 show-procs, 146, 147 signature, Byte Order Mark (BOM), 255 Single Byte Character Set/Double Byte Character Set (SBCS/DBCS), 255 Slick-C aliases for, 237 arguments, 318, 327330 arrays in, 320321 batch macros, 310311 callbacks, 343346 Call Stack Tool window,activating, 39 commands, 11, 328330, 332 configuration placed in. See programmatic configuration control structures, 324326 declarations, 326327 event tables, 331 functions, 309, 311312, 326327 functions of, 6 global variables, 330 hash tables, 321322 header files, extension, 311 help, online, 312 JavaDoc, 195, 312 language, features of, 308309 macros. See Slick-C macros

467

Index

Slick-C

Slick-C (continued)
Slick-C (continued) mode, 174 modules, 309310 names, caution about, 309310 numbers in, 314315 parsing, 318320 preprocessing, 311 properties, 312314 static variables, 330 strings in, 315320 structs, 323 typeless type, 323324 Slick-C macros, 331358 aliases, defining, 381 buffer, interaction with, 337 callback traces, example macro, 353354 code, executing, 332 configuration-settings, placement in, 380381 debug messages, display, 332333 duplicate line counting, example macro, 347348 execute-selection, 332 executing macro, 332 extension-specific settings, 384 files, choosing, 342 files/directories, listing, 340342 font settings, 383 HTML end tag insertion, example macro, 348351 line movement, example macro, 351353 macro variables, 330331 macro variable settings, 382383 N-Queens, example macro, 357358 objects, finding, 334336 search with, 337339 selections, 339 stack traces, 333334 temporary buffers, use of, 340341 terminating, 332 WROX function names conversion, example macro, 355356 SlickEdit command keys, listing of, 392407 compared to other IDEs, 4 configurability of, 4, 19 as development environment, 5 emulations, 5, 1921 extensibility of, 56 key bindings, 1114 key commands, listing of, 408429 macros, 1418 macro variable settings, listing of, 429431 operating systems and functionality, 5, 7 programmability of, 5 scripting language. See Slick-C user interface, 79 versions of, 7 Smart next window, 126 smarttab, 364365 snapshots, Backup History tool window, 269270 soft wrapping mode, enabling, 28 sorting commands, 204 file manager files, 300 source files Add Source Files dialog, 52 dynamic languages, tagging, 90 Java, compared to Jar files, 98 Java, global tag database for, 100 and preview tool window, 100 spaces leading, treating as tabs, 28 tabs to spaces, converting, 28 trailing, removing, 28 special characters, display of, 25 splitting lines, common key settings, 29 split windows commands, 3435 moving between, 35 one file per window setting, 35 Spring library. See Java SQL aliases for, 236 plsql-mode, 174 stable, sorting algorithm, 204 stack traces, 333334 navigating, 334

468

standard libraries, tagging, 7374 Standard Toolbar, 35 state file configuration directory, 30 functions of, 30 saving on exit, 30 statement, line as, 26, 159 static variables, Slick-C, 330 status indicators, location of, 9 stdcmds.e, 343 stream model, 26 strings, color, changing, 176 strings, Slick-C, 315320 concatenation of, 316 delimiters, 315316 examples of, 316317 indexed, 316 parsing, 318320 stripping, 316 structs, Slick-C, 323 substitution parameters file templates, 242, 246248, 250 listing of, 246247 Subversion, 285293 branches and tags, 290291 browse history, 291 changes, committing, 289 changes, review of, 289 configure for SlickEdit, 287 environment variables with, 286 files, adding to, 289 functions of, 285286 hidden files, viewing, 286 key bindings, 292293 merge conflicts, 289290 new project, creating, 287 reference work on, 286 shortcuts, 292293 Update Directory, 289 working copy, checking, 288 suffix, search for, 143144 surround-with aliases, 238 control-structure, adding, 182183

switch, 290291, 325326 symbols adding to tag file, 108 duplicate names problem, 110, 111 Find Symbol tool window, 39, 84 grep-tag options, 85 large projects, problems with, 110 list-symbols, 105107 qualified and tagging problems, 106 in tag database, 73 unqualified and tagging problems, 105106 Symbols tool window activating, 39 use of, 8788 syntax assistance macro record and playback with, 218219 suppressing, 185 word completion, 168169 syntax expansion with aliases, 237238 example of, 181182 key bindings, 181182

T
tabs characters, jump over, 27 converting to spaces, 28 indentation, 177180 keyboard behavior, changing, 363365 leading spaces, treating as, 28 smarttab, 364365 tag databases, 89104 automating creation of, 96 auto-updated tag databases, 90 categories of, 89 compiler definition, creating, 9698 creating (tagging), 73 creating, 9596, 102 file types, specifying, 92 global tag databases, 8990 language, categorization by, 74 naming, 92

469

Index

tag databases

tag files
tag files cache size, 111 functions of, 45 managing, 8889 rebuilding, 109 for run-time libraries, 9697 symbols, adding to, 108 tagfiles, configuration directory, 31 workspaces, 44 tagged expressions and regular expressions, 140 search and replace with, 140 tagging Concurrent Version System (CVS), 282283 defined, 43, 73 and dynamic languages, 9091 Subversion, 290291 testing, push-tag, 94 See also Context Tagging; tag databases target configurations defaults, 60 GNU C/C++ project, 60 templates complex code, problems, 111112 configuration directory, 31 custom project definitions, 71 metaprogramming, 112 See also file templates temporary buffers, Slick-C, 339340 Test Case, 70 test runner, GNU C/C++ project, 5758 test suites GNU C/C++ project, 5457 Java project, 63 text, shifting left-right, 158159 text editing, 151172 clipboard, 153155 line commands, 152153 redo, 152 selections. See selections undo, 152 word completion, 165171 3 Way Merge, example of use, 266269 toggle, edit buffer to command line, 10 toggle-all-outlining, 146, 147 toggle-bookmark, 128 toolbars command keys, 406 Current Context, 35 customizing, 35 defaults, restoring, 40 File Tabs, 78 specialized, 35 Standard, 35 tool windows, 3540 activate with keyboard, 3840 animation, 40 arrangement, changing, 3738 arrangement options, 3637 defaults, restoring, 40 docked, 3638 floating, 3638 functions of, 8, 3536 hidden, 8 orientation, 38 toggle with keyboard bindings, 39 updates, 38 top-of-buffer, 120121, 202 Top of file line, 25 top-of-window, 120 trace callback traces, 353354 stack traces, 333334 trailing spaces removing, 28 selection, 157, 162 stripping, 28 typeless type, Slick-C, 323324

U
underscores, in commands, 9, 328 undo, 152, 227 undo-cursor, 152 Unicode byte offset, 124 Byte Order Mark (BOM), 124, 255 Unicode Source Window, 25

470

unit tests CxxTest, 5458 error parsing, 6870 GNU C/C++ project, 5460 Java project, 6264 Ruby project, 6770 running tests, 5960, 64, 68 test runner, 5758 test suites, 5457, 63 UNIX configuration directory location, 16 extensionless shell scripts, 175 path, specifying, 96 regular expressions, 137139 regular expression syntax, listing of, 435438 Ruby, downloading/installing, 65 unsurround, 185 upcase-selection, 156, 162 updates and configuration directory, 30 tool windows, 38 UP/Down within soft wrapped lines, 2728 on text, 27 URL resources, downloading, macro for, 257258 uscheme.ini, configuration directory, 31 user configuration directory, 30 user.cpp, configuration directory, 31 user interface, 79 Build tool window, 9 command line, 1011 editing pane, 78 message area, 89 status indicators, 9 toolbar, 78 tool windows, 8 usrprjtemplates.vpt, 71 util.e, 343

static, 330 typeless container type, 323324 variable arguments, Slick-C, 327 version control. See Concurrent Version System (CVS); Subversion Version Control Setup dialog, 272274 View Files in Current Project, 118 Visual C++6 command keys, listing of, 392407 key commands, listing of, 408429 macro variable settings, listing of, 429431 Visual Studio command keys, listing of, 392407 key commands, listing of, 408429 macro variable settings, listing of, 429431 vrestore.slk, configuration directory, 31 vsdelta, configuration directory, 31 vslickconfig, 32 vslick.sta, 379 vslick.stu, 379 vsmktags, 95 vsplit-window, 34 .vtg file, workspaces, storing, 43 vusrdefs.e, configuration directory, 31 vusrmacs.e directory, 1617

W
Web programming, embedded languages, 190191 what-is, key bindings, display of, 12 while ( ), Slick-C, 325 white space, settings, 2728 whole word, search by, 134 wildcards add wildcard, 45 in File tools window, 118 window(s), 3440 buffer-to-window, associating, 34 command keys, 407 configuration settings, 126 full screen, 35 Maximize first window, 24 navigation among, 120

V
variable(s) global, 330 macro, 2223, 330331

471

Index

window(s)

window(s) (continued)
window(s) (continued) one file per window setting, 34 positioning, commands, 123 split windows, 3435 tool windows, 3540 use of term, 7 Windows configuration directory location, 16 Fast Open Dialog, 114115 wizards, and IDEs, 3 word(s) navigation among, 120 selection, 156, 160 word completion, 165171 compared to auto-complete, 186188 compared to auto-complete, 190 examples of, 166167 options, 169171 in programming, 168169 usefulness of, 165 word wrap mode, 28 workspace(s), 4349 for auto-updated tag database, 9495, 100102 directory, 44 functions of, 43 Jar files, adding to, 102 naming, 95 for projects, 4344 storing, file for, 43 tag databases, updating, 95 tag files, 44 tag files, rebuilding, 109 tagging, 74 vsmktags, 95 workspace definition, 45 workspace state, 45 workspace-close, 283 workspace-open, 283 Workspace Tag File, contents of, 89 wrapping. See line wrapping WROX emulation, 21 and DIFFzilla, 261 function names, converting, macro for, 355356 key commands, 431434 tool windows, keyboard activation, 3839 wrox-align-left-with-field-above, 223225 wrox-align-right-with-field-above, 223225 wrox-diff-lines, 264 wrox-makestacktrace, 333334 wrox-next-whitespace-word, 217, 224225 wrox-next-word, 120, 121122 source code for, 122123 wrox-prev-whitespace-word, 217, 261 wrox-prev-word, 120, 121 source code for, 122123 wrox-restore-line-sel, 163164 wrox-retain-exts, 301 wrox-save-line-sel, 163164 wrox-toggle-comment, 193194

X
XML auto-validation, 257 Document Type Definition (DTD), 255258 SlickEdit DTE retrieval, 256257 tags, matching of, 350 XML Schema, 25525

472

Programmer to Programmer

TM

Take your library wherever you go.


Now you can access more than 200 complete Wrox books online, wherever you happen to be! Every diagram, description, screen capture, and code sample is available with your subscription to the Wrox Reference Library. For answers when and where you need them, go to wrox.books24x7.com and subscribe today!

Find books on
ASP.NET C#/C++ Database General Java Mac Microsoft Office

.NET Open Source PHP/MySQL SQL Server Visual Basic Web XML

www.wrox.com

Vous aimerez peut-être aussi