documentation/writing_fshell_commands.pod
changeset 0 7f656887cf89
child 36 698ccde15713
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 #!perl
       
     2 # writing_fshell_commands.pod
       
     3 #
       
     4 # Copyright (c) 2010 Accenture. All rights reserved.
       
     5 # This component and the accompanying materials are made available
       
     6 # under the terms of the "Eclipse Public License v1.0"
       
     7 # which accompanies this distribution, and is available
       
     8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 #
       
    10 # Initial Contributors:
       
    11 # Accenture - Initial contribution
       
    12 #
       
    13 
       
    14 __END__
       
    15 
       
    16 =head1 Writing fshell commands
       
    17 
       
    18 A quick guide to adding a new fshell command, covering the fshell build and configuration system, the internals of commands themselves and some background on the relevant concepts.
       
    19 
       
    20 =head1 Before you start
       
    21 
       
    22 =head2 Step 1: RTM!
       
    23 
       
    24 The first step is to make sure there isn't already a command that does what you need. It may seem obvious but there are quite a lot of commands and some have a lot of options and different functionality. Skim through the L<command list|fshell::commands> to be certain. For example you might note there's no 'bluetooth' command in fshell - however a check of the L<command list|fshell::commands> will reveal the L<btservices|fshell::commands::btservices> command which supports a number of Bluetooth-related operations.
       
    25 
       
    26 =head2 Check the todo list
       
    27 
       
    28 Check the todo list (I<TODO: figure out where the todo list is going to live!>). Someone else may have similar ideas or already be working on similar functionality.
       
    29 
       
    30 =head2 Decide whether you want to add it to fshell
       
    31 
       
    32 You're free to write whatever tools you like that use fshell and build on top of it. We (Accenture) have a number of specialised tools that use fshell but aren't part of the fshell package itself. You may however wish to contribute back to the fshell package; if so there are some additional constraints regarding where to put the source and the fshell build and configuration system (in addition to the Foundation Contribution guidelines http://developer.symbian.org/wiki/index.php/Contribution_Process ). You can ignore a lot of the below if you don't plan to add your command to the fshell package.
       
    33 
       
    34 =head1 Getting stuck in
       
    35 
       
    36 Once you've decided there isn't a suitable existing command, and no-one else is developing one, it's time to get started. Let's assume your new fshell command will be called C<qotd> and displays an insightful Quote Of The Day each time you run it. We're also assuming that you plan to integrate the command into the fshell package, thus will create the source code in the fshell\commands\qotd directory. (Please note we have no plans to actually add a qotd command - attributing the quotes and copyright is far too much like hard work!)
       
    37 
       
    38 If you are not contributing the command to the fshell package please put the source outside of the fshell tree.
       
    39 
       
    40 =head2 Built-in vs external
       
    41 
       
    42 (aka 'thread' vs 'process')
       
    43 
       
    44 There are two types of fshell command: ones built into fshell.exe itself (such as cd, export, source, etc) and ones that are implemented as standalone exes (such as listapps.exe, drvinfo.exe and so forth). Built-in commands are restricted as to what APIs they can use (so as to not introduce problematic dependancies), so we generally recommend that new commands are external ones that run in a separate process. Contact the fshell maintainers if you think you've a candidate for a new built-in command.
       
    45 
       
    46 Each external command lives in a separate directory \fshell\commands\<commandname>. Built in commands live in the \fshell\core tree.
       
    47 
       
    48 =head2 Using C<createsrc> to generate the boilerplate
       
    49 
       
    50 The createsrc command (installed in \epoc32\tools) is a great way to automate creating the skeleton of a new command. Run it with no arguments to be prompted for every option, for brevity the example below shortcuts it slightly and assumes you've already created the directory F<fshell\commands\qotd>. It also overrides the default copyright message, since you presumably won't want to assign copyright to Accenture!
       
    51 
       
    52     M:\fshell\commands\qotd>
       
    53     M:\fshell\commands\qotd>createsrc fshellcmd qotd -DCOPYRIGHT="Copyright (c) 2010 N. Seagoon. All Rights Reserved."
       
    54     Enter short description of the command (for the .cif file) for qotd: Displays a randomly selected quote of the day.
       
    55     M:\fshell\commands\qotd>
       
    56     M:\fshell\commands\qotd>dir /B
       
    57     bld.inf
       
    58     qotd.cif
       
    59     qotd.cpp
       
    60     qotd.mmp
       
    61 
       
    62 At this point you have an fshell command that will compile and run - although it won't do very much yet.
       
    63 
       
    64 The C<.cif> file contains meta-data about the command - its description and what arguments and options it accepts. See L<here|cif_syntax> for more information on the CIF file format. The C<bld.inf> and C<.mmp> are the standard Symbian OS build files. The C<.cpp> is a minimalist implementation of your command, based on the information you passed to createsrc.
       
    65 
       
    66 =head2 CCommandBase
       
    67 
       
    68 As you'll see, the C<.cpp> file declares a single class CCmdQotd, which derives from C<IoUtils::CCommandBase> and implements a few derived functions. CCommandBase is the base class for all fshell commands. When your command is executed, fshell converts the command line arguments into member variables of your CCommandBase subclass and calls DoRunL(). (It figures out how to do this from the CIF file and the result of calling the OptionsL() and ArgumentsL() functions). The implementation of your command goes in DoRunL(). For now we will implement a very simple DoRunL that just prints a single string and exits:
       
    69 
       
    70     void CCmdQotd::DoRunL()
       
    71         {
       
    72         Printf(_L("Quote goes here!\r\n"));
       
    73         }
       
    74 
       
    75 If you build your command now, you'll see it in action:
       
    76 
       
    77     M:\fshell\commands\qotd>sbs -c winscw_udeb
       
    78     ...
       
    79     M:\fshell\commands\qotd>fshell
       
    80     ...
       
    81     c:\>qotd
       
    82     Quote goes here!
       
    83     c:\>exit
       
    84     M:\fshell\commands\qotd>
       
    85 
       
    86 Note how we've used the fshell bat file to start the winscw emulator inside the DOS command prompt. There's a lot of stuff going on behind the scenes to make this work, but it's a convenient way of testing commands. Normally you'd build the fshell tree (or any part of it) from one of the \fshell\build directories, and you wouldn't use the bld.inf that createsrc generated. I've skipped that for the moment for simplicity's sake.
       
    87 
       
    88 =head2 Adding options and arguments
       
    89 
       
    90 Fshell takes care of parsing command lines in a consistant manner, but you have to let it know what your command supports. Let's say that you want to give qotd a C<--shouty> option which, if specified, prints the quote in upper case. Since all options in fshell commands have a long form and a single-letter abbreviation, we'll choose C<-s>. Firstly we need to add a C<==option> section to the CIF file:
       
    91 
       
    92     ==option bool s shouty
       
    93 
       
    94     Displays the quote in UPPER CASE.
       
    95 
       
    96 Now we need to update the C++ code. Firstly, to add a TBool to CCmdQotd for fshell to fill in:
       
    97 
       
    98      class CCmdQotd : public CCommandBase
       
    99         {
       
   100     ...
       
   101      private:
       
   102     -//TODO: arguments/options
       
   103     +   TBool iShouty;    
       
   104         };
       
   105 
       
   106 Then we need to associate the --shouty option with the iShouty member variable:
       
   107 
       
   108     void CCmdQotd::OptionsL(RCommandOptionList& aOptions)
       
   109         {
       
   110         aOptions.AppendBoolL(iShouty, _L("shouty"));
       
   111         }
       
   112 
       
   113 If you rebuild and run the help now, you'll see that the option is all configured:
       
   114 
       
   115     c:\>qotd --help
       
   116     SYNTAX
       
   117 
       
   118         qotd [options]
       
   119 
       
   120     OPTIONS
       
   121 
       
   122          -s (--shouty)  Displays the quote in UPPER CASE.
       
   123          -h (--help)    Display help.
       
   124 
       
   125     DESCRIPTION
       
   126 
       
   127     Displays a randomly selected quote of the day.
       
   128 
       
   129     COPYRIGHT
       
   130 
       
   131     Copyright (c) 2010 N. Seagoon. All Rights Reserved.
       
   132 
       
   133     c:\>
       
   134 
       
   135 All that remains is to actually do something when --shouty is specified:
       
   136 
       
   137     void CCmdQotd::DoRunL()
       
   138         {
       
   139         if (iShouty)
       
   140             {
       
   141             Printf(_L("QUOTE GOES HERE!\r\n"));
       
   142             }
       
   143         else
       
   144             {
       
   145             Printf(_L("Quote goes here!\r\n"));
       
   146             }
       
   147         }
       
   148 
       
   149 After rebuilding, you should be able to do:
       
   150 
       
   151     c:\>qotd
       
   152     Quote goes here!
       
   153     c:\>
       
   154     c:\>qotd --shouty
       
   155     QUOTE GOES HERE!
       
   156     c:\>
       
   157     c:\>qotd -s
       
   158     QUOTE GOES HERE!
       
   159     c:\>
       
   160 
       
   161 Adding other types of option/argument is done in a similar way, see L<here|cif_syntax/CIF types and CCommandBase types> for the list of CIF types and their equivalent C++ types. The one thing to be aware of is that you are responsible for deleting any string or array arguments in the command's destructor, even though the fshell framework created them. This is mainly for legacy compatability reasons, it should probably be done automatically in ~CCommandBase().
       
   162 
       
   163 =head2 Integrating with fshell's build system
       
   164 
       
   165 I<If you're not writing a command that's going to be integrated into the fshell source tree, you can mostly ignore this section.>
       
   166 
       
   167 To make sure your new command gets built, add the mmp and any exports (eg the CIF) to \fshell\commands\group\bld.inf:
       
   168 
       
   169     PRJ_EXPORTS
       
   170     ..\qotd\qotd.cif            z:\resource\cif\fshell\qotd.cif
       
   171     PRJ_MMPFILES
       
   172     ..\qotd\qotd.mmp
       
   173 
       
   174 The fshell build system makes heavy use of preprocessor conditionals to make sure that the codebase builds on a wide variety of platforms. In this example qotd doesn't have any depenancies so the files can be added unconditionally to the bld.inf. If however you take the USB command as an example, you'll see that in the bld.inf it is surrounded by C<#ifdef FSHELL_CORE_SUPPORT_USB>. This in turn is defined in L<common.mmh|common_mmh> only if C<FSHELL_COMMS_SUPPORT> is available. In other words the USB command relies on comms support being available in the platform that's being build. (You may thing that's overkill but early baseport bringup regularly needs to build minimalist textshell ROMs without any form of comms support other than maybe a uart - this level of configurability means it's possible to include fshell on there too.)
       
   175 
       
   176 If your command can take advantage of a feature, but doesn't absolutely require it, you may wish to guard only sections of code with an appropriate C<FSHELL_xyz> macro. common.mmh can be included anywhere the preprocessor is used (source files, bld.inf, MMPs, resource files) so you can be as fine-grained as you like. For example fshell itself uses many C<#ifdef FSHELL_MEMORYACCESS_SUPPORT> blocks so that ps can give more detailed process listings if MemoryAccess is available, but falls back gracefully to less detailed info if it isn't.
       
   177 
       
   178 B<I<To be completed...>>