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

B827d6cfdfbcfce33700b0e6cc03e344?s=128

Mikhail Davydov

August 02, 2015
Tweet

Transcript

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

    _ _ _ _ _ _ | | _ _ | | _ _ _ _ | _ \ / _ ` | / _ _ | | / / | _ _ / _ \ | | _ ) | ( _ | | ( _ _ | < | | | ( _ ) | | _ _ _ _ / \ _ _ , _ | \ _ _ _ | _ | \ _ \ \ _ _ \ _ _ _ / | _ _ | _ _ _ _ _ | | _ | | | | _ _ | | | / _ \ \ / / _ _ | | | | | | | | | _ _ / > < | | _ | | _ | | | | | _ | \ _ _ _ / _ / \ _ \ \ _ _ | \ _ _ _ / | _ _ _ |
  2. None
  3. Writing, 3200 BCE

  4. Woodblock printing, 200 AE

  5. Printing press, 1440

  6. Typewriter, 1860

  7. Terminal, 70-80th

  8. R e n d e r t e x t

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

    S C I I A r t = = = = o o ~ ~ / ~ \ _ \ ­ / _ ( o o | _ _ _ / \ / \ _ \ = / _ / ( ) \ / / | | | \ \ / _ \ _ | _ _ _ _ _ | _ / / | | | / / = = = = = = = = = = = = = = = = = = = | | = = = | | / / | | / / | | | _ | O | _ | ( ' | = = = ( | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | O | | | | | | | | | | _ _ * _ _ | | ( _ ) ( _ ) | | | ~ \ _ _ _ / ~ | | _ | | _ | | | / = \ / = \ / = \ | _ | | _ | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | _ _ _ _ _ _ _ [ _ ] _ [ _ ] _ [ _ ] _ _ _ _ / _ _ ] [ _ _ \ _ _ 9
  10. Text UI of Dired, 1974

  11. Graphic UI, 1985

  12. Window Art

  13. None
  14. 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
  15. 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
  16. > w g e t ­ q O ­ f

    i l e | b s d t a r ­ x v f ­
  17. 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
  18. Blessed.js Demo

  19. 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
  20. 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
  21. Inquirer.js Demo

  22. Creating UI engine is challenging 1. Layout Math • Relative

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

  24. _ _ _ _ _ _ _ _ _ _

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

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

    ┐ | C o n t e n t | └ ­ ­ ­ ­ ­ ­ ­ ­ ­ ┘ █
  27. < 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 >
  28. ┌ ­ ­ ­ ­ ­ ­ ­ ­ ┐

    ┌ ­ ­ ­ ­ ­ ­ ┐ | A d v a n c e d | | L a y o u t | └ ­ ­ ­ ­ ­ ­ ­ ­ ┘ └ ­ ­ ­ ­ ­ ­ ┘
  29. < 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
  30. React Midnight Commander

  31. 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
  32. < d i v s t y l e =

    " . . . " > C o n t e n t < / d i v >
  33. 9 P i x e l Content 3 p x

  34. 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
  35. 9 S y m b o l s 3 s

    ┌ ­ ­ ­ ­ ­ ­ ­ ┐ | | └ ­ ­ ­ ­ ­ ­ ­ ┘
  36. 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
  37. 9 S y m b o l s 3 s

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

    | └ ­ ­ ­ ­ ­ ­ ­ ┘ C o n t e n t
  39. DOM STDOUT →

  40. STDIN DOM →

  41. 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
  42. None
  43. 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
  44. componentDidUpdate event bubbling?

  45. No such thing!

  46. Let's hack React!

  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. Questions?

  55. See more on GitHub

  56. g o o . g l / E h w

    p a 2