• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. How to create two or three key strokes bindkeys

Stats

  • Locked Locked
  • Replies 21
  • Subscribers 146
  • Views 28525
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to create two or three key strokes bindkeys

SlimAnt
SlimAnt over 15 years ago

Hello,

How can I create two or three key strokes bindkeys without changing the existing bindkeys?

For example, addition of existing bindkeys such as: m -> to activate move

I would like to create new bindkeys such as: jmp -> SKILL code to jump to a certain coordinate


I tried using the following function getc to read the next character from keyboard and it doesn't work.

   procedure( call_2()

        TT = getc()

                if( TT = "p" then

                     ; function to jump

                )

     )


   procedure( call_1()

          TT = getc()

                 if( TT = "m" then

                        call_2()

                 )

      )


hiSetBindKey("Layout" "none<Key>j" "call_1()")


I am using version IC6.1.3

I Appreciate any help that I can get.

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 15 years ago

    I had originally planned to describe an outline of a way to do this - but realised that as I started writing the outline, I wasn't that far off having the code itself. So I put together the code below which is a way to implement what I've called "sequence" bindkeys.

    Rather than having to code each specific combination (as in the code in the original post) you register a SKILL action against particular sequences. 

    Anyway, the comments at the top of the code should explain things clearly enough.

    /* abSeqBindKey.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL++ (keep the .ils suffix on this file)
    Date       Oct 22, 2009 
    Modified   
    By         
    
    A package to support sequence bindkeys. This means you can define multi-key
    bindkeys. So for example, you can define a bindkey "chop" - you type the four
    characters c, h, o, and then p - and this then triggers the bindkey.
    The sequence is displayed as a banner label so you can see the current 
    sequence. Escape is normally used to reset the sequence.
    
    Note this is really a proof-of-concept - it is not fully formed, and may
    need some enhancement.
    
    ; Initialize the a-z, A-Z, and 0-9 bindkeys to be entry keys
    ; and escape to be a reset key for Layout application
    abSeqBindKey->initBindKeys("Layout")
    
    ; give warning if any key sequence defined which obscures another
    ; for example, "ed" obscures "edit"
    abSeqBindKey->option(?checkObscured t)
    
    ; Define some key sequences
    abSeqBindKey->set("Layout" "fit" "hiZoomAbsoluteScale(hiGetCurrentWindow() 0.9)")
    abSeqBindKey->set("Layout" 
      '(
        ("copy" "leHiCopy()")
        ("chop" "leHiChop()")
        ("del"  "leHiDelete()")
        ("undo" "hiUndo()")
       )
    )
    
    ; Retrieve bindkeys:
    abSeqBindKey->get("Layout") => returns all the keys
    abSeqBindKey->get("Layout" "chop") => "leHiChop()"
    
    ; If you want to define your own bindkeys (rather than using initBindKeys)
    ; then you'll need to use these:
    abSeqBindKey->enter("X") ; enters an X in the sequence
    abSeqBindKey->reset()    ; resets the sequence
    
    Limitations:
    
    Doesn't have the concept of "Enter Function" bindkeys which are
    different during enter functions. Could do, but needs some thought
    as to a sensible use model.
    
    ***************************************************
    
    SCCS Info: @(#) abSeqBindKey.ils 10/22/09.13:44:45 1.1
    
    */
    
    importSkillVar(abSeqBindKey)
    abSeqBindKey=let(
        ((bindkeys makeTable('bindkeys nil)) obscuredCheck)
    
        /*****************************************************************
        *                                                                *
        *                     initBindKeys(appType)                      *
        *                                                                *
        * EXPORTED function to initialize the bindkeys a-z, A-Z and 0-9, *
        *  as well as Escape, to work with the sequence bindkey system.  *
        *                                                                *
        *****************************************************************/
        defun(initBindKeys (appType)
            let((appRoot)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appRoot
                    ;--------------------------------------------------------
                    ; Define bindkeys for a-z, A-Z and 0-9
                    ;--------------------------------------------------------
                    for(ascii charToInt('a) charToInt('z)
                        hiSetBindKey(appRoot
                            strcat("<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                intToChar(ascii))
                        )
                        hiSetBindKey(appRoot
                            strcat("Shift<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                upperCase(intToChar(ascii)))
                        )
                    ) ; for
                    for(ascii charToInt('\0) charToInt('\9)
                        hiSetBindKey(appRoot
                            strcat("<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                intToChar(ascii))
                        )
                    ) ; for
                    hiSetBindKey(appRoot "<Key>Escape" "abSeqBindKey->reset()")
                ) ; when appRoot
            ) ; let
        ) ; defun initBindKeys
    
        /************************************************************************
        *                                                                       *
        *                              enter(char)                              *
        *                                                                       *
        *   EXPORTED Function to enter a character in the sequence. If there    *
        *     is a sequence bindkey registered for that sequence, reset and     *
        *       then execute the bindkey definition - otherwise continue        *
        * collecting the characters in the sequence (and display in the banner) *
        *                                                                       *
        ************************************************************************/
        defun(enter (char)
            let((win appType appRoot bindkeyTab defn sequence)
                win=hiGetCurrentWindow()
                when(win
                    sequence=strcat(win~>abSequence || "" char)
                    win~>abSequence=sequence
                )
                appType=win && hiGetAppType(win)
                when(appType
                    appRoot=hiGetBindKeyInheritRoot(appType)
                )
                when(appRoot
                    ;--------------------------------------------------------
                    ; Look up the bindkey definition. If found, then
                    ; reset the sequence and evaluate it, otherwise just
                    ; append the current sequence.
                    ;--------------------------------------------------------
                    bindkeyTab=bindkeys[appRoot]
                    defn=bindkeyTab && bindkeyTab[sequence]
                    if(stringp(defn) then
                        reset()
                        errsetstring(defn t)
                    else
                        hiChangeBannerLabel(
                            hiGetCurrentWindow()
                            strcat("Seq: " sequence)
                            0
                        )
                    ) ; if bindkey found
                ) ; when appRoot
            ) ; let
        ) ; defun enter
    
        /***************************************************************
        *                                                              *
        *                           reset()                            *
        *                                                              *
        *       EXPORTED function to reset the current sequence        *
        *                                                              *
        ***************************************************************/
        defun(reset ()
            hiGetCurrentWindow()~>abSequence=""
            hiChangeBannerLabel(
                hiGetCurrentWindow()
                "Seq: "
                0
            )
        ) ; defun reset
    
        /***************************************************************
        *                                                              *
        *                    check(bindkeyTab key)                     *
        *                                                              *
        *  INTERNAL function to check that a new key sequence is not   *
        *    obscured by another, or does not obscure another. Only    *
        *      checked if option(?checkObscured t) has been used.      *
        *                                                              *
        ***************************************************************/
        defun(check (bindkeyTab key)
            let((len subKeyName)
                when(obscuredCheck && stringp(bindkeyTab[key])
                    len=strlen(key)
                    ;--------------------------------------------------------
                    ; Look for any existing key sequences which the new key is
                    ; the beginning part of
                    ;--------------------------------------------------------
                    foreach(keyName bindkeyTab
                        when(key!=keyName && zerop(strncmp(key keyName len)) &&
                            stringp(bindkeyTab[keyName])
                            warn("Definition for sequence %s will obscure sequence %s\n"
                                key keyName)
                        ) ; when
                    ) ; foreach
                    ;--------------------------------------------------------
                    ; Look for any key sequences which are shorter than the new key
                    ;--------------------------------------------------------
                    for(sub 1 sub1(len)
                        subKeyName=substring(key 1 sub)
                        when(stringp(bindkeyTab[subKeyName])
                            warn("Definition for sequence %s will obscure sequence %s\n"
                                subKeyName key)
                        ) ; when
                    ) ; for
                )
            ) ;let
        ) ; defun
    
        /***************************************************************
        *                                                              *
        *                   set(appType key [defn])                    *
        *                                                              *
        *  EXPORTED function to set one or more sequence bindkeys for  *
        *                        an application                        *
        *                                                              *
        ***************************************************************/
        defun(set (appType key @optional defn "tg")
            let((appRoot bindkeyTab)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appRoot
                    bindkeyTab=bindkeys[appRoot]
                    unless(bindkeyTab
                        bindkeyTab=makeTable('appBindkeys nil)
                        bindkeys[appRoot]=bindkeyTab
                    )
                    ;--------------------------------------------------------
                    ; Handle list of definitions, and individual definitions
                    ;--------------------------------------------------------
                    if(listp(key) then
                        foreach(keyDefn key
                            if(listp(keyDefn) && length(keyDefn==2) then
                                bindkeyTab[car(keyDefn)]=cadr(keyDefn)
                                check(bindkeyTab car(keyDefn))
                            else
                                warn("Key definition %L is invalid\n" keyDefn)
                            )
                        )
                    else
                        bindkeyTab[key]=defn
                        check(bindkeyTab key)
                    )
                    t
                ) ; when appRoot
            ) ; let
        ) ; defun set
    
        /*******************************************************************
        *                                                                  *
        *                        get(appType [key])                        *
        *                                                                  *
        * EXPORTED function to get one or all sequence bindkey definitions *
        *                                                                  *
        *******************************************************************/
        defun(get (appType @optional key "tg")
            let((appRoot bindkeyTab)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appType 
                    bindkeyTab=bindkeys[appRoot]
                    ;--------------------------------------------------------
                    ; If the key argument provided, just return the definition
                    ; otherwise return an assoc list of the whole lot
                    ;--------------------------------------------------------
                    if(key then
                        bindkeyTab && bindkeyTab[key]
                    else
                        tableToList(bindkeyTab)
                    )
                ) ; when appType
            ) ; let
        ) ; defun get
    
        /***************************************************************
        *                                                              *
        *                  option(@key checkObscured)                  *
        *                                                              *
        *       EXPORTED function to set any options. Currently        *
        *                     just ?checkObscured.                     *
        *                                                              *
        ***************************************************************/
        defun(option (@key checkObscured)
            obscuredCheck=checkObscured
        )
    
        ;--------------------------------------------------------------------
        ; DPL containing all the package functions available from outside
        ;--------------------------------------------------------------------
        `(nil
            initBindKeys ,initBindKeys
            enter ,enter
            reset ,reset
            set ,set
            get ,get
            option ,option
        )
    ) ; let
    
    

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • wklane
    wklane over 4 years ago in reply to Andrew Beckett

    is there any recent revisions?  I cant get it to work

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to wklane

    Hmm, something got messed up in the formatting on the forum site, and so some of the code where the bind keys were being formed got screwed up - I suspect the <Key> parts were being confused as HTML. I copied the code from the forum, and when I tried to initialise:

    abSeqBindKey->initBindKeys("Layout")

    I got loads of messages like this:

    *WARNING* Invalid bindkey key string: Shiftt

    Anyway, I've re-uploaded the code (I replaced it in the post above) and now it should be OK. I'm assuming you kept the .ils suffix in the file, that you'd loaded it, and you called the abSeqBindKey->initBindKeys("Layout") function to initialise everything?

    Let me know if that doesn't fix your problem - and if it doesn't, please describe what you've done, and what happens... the code itself hasn't needed changing in 11 years; I just tested it using IC6.1.8 ISR15 (using the samples in the comments at the top of the code).

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to wklane

    Hmm, something got messed up in the formatting on the forum site, and so some of the code where the bind keys were being formed got screwed up - I suspect the <Key> parts were being confused as HTML. I copied the code from the forum, and when I tried to initialise:

    abSeqBindKey->initBindKeys("Layout")

    I got loads of messages like this:

    *WARNING* Invalid bindkey key string: Shiftt

    Anyway, I've re-uploaded the code (I replaced it in the post above) and now it should be OK. I'm assuming you kept the .ils suffix in the file, that you'd loaded it, and you called the abSeqBindKey->initBindKeys("Layout") function to initialise everything?

    Let me know if that doesn't fix your problem - and if it doesn't, please describe what you've done, and what happens... the code itself hasn't needed changing in 11 years; I just tested it using IC6.1.8 ISR15 (using the samples in the comments at the top of the code).

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • wklane
    wklane over 4 years ago in reply to Andrew Beckett

    I think I am missing something basic.  First the get, set and reset functions wouldnt load, it errored saying they were internal functions and couldnt be re-defined.  I appended an _f to the end of them and their respective calls to get it to load. It does load now but nothing seems to have changed in my environment.....ie, all my keys operate as initially defined at startup

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to wklane

    It sounds as if you did not keep the file suffix as “.ils”. That is important - otherwise it won’t get loaded using SKILL++ semantics and the local functions will clash with existing global functions. You should not need to rename any function to make this work. What did you call the file name you stored the code in?

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • wklane
    wklane over 4 years ago in reply to Andrew Beckett

    mbind.ils

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • wklane
    wklane over 4 years ago in reply to wklane

    I put everything back as you had it and correct extension. it loads fine but still no change

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to wklane

    Well, if I either give the file the .il suffix, or omit the let() around everything in the code, then I get an error like this when loading:

    *Error* define: can't redefine an internal function - reset
    *Error* load: error while loading file - "~/shared/xfer/mbind.ils" at line 161

    Are you just loading the file with load("mbind.ils") ? Or are you copying and pasting the code into the CIW (which won't work)?

    Please give an exact transcript of what you're doing - it doesn't make any sense to me, since this is very simple - you put the code in a file with a .ils suffix, then load("thatfile.ils") and then initialise using  abSeqBindKey->initBindKeys("Layout") and finally define some multi-key bind keys as described at the top of the file in the comments.

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • wklane
    wklane over 4 years ago in reply to Andrew Beckett

    ok, i got it to work.  operator error, my file editor didnt indicate the first section as comments and I assumed they had be executed.  thanks for your patience

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information