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

Back To Text UI

Back To Text UI

Paradoxically that today it is easier to create GUI than Text UI. Developer has an arsenal of different GUI libraries and layout engines. When one decides to write Terminal Text UI app he faces obstacles of Text UI DSL Library, imperative layouts, constantly increasing complexity and underdeveloped approaches. In this talk I will show you how to ask browser layout engine for help, how to avoid slavery of DSL and build declarative Text UI using only web-technologies like HTML, JS, CSS and React.

Video https://www.youtube.com/watch?v=ee_U2t-8L48

Mikhail Davydov

August 02, 2015
Tweet

More Decks by Mikhail Davydov

Other Decks in Programming

Transcript

  1. _ _ _ _ _ _ | _ _ )

    _ _ _ _ _ _ | | _ _ | | _ _ _ _ | _ \ / _ ` | / _ _ | | / / | _ _ / _ \ | | _ ) | ( _ | | ( _ _ | < | | | ( _ ) | | _ _ _ _ / \ _ _ , _ | \ _ _ _ | _ | \ _ \ \ _ _ \ _ _ _ / | _ _ | _ _ _ _ _ | | _ | | | | _ _ | | | / _ \ \ / / _ _ | | | | | | | | | _ _ / > < | | _ | | _ | | | | | _ | \ _ _ _ / _ / \ _ \ \ _ _ | \ _ _ _ / | _ _ _ |
  2. R e n d e r t e x t

    s ┌ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ┐ | D r a w T e x t U I | └ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ┘ █ 8
  3. . . . a n d f o r A

    S C I I A r t = = = = o o ~ ~ / ~ \ _ \ ­ / _ ( o o | _ _ _ / \ / \ _ \ = / _ / ( ) \ / / | | | \ \ / _ \ _ | _ _ _ _ _ | _ / / | | | / / = = = = = = = = = = = = = = = = = = = | | = = = | | / / | | / / | | | _ | O | _ | ( ' | = = = ( | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | O | | | | | | | | | | _ _ * _ _ | | ( _ ) ( _ ) | | | ~ \ _ _ _ / ~ | | _ | | _ | | | / = \ / = \ / = \ | _ | | _ | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | _ _ _ _ _ _ _ [ _ ] _ [ _ ] _ [ _ ] _ _ _ _ / _ _ ] [ _ _ \ _ _ 9
  4. GUI 1. Text UI – step in GUI evolution •

    PC for non-technical users 2. Browser APIs, WinAPI, GTK, Qt, ... • Easier to create GUI than TUI now 3. «Text UI is for hackers» 14
  5. Developers <3 Terminal 1. Faster to type than click 2.

    Ability to compose text streams 3. More flexible than GUI 4. Less complicated than equal GUI 15
  6. > w g e t ­ q O ­ f

    i l e | b s d t a r ­ x v f ­
  7. Post GUI Text UI 1. Toolchain is not limited •

    1-2 good libraries for every language 2. Imperative style 3. Range of DSV/DSL is a problem DSV – Domain Specific Vocabulary 17
  8. Blessed.js v a r b o x = b l

    e s s e d . b o x ( { s t y l e : { f g: ' w h i t e ' , b g: ' m a g e n t a ' } , b o r d e r: { t y p e : ' l i n e ' } , t a g s : t r u e } ) ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 19
  9. Simple lib – simple DSV i n q u i

    r e r . p r o m p t ( [ { t y p e : ' r a w l i s t ' , n a m e : ' t u i ' , m e s s a g e : ' A r e T U I s c o o l ? ' , c h o i c e s : [ ' Y u p ' , ' W h y d o y o u a s k ? ' ] } ] , ( a n s w e r s ) = > { } ) ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 20
  10. Creating UI engine is challenging 1. Layout Math • Relative

    positioning • Dynamic box dimensions 2. Simple yet familiar DSV • Naming, Structure, Styling, ... 22
  11. 23

  12. _ _ _ _ _ _ _ _ _ _

    _ _ _ _ _ _ _ _ | | | | | | | | _ | | | | | | _ | | | _ _ | | | | | | | | | | | | | | | | | | | | | _ _ _ | _ | | | | | | _ | | | | | | _ _ | | _ _ | | _ _ _ | | _ | | _ | | _ _ _ _ _ _ _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | | | | | | | _ _ | | | | | | | | | | | _ | | | | | | | | | | | | | | | |
  13. < d i v s t y l e =

    " . . . " > C o n t e n t < / d i v >
  14. ┌ ­ ­ ­ ­ ­ ­ ­ ­ ­

    ┐ | C o n t e n t | └ ­ ­ ­ ­ ­ ­ ­ ­ ­ ┘ █
  15. < d i v s t y l e =

    " . . . " > A d v a n c e d < / d i v > < d i v s t y l e = " . . . " > L a y o u t < / d i v >
  16. ┌ ­ ­ ­ ­ ­ ­ ­ ­ ┐

    ┌ ­ ­ ­ ­ ­ ­ ┐ | A d v a n c e d | | L a y o u t | └ ­ ­ ­ ­ ­ ­ ­ ­ ┘ └ ­ ­ ­ ­ ­ ­ ┘
  17. < d i v c l a s s N

    a m e = " m c " > < u l c l a s s N a m e = " m e n u " > < l i c l a s s N a m e = " m e n u _ _ i t e m " > < s p a n c l a s s N a m e = " m e n u _ _ i t e m - s h o r t c < l i c l a s s N a m e = " m e n u _ _ i t e m " > < s p a n c l a s s N a m e = " m e n u _ _ i t e m - s h o r t c < l i c l a s s N a m e = " m e n u _ _ i t e m " > < s p a n c l a s s N a m e = " m e n u _ _ i t e m - s h o r t c < l i c l a s s N a m e = " m e n u _ _ i t e m " > < s p a n c l a s s N a m e = " m e n u _ _ i t e m - s h o r t c < l i c l a s s N a m e = " m e n u _ _ i t e m " > < s p a n c l a s s N a m e = " m e n u _ _ i t e m - s h o r t c < / u l > < d i v c l a s s N a m e = " c o n t e n t " > { t h i s . p r o p s . l e f t P a n e l ? t h i s . _ r e n d e r P a n e l ( t h i s . p r o p s . l e f t P a n e { t h i s . p r o p s . r i g h t P a n e l ? t h i s . _ r e n d e r P a n e l ( t h i s . p r o p s . r i g h t P a < / d i v > < d i v c l a s s N a m e = " c o n s o l e " > < i n p u t c l a s s N a m e = " c o n s o l e _ _ i n p u t " t y p e = " t e x t " d e f a u l t V a l u e = " ~ < / d i v > < u l c l a s s N a m e = " c o n t r o l s " > < l i c l a s s N a m e = " c o n t r o l " > < d i v c l a s s N a m e = " c o n t r o l _ _ n u m b e r " > 1 < / d i v > < d i v c l a s s N a m e = " c o n t r o l _ _ n a m e " > H e l p < / d i v > < / l i > < l i c l a s s N a m e = " c o n t r o l " > < d i v c l a s s N a m e = " c o n t r o l _ _ n u m b e r " > 2 < / d i v > < d i v c l a s s N a m e = " c o n t r o l _ _ n a m e " > M e n u < / d i v > < / l i > < l i c l a s s N a m e = " c o n t r o l " > 29
  18. Borrow from DOM API/CSSOM • e l e m .

    g e t C l i e n t R e c t s ( ) — Layout Math • g e t C o m p u t e d S t y l e ( e l e m ) — Styles • DOM Event system • Document Structure 31
  19. < d i v s t y l e =

    " . . . " > C o n t e n t < / d i v >
  20. Translating <div> to TUI l e t s t y

    l e s = w i n d o w . g e t C o m p u t e d S t y l e ( d i v ) ; l e t r e c t = d i v . g e t C l i e n t R e c t s ( ) ; l e t b o x = r e n d e r B o x( r e c t , s t y l e s ) ; 0 1 . 0 2 . 0 3 . 34
  21. 9 S y m b o l s 3 s

    ┌ ­ ­ ­ ­ ­ ­ ­ ┐ | | └ ­ ­ ­ ­ ­ ­ ­ ┘
  22. Translating textNode to TUI l e t s t y

    l e s = w i n d o w . g e t C o m p u t e d S t y l e ( d i v ) ; l e t t e x t = d i v . f i r s t C h i l d ; l e t r a n g e = d o c u m e n t . c r e a t e R a n g e ( ) ; r a n g e . s e l e c t N o d e C o n t e n t s ( t e x t ) ; l e t r e c t = r a n g e . g e t C l i e n t R e c t s ( ) ; l e t t e x t B o x = r e n d e r T e x t( r e c t , s t y l e s ) ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 36
  23. 9 S y m b o l s 3 s

    ┌ ­ ­ ­ ­ ­ ­ ­ ┐ | | └ ­ ­ ­ ­ ­ ­ ­ ┘ C o n t e n t
  24. ┌ ­ ­ ­ ­ ­ ­ ­ ┐ |

    | └ ­ ­ ­ ­ ­ ­ ­ ┘ C o n t e n t
  25. Forwarding Input events 1. Read from S T D I

    N 2. Serialize Event 3. Transmit to Browser 4. Replay on D O M 5. G O T O 1 41
  26. Ways of repainting 1. a d d E v e

    n t L i s t e n e r ( 'M o zA f t e r P a i n t ' ) 2. r e q u e s t A n i m a t i o n F r a m e ( ) • CPU burning 3. n e w M u t a t i o n O b s e r v e r ( ) • Only DOM changes 43
  27. ReactReconcileTransaction in a nutshell • Restores Selection after updates •

    Suppresses DOM events during updates • Source of c o m p o n e n t D i d U p d a t e 47
  28. ON_DOM_READY_QUEUEING Transaction / / A q u e u e

    f o r c o l l e c t i n g ` c o m p o n e n t D i d M o u n t ` a n d / / ` c o m p o n e n t D i d U p d a t e ` c a l l b a c k s d u r i n g t r a n s a c t i o n v a r O N _ D O M _ R E A D Y _ Q U E U E I N G = { c l o s e : f u n c t i o n ( ) { t h i s . r e a c t M o u n t R e a d y .n o t i f y A l l( ) ; } / / . . . } ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 48
  29. Hacking CallbackQueue c l a s s M y C

    Q e x t e n d s C a l l b a c k Q u e u e { n o t i f y A l l ( ) { s u p e r . n o t i f y A l l ( ) ; c o n s o l e . l o g ( ' u p d a t e ' ); } } P o o l e d C l a s s . a d d P o o l i n g T o ( M y C Q ) ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 49
  30. Hacking ReactReconcileTransaction c l a s s M y R

    R T e x t e n d s R e a c t R e c o n c i l e T r a n s a c t i o n { c o n s t r u c t o r ( ) { s u p e r ( ) ; t h i s . r e a c t M o u n t R e a d y = M y C Q. g e t P o o l e d ( n u l l ) ; } } P o o l e d C l a s s . a d d P o o l i n g T o ( M y R R T ) ; R e a c t U p d a t e s . i n j e c t i o n . i n j e c t R e c o n c i l e T r a n s a c t i o n( M y R R T ) ; 0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 50
  31. Hacking ReactReconcileTransaction 1. Global React Tree changes • Close enough

    to AfterPaint 2. Requires o n W h e e l event hack 3. Doesn't help with stylesheet injections 51
  32. Full Text UI Application Cycle 1. Measure D O M

    & generate Text UI 2. Render Text UI to S T D O U T 3. Receive S T D I N Events 4. Replay Events on D O M 5. G O T O 1 52
  33. Conclusion: Back to Text UI 1. Text UI toolchain is

    not limited 2. H T M L+ C S S+ J S= T U I 3. Declarative Text UI with React! 4. It's easy to extend React unsing injections 53