Keyboard macros: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Ruby}}: expand example a bit)
Line 289: Line 289:
end</lang>
end</lang>


A more specific example, using the emacs bindings
A more specific example, using some emacs bindings


<lang ruby>Shoes.app do
<lang ruby>Shoes.app do

Revision as of 14:09, 11 November 2011

Task
Keyboard macros
You are encouraged to solve this task according to the task description, using any language you may know.

Show how to link user defined methods to user defined keys. An example of this is the facility provided by emacs for key bindings. These key bindings may be application-specific or system-wide; state which you have done.

AutoHotkey

<lang AutoHotkey>Loop, 200  ; loop 200 times while not paused {

 TrayTip, counting, %A_Index% press alt-p to pause
 Sleep, 1000

}

!p::  ; links alt-p key combination to the method pauseme() (system wide)

 pauseMe()

Return

!r::  ; links alt-r key combination to the method resume() (system wide)

 resume()

Return

pauseMe() {

 MsgBox, pausing`, press alt-r to resume
 Pause

}

resume() {

 TrayTip, resume, resuming, 2
 Pause, off

}</lang> See ahk-viper-mode for a context sensitive vi key bindings example.

C

Library: Xlib

The following example grabs Alt+F6 and Alt+F7 system-wide on a X server. <lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <X11/Xlib.h>
  3. include <X11/keysym.h>

int main() {

 Display *d;
 XEvent event;
 
 d = XOpenDisplay(NULL);
 if ( d != NULL ) {
               /* or simply XK_F7 should work too */
   XGrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F7")), 

Mod1Mask, /* normally it's Alt */ DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync);

   XGrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F6")), 

Mod1Mask, DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync);

   for(;;)
   {
     XNextEvent(d, &event);
     if ( event.type == KeyPress ) {

KeySym s = XLookupKeysym(&event.xkey, 0); if ( s == XK_F7 ) { printf("something's happened\n"); } else if ( s == XK_F6 ) { break; }

     }
   }
   XUngrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F7")), Mod1Mask, DefaultRootWindow(d));
   XUngrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F6")), Mod1Mask, DefaultRootWindow(d));
 }
 return EXIT_SUCCESS;

}</lang>

HicEst

<lang hicest>! bound to application

  CALL F2
  ! ...
END

SUBROUTINE F2 ! this text shows as tooltip text. F2 ... F9 are possible

  !  synchronous call:     CALL F2
  ! asynchronous calls:    F2 key
  !                        mouse click on the F2 toolbar tool
  !                        ALARM( delay_seconds, 2 )
  ! check if a modifier key is pressed, or a lock key is activated to control program flow:
  KEY(SHift=shft, Control=cntl, ALt=alt, CApital=caps, Numlock=num, SCRoll=scrl)
  WRITE(ClipBoard, Name) shft, cntl, alt, caps, num, scrl
  ! shft=1; cntl=2; alt=4; caps=8; num=16; scrl=32;
  ! is copied to clipboard if all 6 keys are activated and the F2 tool is clicked
  ! Alarm methods F2 ... F9 suspend program flow, which is resumed when finished
  ! If Fn is running and Fm is called:
  !       Fn is suspended if m > n AND n <= 5, else Fm is queued
  ! ...

END</lang>

Java

<lang java> package keybord.macro.demo;

import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent;

class KeyboardMacroDemo {

   public static void main( String [] args ) {
       final JFrame frame = new JFrame();
       
       String directions = "<html>Ctrl-S to show frame title
" +"Ctrl-H to hide it</html>"; frame.add( new JLabel(directions)); frame.addKeyListener( new KeyAdapter(){ public void keyReleased( KeyEvent e ) { if( e.isControlDown() && e.getKeyCode() == KeyEvent.VK_S){ frame.setTitle("Hello there"); }else if( e.isControlDown() && e.getKeyCode() == KeyEvent.VK_H){ frame.setTitle(""); } } }); frame.pack(); frame.setVisible(true); }

} </lang>

JavaScript

The example below captures the F7 key when pressed, if the document (that is, the web page) has focus. If the function returns false, the event processing is halted. If it returns any other value, including undefined, the event continues up the DOM tree ('bubbling').

<lang javascript>document.onkeydown = function(evt) {

 if (evt.keyCode === 118) {
   alert("You pressed F7!");
   return false;
 }

}</lang>

See quirksmode for more information about key detection in JavaScript.

Oz

Window-specific key bindings: <lang oz>declare

 [QTk] = {Module.link ['x-oz://system/wp/QTk.ozf']}
 Label
 Window = {QTk.build td(label(text:"Hello" handle:Label))}

in

 {Window bind(event:"<Control-x><Control-s>"

action:proc {$} {Label set(text:"This is not Emacs.")} end )}

 {Window bind(event:"<Control-x><Control-c>"

action:toplevel#close )}

 {Window show}</lang>

PicoLisp

The 'fkey' function associates a key with an executable body. Some common key codes are predefined in "lib/term.l". Here we use 'F1' to store the value 1 in a global variable, 'Up' and 'Down' arrows to increment or decrement that value, and 'Home' to print the current value to the console. <lang PicoLisp>(load "@lib/term.l")

(fkey *XtF1

  (prinl "Initialized value to " (setq *Number 1)) )

(fkey *XtUp

  (prinl "Incremented to " (inc '*Number)) )

(fkey *XtDown

  (prinl "Decremented to " (dec '*Number)) )

(fkey *XtHome

  (prinl "Current value is " *Number) )</lang>

Output when hitting 'F1', 'Down', 'Up', 'Up' and 'Home':

Initialized value to 1
Decremented to 0
Incremented to 1
Incremented to 2
Current value is 2

PureBasic

PureBasic has support for shortcut/macro creation in any window that supports events. This allows for creation of both single and combinations as shown in the code below. For full set of combinations on PC, Mac & Linux please see the official manual, here. <lang PureBasic>#Win = 0

  1. Demo1 = 0
  2. Demo2 = 1

If OpenWindow(#Win,50,50,200,60,"PureBasic",#PB_Window_SystemMenu)

 ;
 AddKeyboardShortcut(#Win,#PB_Shortcut_F1, #Demo1)
 AddKeyboardShortcut(#Win,#PB_Shortcut_F|#PB_Shortcut_Alt, #Demo2)
 ;
 Repeat
   WEvent = WaitWindowEvent()
   Select  WEvent
     Case #PB_Event_Menu
       Select EventMenu()
         Case #Demo1
           MessageRequester("Info", "You Pressed F1")
         Case #Demo2
           MessageRequester("Info", "You Pressed Alt-F")
       EndSelect
     Case #PB_Event_CloseWindow
       Break
   EndSelect
 ForEver

EndIf</lang>

Python

Works on Unix platforms.

<lang python>#!/usr/bin/env python import curses

def print_message():

   stdscr.addstr('This is the message.\n')

stdscr = curses.initscr() curses.noecho() curses.cbreak() stdscr.keypad(1)

stdscr.addstr('CTRL+P for message or q to quit.\n') while True:

   c = stdscr.getch()
   if c == 16: print_message()
   elif c == ord('q'): break

curses.nocbreak() stdscr.keypad(0) curses.echo() curses.endwin() </lang>

REBOL

<lang REBOL>REBOL [

   Title: "Keyboard Macros"
   Date: 2009-12-14
   Author: oofoe
   URL: http://rosettacode.org/wiki/Keyboard_macros

]

Application specific keyboard bindings using REBOL VID
dialect. Implementation of the "Averageman" calculator --
See http://www.atariarchives.org/bcc2/showpage.php?page=63 for details.

view layout [ style btn button coal 46 across

display: h1 100 red maroon right "" return

Key shortcuts are specified as character arguments to widget
descriptions in the layout.

btn "1" #"1" [set-face display "1"] btn "+" #"+" [set-face display ""] return

pad 54 btn "=" #"=" [set-face display "3"]

pad 1x100 return text "(c) 1977 G. Beker" ]</lang>

Retro

There is a global key handler which we can hook into to capture keys. As a fairly trivial example, remap the ~ key to clear the display.

<lang Retro>[ default: getc

 [ '~ = ] [ drop clear 0 ] when

] is getc</lang>

Additional when conditions could be added to handle other keys. Clearing the key handler to restore its default functionality is done by doing:

<lang Retro>devector getc</lang>

Ruby

Library: Shoes

Here's a sample from the Shoes manual showing how to capture key sequences. This is application specific.

<lang ruby>Shoes.app do

 @info = para "NO KEY is PRESSED."
 keypress do |k|
   @info.replace "#{k.inspect} was PRESSED."
 end

end</lang>

A more specific example, using some emacs bindings

<lang ruby>Shoes.app do

 keypress do |key|
   case key
   when "\x04"  # control-d
     delete_char
   when :backspace
     delete_previous_char
   when "\x14"  # control-t
     transpose_chars
   when :alt_t
     transpose_words
   when "\x18"  # control-x
     @ctrl_x = true
   when "\x13"  # control-s
     if @ctrl_x
       save_text 
       @ctrl_x = false  
     end
   when "\x11"  # control-q
     exit if @ctrl_x
   end
 end

end</lang>

Tcl

Library: Tk

All Tk bindings are bound to a context that is no wider than a particular application and is frequently smaller (e.g., a single dialog box or an individual widget). <lang tcl>package require Tk

  1. Show off some emacs-like bindings...

pack [label .l -text "C-x C-s to save, C-x C-c to quit"] focus . bind . <Control-x><Control-s> {

   tk_messageBox -message "We would save here"

} bind . <Control-x><Control-c> {exit}</lang>

Key-to-key mapping macros

A more direct macro-like facility (substituting one key sequence for another) would be: <lang tcl>bind . <F1> {

   foreach c [split "Macro demo!" {}] {
       event generate %W $c
   }

}</lang> This can then be wrapped up like this: <lang tcl>package require Tk proc sendMacro {w string} {

   foreach c [split $string {}] {
       # Will not work for “<” character...
       event generate $w $c
   }

} proc macro {key translation} {

   bind . <$key> [list sendMacro %W [string map {% %%} $translation]]

}

  1. Some demonstration macros

macro F1 "Help me!" macro F2 "You pressed the F2 key" macro F3 "I'm getting bored here..." pack [text .t]; # A place for you to test the macros</lang>

Vedit macro language

<lang vedit>// Configure a key to access menu item. // The menu item may then contain the commands directly, or it may call a macro from disk. // This has the advantage that the key binding is shown in the menu.

Key_Add("Shft-F6","[MENU]TV", OK)

// Configure a key to perform visual mode edit operations (similar to recorded key macro):

Key_Add("Numpad.Enter", "[CURSOR LEFT][LINE END][RETURN]", OK)

// Configure a key to execute macro language commands:

Key_Add("Numpad+", '[VISUAL EXIT] if(BB!=-1) { RCB(10,BB,BE) BB(-1) S("|@(10)",SET+CONFIRM) } else { S("",CONFIRM) }', OK)

// Configure a key to call a macro from disk. The old key assignment is not removed.

Key_Add("Ctrl-Shft-N",'[VISUAL EXIT] Call_File(100,"aspell.vdm","NEXT_ERROR")',INSERT+OK)

// Configure a two-key sequence (C-x C-c to save file).

Key_Add("^X C","[MENU]FS", OK)

// Remove a key assignment. If INSERT option was used when the key was assigned, the old assignment will come in effect again.

Key_Delete("Ctrl-Shft-N")</lang>