Slide 1

Slide 1 text

Emacs × Touch Bar 2018.11.16 ୈ80ճ Cocoaษڧձؔ੢ @matuyuji

Slide 2

Slide 2 text

@matuyuji • https://github.com/safx • http://safx-dev.blogspot.com • גࣜձࣾψʔϥϘ

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

΍ͬͨ͜ͱ

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Motivation • Touch BarʹͳͬͯEsc͕ԡͮ͠Β͘ͳͬͨ • EmacsͰEscΛ࢖͏ͷ͸࣍ͷ3ͭɻ͜ΕΛָʹ࢖͍͍ͨ • ESC-x (M-xʹͳΔ) • ESC-% (query-replace) • ESC-& (query-replace-regexpʹׂΓ౰͍ͯͯΔ) • Touch Bar͕͋Δ͔ΒͦΕʹׂΓ౰ͯΒΕͨΒΑ͍?

Slide 7

Slide 7 text

Agenda • Emacs • Touch Bar • Emacs-mac • Emacs × Touch Bar

Slide 8

Slide 8 text

Emacs

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

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)

Slide 11

Slide 11 text

Touch Bar

Slide 12

Slide 12 text

https://www.apple.com/macbook-pro/

Slide 13

Slide 13 text

Touch Bar • Late-2016 ͷMacbook ProΑΓ౥ࡌ • ϚϧνλονՄೳͳOLED

Slide 14

Slide 14 text

Emacs Mac Port

Slide 15

Slide 15 text

Emacs Mac Port • macOS޲͚ύον෇͖ͷEmacs
 - ઍ༿େֶͷࢁຊޫ੖ઌੜ͕ϝϯς͍ͯ͠Δ • https://bitbucket.org/mituharu/emacs-mac • https://github.com/railwaycat/homebrew-emacsmacport • Touch Bar޲͚ͷ࣮૷͕ͪΐͬͱೖ͍ͬͯΔ

Slide 16

Slide 16 text

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͕͋Δ

Slide 17

Slide 17 text

Xcode Touch Bar Simulator λονόʔ͕ͳ͍Ϟσϧʹ΋࢖͑Δ

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

×

Slide 20

Slide 20 text

ٙ໰ • Ͳ͏΍ͬͨΒTouch BarʹϘλϯΛදࣔͤ͞ΒΕΔ͔?
 → Ϙλϯͷදࣔ • Ͳ͏΍ͬͨΒTouch BarͷϘλϯΛԡͨ͠ͱ͖ʹLispͷؔ ਺Λ࣮ߦͤ͞ΒΕΔ͔? → Ϙλϯͷ࣮ߦ

Slide 21

Slide 21 text

දࣔ

Slide 22

Slide 22 text

αϯϓϧΞϓϦ Appleެࣜͷ΋ͷ • NSTouchBar Catalog • ToolbarSample

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

AppleͷαϯϓϧΞϓϦ͸ετʔϦʔϘʔυΛ࢖͍ͬͯΔ → ࠓճͷࢀߟʹͳΒͳ͍

Slide 25

Slide 25 text

// 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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

// 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

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

https://developer.apple.com/documentation/appkit/nstouchbar

Slide 34

Slide 34 text

// 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

Slide 35

Slide 35 text

ϘλϯΛදࣔͤͯ͞ΈΔ

Slide 36

Slide 36 text

- (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.")

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

NSApplication NSView EmacsApplication EmacsView EmacsController EmacsMainView EmacsFrameController NSApplicationDelegate NSWindowDelegate NSWindow emacs window EmacsWindow frame NSResponder

Slide 39

Slide 39 text

Window Frame

Slide 40

Slide 40 text

Window Frame

Slide 41

Slide 41 text

NSApplication NSView EmacsApplication EmacsView EmacsController EmacsMainView EmacsFrameController NSApplicationDelegate NSWindowDelegate NSWindow emacs window EmacsWindow frame NSResponder

Slide 42

Slide 42 text

࣮ߦ →

Slide 43

Slide 43 text

࠷ॳͷҊ - (void)touchBarButtonAction:(NSButton *)sender { Fcall_interactively (intern ("query-replace"), Qnil, Qnil); }

Slide 44

Slide 44 text

ϋϯά͢Δ

Slide 45

Slide 45 text

Thread ϋϯά ਖ਼ৗ

Slide 46

Slide 46 text

About Emacs-macͰ௥Ճ͞Εͨૉఢػೳ

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

վྑҊ - (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͕΍ͬͯ͘ΕΔ

Slide 50

Slide 50 text

վྑҊ

Slide 51

Slide 51 text

Elisp͔ΒจࣈྻΛऔΔ ←

Slide 52

Slide 52 text

άϩʔόϧม਺Λ௥Ճ͢Δ Lisp_Object f_Vmac_touch_bar_buttons; #define Vmac_touch_bar_buttons globals.f_Vmac_touch_bar_buttons global.h (ࣗಈੜ੒͞ΕΔ) DEFVAR_LISP ("mac-touch-bar-buttons", Vmac_touch_bar_buttons, doc: /* Vector for Touch bar buttons of Macbook Pro. */); Vmac_touch_bar_buttons = Qnil; macselect.c

Slide 53

Slide 53 text

άϩʔόϧม਺Λ௥Ճ͢Δ • Q Ͱ͸͡·Δ΋ͷ͸ఆ਺ • V Ͱ͸͡·Δ΋ͷ͸ม਺ • doc: Λॻ͍͓ͯ͘ͱdescribe-variableͰࢀর͞ΕΔ

Slide 54

Slide 54 text

ద౰ͳλΠϛϯάͰߋ৽ • mac_read_socket͋ͨΓ͕ϙʔϦϯά͍ͯ͠Δ if (old_mac_touch_bar_buttons != Vmac_touch_bar_buttons) { old_mac_touch_bar_buttons = Vmac_touch_bar_buttons; NSApp.touchBar = nil; }

Slide 55

Slide 55 text

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); }

Slide 56

Slide 56 text

- (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; }