Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Emacs × Touch Bar

matuyuji
November 17, 2018

Emacs × Touch Bar

Macbook ProのTouch BarからElispの関数を呼べるようにしたのでその実装を紹介しています。
I introduced that the modified version of Emacs which enables to call Elisp functions from Touch Bar.

matuyuji

November 17, 2018
Tweet

More Decks by matuyuji

Other Decks in Programming

Transcript

  1. Motivation • Touch BarʹͳͬͯEsc͕ԡͮ͠Β͘ͳͬͨ • EmacsͰEscΛ࢖͏ͷ͸࣍ͷ3ͭɻ͜ΕΛָʹ࢖͍͍ͨ • ESC-x (M-xʹͳΔ) •

    ESC-% (query-replace) • ESC-& (query-replace-regexpʹׂΓ౰͍ͯͯΔ) • Touch Bar͕͋Δ͔ΒͦΕʹׂΓ౰ͯΒΕͨΒΑ͍?
  2. How to compile Emacs Requirements • autoconf • automake git

    clone git://git.savannah.gnu.org/emacs.git cd emacs-mac ./autogen.sh ./configure --with-ns --without-makeinfo --without-xpm \ --without-jpeg --without-tiff --without-gif --without-png \ --without-rsvg --without-lcms2 --without-libsystemd \ --without-xml2 --without-imagemagick make cd nextstep # ͜͜ʹEmacs.app͕͋Δ mac OS 10.13.6, Xcode 10.1 (Build version 10B61)
  3. Emacs Mac Port • macOS޲͚ύον෇͖ͷEmacs
 - ઍ༿େֶͷࢁຊޫ੖ઌੜ͕ϝϯς͍ͯ͠Δ • https://bitbucket.org/mituharu/emacs-mac •

    https://github.com/railwaycat/homebrew-emacsmacport • Touch Bar޲͚ͷ࣮૷͕ͪΐͬͱೖ͍ͬͯΔ
  4. How to compile Emacs-Mac git clone https://bitbucket.org/mituharu/emacs-mac.git cd emacs-mac ./autogen.sh

    CC="clang -fobjc-arc" ./configure --without-makeinfo \ --without-xpm --without-jpeg --without-tiff \ --without-gif --without-png --without-rsvg \ --without-lcms2 --without-libsystemd --without-xml2 \ --without-imagemagick make cd mac # ͜͜ʹEmacs.app͕͋Δ
  5. ×

  6. // EmacsMainView - (NSTouchBar *)makeTouchBar { NSTouchBar *mainBar = [[NS_TOUCH_BAR

    alloc] init]; mainBar.delegate = self; mainBar.defaultItemIdentifiers = [NSArray arrayWithObjects:NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER, NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST, nil]; return MRC_AUTORELEASE (mainBar); } - (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSTouchBarItem *result = nil; if ([identifier isEqualToString:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]) { if (candidateListTouchBarItem == nil) candidateListTouchBarItem = [[NS_CANDIDATE_LIST_TOUCH_BAR_ITEM alloc] initWithIdentifier:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]; result = candidateListTouchBarItem; } return result; } NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST
  7. NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 #define NS_TOUCH_BAR NSTouchBar #define

    NS_CUSTOM_TOUCH_BAR_ITEM NSCustomTouchBarItem #define NS_CANDIDATE_LIST_TOUCH_BAR_ITEM NSCandidateListTouchBarItem #define NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER \ NSTouchBarItemIdentifierCharacterPicker #define NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST \ NSTouchBarItemIdentifierCandidateList #else #define NS_TOUCH_BAR (NSClassFromString (@"NSTouchBar")) #define NS_CUSTOM_TOUCH_BAR_ITEM (NSClassFromString (@"NSCustomTouchBarItem")) #define NS_CANDIDATE_LIST_TOUCH_BAR_ITEM \ (NSClassFromString (@"NSCandidateListTouchBarItem")) #define NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER \ (@"NSTouchBarItemIdentifierCharacterPicker") #define NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST \ (@"NSTouchBarItemIdentifierCandidateList") #endif
  8. // EmacsMainView - (NSTouchBar *)makeTouchBar { NSTouchBar *mainBar = [[NS_TOUCH_BAR

    alloc] init]; mainBar.delegate = self; mainBar.defaultItemIdentifiers = [NSArray arrayWithObjects:NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER, NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST, nil]; return MRC_AUTORELEASE (mainBar); } - (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSTouchBarItem *result = nil; if ([identifier isEqualToString:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]) { if (candidateListTouchBarItem == nil) candidateListTouchBarItem = [[NS_CANDIDATE_LIST_TOUCH_BAR_ITEM alloc] initWithIdentifier:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]; result = candidateListTouchBarItem; } return result; } NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST
  9. // EmacsMainView - (NSTouchBar *)makeTouchBar { NSTouchBar *mainBar = [[NS_TOUCH_BAR

    alloc] init]; mainBar.delegate = self; mainBar.defaultItemIdentifiers = [NSArray arrayWithObjects:NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER, NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST, nil]; return MRC_AUTORELEASE (mainBar); } - (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSTouchBarItem *result = nil; if ([identifier isEqualToString:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]) { if (candidateListTouchBarItem == nil) candidateListTouchBarItem = [[NS_CANDIDATE_LIST_TOUCH_BAR_ITEM alloc] initWithIdentifier:NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST]; result = candidateListTouchBarItem; } return result; } NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER NS_TOUCH_BAR_ITEM_IDENTIFIER_CANDIDATE_LIST
  10. - (NSTouchBar *)makeTouchBar { NSTouchBar *mainBar = [[NS_TOUCH_BAR alloc] init];

    mainBar.delegate = self; mainBar.defaultItemIdentifiers = [NSArray arrayWithObjects:NS_TOUCH_BAR_ITEM_IDENTIFIER_CHARACTER_PICKER, NS_TOUCH_BAR_ITEM_IDENTIFIER_EMACS_FUNC, nil]; return MRC_AUTORELEASE (mainBar); } - (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSTouchBarItem *result = nil; if ([identifier isEqualToString:NS_TOUCH_BAR_ITEM_IDENTIFIER_EMACS_FUNC]) { NSCustomTouchBarItem *item; NSButton *button; button = [NSButton buttonWithTitle:@"foobar" target:self action:@selector(touchBarButtonAction:)]; item = [[NS_CUSTOM_TOUCH_BAR_ITEM alloc] initWithIdentifier:identifier]; item.view = button; MRC_RELEASE (scrollView); result = MRC_AUTORELEASE (item); } return result; } #define NS_TOUCH_BAR_ITEM_IDENTIFIER_EMACS_FUNC \ (@"com.blogspot.safx-dev.emacs.touchbar.")
  11. GUI -respondsToSelector: -storeEvent: kbd_buffer_store_buffered_event ΩʔϘʔυΠϕϯτͱͯ͠ѻ͏ kbd_buffer_get_event EmacsController mainThread lispThread mac-dispatch-apple-event

    about: read_char read_event_from_main_queue read_decoded_event_from_main_queue make_lispy_event command_loop access_keymap call4 mac-apple-event-mapʹΞΫηε read_key_sequence command-execute special-event-mapʹΞΫηε mac-apple-eventͳconsηϧΛ࡞੒ mac-handle-about Emacs → About Emacs lisp-function C/ObjC function EmacsController handle_action_invocation -methodSignatureForSelector: -forwardInvocation: EmacsController EmacsController keyboard.c
  12. GUI -touchBarButtonAction: -storeEvent: EmacsMainView kbd_buffer_store_buffered_event ΩʔϘʔυΠϕϯτͱͯ͠ѻ͏ kbd_buffer_get_event EmacsController mainThread lispThread

    mac-dispatch-apple-event Touch read_char read_event_from_main_queue read_decoded_event_from_main_queue make_lispy_event command_loop access_keymap call4 mac-apple-event-mapʹΞΫηε read_key_sequence command-execute special-event-mapʹΞΫηε mac-apple-eventͳconsηϧΛ࡞੒ mac-handle-foobar Touch bar lisp-function C/ObjC function keyboard.c
  13. վྑҊ - (void)touchBarButtonAction:(id)sender { struct frame *f = [self emacsFrame];

    struct input_event inev; EVENT_INIT (inev); inev.kind = MAC_APPLE_EVENT; inev.x = Qaction; inev.y = intern ("foobar"); XSETFRAME (inev.frame_or_window, f); inev.arg = Fcons (build_string ("aevt"), Qnil); [emacsController storeEvent:&inev]; } (define-key mac-apple-event-map [action foobar] 'mac-handle-foobar) (defun mac-handle-foobar () (interactive) (print "foobar")) ޙ͸Emacs-mac͕΍ͬͯ͘ΕΔ
  14. TouchBarͷߋ৽ - (NSTouchBar *)makeTouchBar { NSTouchBar *mainBar = [[NS_TOUCH_BAR alloc]

    init]; NSMutableArray *items = [NSMutableArray array]; if (!NILP(Vmac_touch_bar_buttons)) { Lisp_Object rest; for (rest = Vmac_touch_bar_buttons; CONSP (rest); rest = XCDR (rest)) { if (STRINGP (XCAR (rest))) { NSString *label = [NSString stringWithUTF8LispString:(XCAR (rest))]; NSString *ident = [NSString stringWithFormat:@"%@%@", NS_TOUCH_BAR_ITEM_IDENTIFIER_PREFIX, label]; [items addObject:ident]; } } } mainBar.delegate = self; mainBar.defaultItemIdentifiers = [items copy]; return MRC_AUTORELEASE (mainBar); }
  15. - (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { NSTouchBarItem *result = nil;

    if ([identifier hasPrefix:NS_TOUCH_BAR_ITEM_IDENTIFIER_PREFIX] && !NILP(Vmac_touch_bar_buttons)) { Lisp_Object rest; for (rest = Vmac_touch_bar_buttons; CONSP (rest); rest = XCDR (rest)) { if (STRINGP (XCAR (rest))) { NSString *label = [NSString stringWithUTF8LispString:(XCAR (rest))]; NSString *ident = [NSString stringWithFormat:@"%@%@", NS_TOUCH_BAR_ITEM_IDENTIFIER_PREFIX, label]; if ([identifier isEqualToString:ident]) { NSCustomTouchBarItem *item; NSButton *button; button = [NSButton buttonWithTitle:label target:self action:@selector(touchBarButtonAction:)]; item = [[NS_CUSTOM_TOUCH_BAR_ITEM alloc] initWithIdentifier:identifier]; item.view = button; result = MRC_AUTORELEASE (item); break; } } } } return result; }