From 1a3fcc1bd8fc3d29c87d08c5167676bac0eca3a0 Mon Sep 17 00:00:00 2001 From: Arthur Sonzogni Date: Sun, 20 Mar 2022 18:13:11 +0100 Subject: [PATCH] Improvement documentation. (#361) --- CHANGELOG.md | 4 +- README.md | 26 +-- doc/mainpage.md | 425 ++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 379 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a18c339..521111f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ current (development) means non-cmake users should not link against "libftxui-dom" for instance. ### Component -- Animations module! Components can implement the `OnAnimation` method and the - animation::Animator to define some animated properties. +- **Animations** module! Components can implement the `OnAnimation` method and + the animation::Animator to define some animated properties. - `Menu` now support animations. - `Button` now supports animations. - Support SIGTSTP. (ctrl+z). diff --git a/README.md b/README.md index d5e66875..37aefa67 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,26 @@ A simple C++ library for terminal based user interfaces! [[1]](https://hackernoon.com/building-reactive-terminal-interfaces-in-c-d392ce34e649?gi=d9fb9ce35901) and [React](https://reactjs.org/) * Simple and elegant syntax (in my opinion) + * Keyboard & mouse navigation. * Support for [UTF8](https://en.wikipedia.org/wiki/UTF-8) and [fullwidth chars](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) (→ 测试) + * Support for animations. [Demo 1](https://arthursonzogni.com/FTXUI/examples/?file=component/menu_underline_animated_gallery), [Demo 2](https://arthursonzogni.com/FTXUI/examples/?file=component/button_style) + * Support for drawing. [Demo](https://arthursonzogni.com/FTXUI/examples/?file=component/canvas_animated) * No dependencies - * Cross platform. Linux/MacOS (main target), Windows (experimental thanks to contributors), WebAssembly - * Keyboard & mouse navigation + * Cross platform: Linux/MacOS (main target), WebAssembly, Windows (Thanks to contributors!). + * Learn by [examples](#documentation), and [tutorials](#documentation) + * Multiple packages: CMake [FetchContent](https://bewagner.net/programming/2020/05/02/cmake-fetchcontent/) (preferred), vcpkg, pkgbuild, conan. + * Good practises: documentation, tests, fuzzers, performance tests, automated CI, automated packaging, etc... + +## Documentation + +- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter) +- [Documentation](https://arthursonzogni.github.io/FTXUI/) +- [Examples (WebAssembly)](https://arthursonzogni.com/FTXUI/examples/) +- [Build using CMake](https://github.com/ArthurSonzogni/FTXUI/blob/master/doc/mainpage.md#using-cmake) ## Operating systems +This is expected to be cross platform. This supports / tests: - WebAssembly - Linux - MacOS @@ -62,13 +75,6 @@ A simple C++ library for terminal based user interfaces! └────────────────────────────────────────────────────────────────────────────┘ ~~~ -## Documentation - -- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter) -- [Documentation](https://arthursonzogni.github.io/FTXUI/) -- [Examples (WebAssembly)](https://arthursonzogni.com/FTXUI/examples/) -- [Build using CMake](https://github.com/ArthurSonzogni/FTXUI/blob/master/doc/mainpage.md#using-cmake) - ## Short gallery #### DOM @@ -165,7 +171,7 @@ Element paragraphAlignCenter(std::string text); Element paragraphAlignJustify(std::string text); ``` -[Paragraph example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2table_8cpp-example.html): +[Paragraph example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2paragraph_8cpp-example.html) ![ezgif com-gif-maker (4)](https://user-images.githubusercontent.com/4759106/147251370-983a06e7-6f41-4113-92b8-942f43d34d06.gif) diff --git a/doc/mainpage.md b/doc/mainpage.md index f4ab30d4..0805c445 100644 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -1,14 +1,19 @@ \mainpage -# Introduction +# Introduction {#introduction} -Welcome to the FTXUI documentation. Here, you will find the detail of every -functions and classes. +Welcome to the FTXUI documentation! + +This is a brief tutorial. You are also encouraged to learn, by reading the +[examples](./examples.html) @tableofcontents **Short example** +To build a single frame, you need create an `ftxui::Element`, and display it on +a `ftxui::Screen`. + **main.cpp** ```cpp #include @@ -37,6 +42,7 @@ int main(void) { } ``` + **output** ```bash ┌────┐┌─────────────────────────────────────────────────────────────────┐┌─────┐ @@ -44,9 +50,9 @@ int main(void) { └────┘└─────────────────────────────────────────────────────────────────┘└─────┘ ``` -# Build +# Build {#build} -## Using CMake +## Using CMake {#build-cmake} CMakeLists.txt ~~~cmake @@ -58,7 +64,7 @@ include(FetchContent) set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE) FetchContent_Declare(ftxui GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui - # Specify a GIT_TAG here. + # Important: Specify a GIT_TAG XXXXX here. ) FetchContent_GetProperties(ftxui) @@ -86,16 +92,16 @@ target_link_libraries(ftxui-starter ~~~ Build -~~~ +~~~sh mkdir build && cd build cmake .. make ./main ~~~ -# List of modules. +# List of modules. {#modules} -The project is split into 3 modules: +The project is made from into 3 modules: 1. **ftxui/screen** defines a `ftxui::Screen`, this is a grid of `ftxui::Pixel`. @@ -108,7 +114,7 @@ The project is split into 3 modules: using the arrow keys and interact with widgets like checkbox/inputbox/... You can make you own components. -# screen +# screen {#module-screen} It defines a `ftxui::Screen`. This is a grid of `ftxui::Pixel`. A Pixel represent a Unicode character and its associated style (bold, colors, etc...). @@ -132,31 +138,41 @@ The screen can be printed as a string using `ftxui::Screen::ToString()`. } ~~~ -# dom +# dom {#module-dom} -This module defines a hierarchical set of Element. An element manages layout and -can be responsive to the terminal dimensions. +This module defines a hierarchical set of `ftxui::Element`. An element manages +layout and can be responsive to the terminal dimensions. **Example:** ```cpp // Define the document Element document = vbox({ - text("The window") | bold | color(Color::Blue), - gauge(0.5) - text("The footer") - }); + text("The window") | bold | color(Color::Blue), + gauge(0.5) + text("The footer") +}); -// Add a border. +// Add a border, by calling the `ftxui::border` decorator function. document = border(document); + +// Add another border, using the pipe operator. +document = document | border. + +// Add another border, using the |= operator. +document |= border + ``` **List of elements** -You only need one header: ftxui/dom/elements.hpp +They are all defined inside: +```cpp +#include +``` \include ftxui/dom/elements.hpp -## text +## text ## {#dom-text} The most simple widget. It displays a text. ~~~cpp @@ -166,7 +182,44 @@ text("I am a piece of text"); I am a piece of text. ~~~ -## border +## vtext {#dom-vtext} + +Same as `ftxui::text`, but vertical. +~~~cpp +vtext("HELLO"); +~~~ +~~~bash +H +E +L +L +O +~~~ + +## paragraph {#dom-paragraph} + +```cpp +paragraph("A very long text") +``` + +Similar to `ftxui::text`, but this support line wrapping and alignments. The +words are split by spaces + +[Paragraph example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2paragraph_8cpp-example.html) + +![ezgif com-gif-maker (4)](https://user-images.githubusercontent.com/4759106/147251370-983a06e7-6f41-4113-92b8-942f43d34d06.gif) + +See: +```cpp +Element paragraph(std::string text); +Element paragraphAlignLeft(std::string text); +Element paragraphAlignRight(std::string text); +Element paragraphAlignCenter(std::string text); +Element paragraphAlignJustify(std::string text); +``` + + +## border {#dom-border} Add a border around an element ~~~cpp @@ -179,7 +232,27 @@ border(text("The element")) └───────────┘ ~~~ -## window +Same, with the pipe operator: + +```cpp +text("The element") | border +``` + +Border come with different styles. +See: +```cpp +Element border(Element); +Element borderLight(Element); +Element borderHeavy(Element); +Element borderDouble(Element); +Element borderRounded(Element); +Element borderEmpty(Element); +Decorator borderStyled(BorderStyle); +Decorator borderWith(Pixel); +``` + + +## window ## {#dom-window} A `ftxui::window` is a `ftxui::border`, but with some text on top of the border. Add a border around an element @@ -193,7 +266,7 @@ window("The window", text("The element")) └───────────┘ ~~~ -## separator +## separator {#dom-separator} Display a vertical or horizontal line to visually split the content of a container in two. @@ -214,7 +287,29 @@ border( └────┴─────┘ ~~~ -## gauge + +Separators come with different styles: +See: +```cpp +Element separator(void); +Element separatorLight(); +Element separatorHeavy(); +Element separatorDouble(); +Element separatorEmpty(); +Element separatorStyled(BorderStyle); +Element separator(Pixel); +Element separatorCharacter(std::string); +Element separatorHSelector(float left, + float right, + Color background, + Color foreground); +Element separatorVSelector(float up, + float down, + Color background, + Color foreground); +``` + +## gauge {#dom-gauge} A gauge. It can be used to represent a progress bar. ~~~cpp @@ -227,13 +322,28 @@ border(gauge(0.5)) └────────────────────────────────────────────────────────────────────────────┘ ~~~ -## graph +A gauge can be displayed into several directions. See: +```cpp +Element gauge(float ratio); +Element gaugeLeft(float ratio); +Element gaugeRight(float ratio); +Element gaugeUp(float ratio); +Element gaugeDown(float ratio); +Element gaugeDirection(float ratio, GaugeDirection); +``` + +## graph {#dom-graph} @htmlonly @endhtmlonly -## Colors +See: +```cpp +Element graph(GraphFunction); +``` + +## Colors {#dom-colors} A terminal console can usually display colored text and colored background. ~~~cpp @@ -241,7 +351,12 @@ Decorator color(Color); Decorator bgcolor(Color); ~~~ -### Palette16 +FTXUI support every color palette: + +Color [gallery](https://arthursonzogni.github.io/FTXUI/examples_2dom_2color_gallery_8cpp-example.html): +![image](https://user-images.githubusercontent.com/4759106/147248595-04c7245a-5b85-4544-809d-a5984fc6f9e7.png) + +### Palette16 #{#dom-colors-palette-16} On most terminal the following colors are supported: - Default @@ -277,7 +392,7 @@ text("Blue background") | bgcolor(Color::Blue); text("Black on white") | color(Color::Black) | bgcolor(Color::White); ``` -### Palette256 +### Palette256 #{#dom-colors-palette-256} On terminal supporting 256 colors. @htmlonly @@ -288,7 +403,7 @@ On terminal supporting 256 colors. text("HotPink") | color(Color::HotPink); ``` -### TrueColor +### TrueColor #{#dom-colors-true-color} On terminal supporting trueColor, you can directly chose the 24bit RGB color: @@ -303,7 +418,7 @@ ftxui::Color::HSV(uint8_t hue, uint8_t saturation, uint8_t value); @endhtmlonly -## Style +## Style {#dom-style} A terminal console can usually display colored text and colored background. The text can also have different effects: bold, dim, underlined, inverted, blink. @@ -318,6 +433,10 @@ Decorator color(Color); Decorator bgcolor(Color); ~~~ +[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2style_gallery_8cpp-example.html) + +![image](https://user-images.githubusercontent.com/4759106/147244118-380bf834-9e33-40df-9ff0-07c10f2598ef.png) + Example: ~~~cpp underlined(bold(text("This text is bold and underlined"))) @@ -328,22 +447,30 @@ Tips: The pipe operator can be used to chain Decorator: text("This text is bold")) | bold | underlined ~~~ -## Layout +## Layout {#dom-layout} -These layout are similar to the HTML flexbox: -* vbox (Vertical-box) -* hbox (Horizontal-box) -* dbox (Z-axis-box) -They are used to compose all the elements together. Each -children are put side by side. If the container is flexible, the extra space -available will be shared among the remaining flexible children. +Element can be arranged together: + - horizontally with `ftxui::hbox` + - vertically with `ftxui::vbox` + - inside a grid with `ftxui::gridbox` + - wrap along one direction using the `ftxui::flexbox`. + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2vbox_hbox_8cpp-example.html) using `ftxui::hbox`, `ftxui::vbox` and `ftxui::filler`. -`flex(element)` can be used to make a non-flexible element flexible. `filler()` -is a flexible empty element. You can use it align children on one side of the -container. +![image](https://user-images.githubusercontent.com/4759106/147242524-7103b5d9-1a92-4e2d-ac70-b3d6740061e3.png) + + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2gridbox_8cpp-example.htmlp) using `ftxui::gridbox`: -An horizontal flow layout is implemented by: -* hflow (Horizontal flow) +![image](https://user-images.githubusercontent.com/4759106/147242972-0db1f2e9-0790-496f-86e6-ed2c604f7a73.png) + +[Example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/dom/hflow.cpp) using flexbox: + +![image](https://user-images.githubusercontent.com/4759106/147243064-780ac7cc-605b-475f-94b8-cf7c4aed03a5.png) + +[See](https://arthursonzogni.github.io/FTXUI/examples_2dom_2hflow_8cpp-example.html) also this [demo](https://arthursonzogni.com/FTXUI/examples/?file=component/flexbox). + +Element can become flexible using the the `ftxui::flex` decorator. **Examples** ~~~cpp @@ -372,11 +499,39 @@ An horizontal flow layout is implemented by: └────┘└───────────────────────────────────┘└───────────────────────────────────┘ ~~~ +## Table {#dom-table} -# component +A class to easily style a table of data. -The `ftxui/component` directory defines the logic to get produce -interactive component responding to user's events (keyboard, mouse, etc...) +[Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2table_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147250766-77d8ec9e-cf2b-486d-9866-1fd9f1bd2e6b.png) + +## Canvas {#dom-canvas} + +See [](./canvas_8hpp_source.html) + +```cpp + auto c = Canvas(100, 100); + c.DrawPointLine(10, 10, 80, 10, Color::Red); + auto element = canvas(c); +``` + +Drawing can be made on a `ftxui::Canvas`, using braille, block, or simple +characters: + +Simple [example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/dom/canvas.cpp): + +![image](https://user-images.githubusercontent.com/4759106/147245843-76cc62fb-ccb4-421b-aacf-939f9afb42fe.png) + +Complex [examples](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/component/canvas_animated.cpp): + +![ezgif com-gif-maker (3)](https://user-images.githubusercontent.com/4759106/147250538-783a8246-98e0-4a25-b032-3bd3710549d1.gif) + +# component {#module-component} + +The `ftxui::component`module defines the logic to produce interactive component +responding to user's events (keyboard, mouse, etc...) A `ftxui::ScreenInteractive` defines a main loop to render a component. @@ -388,15 +543,23 @@ defines two component. This defines a tree a components, which help properly define how keyboard navigation works. -Predefined components are available in `ftxui/dom/component.hpp`: +`ftxui::Element` are used to render a single frame. On the other side +`ftxui::Component` are used to render dynamic user interface, producing multiple +frame, and updating its state on events. + +[Gallery](https://arthursonzogni.github.io/FTXUI/examples_2component_2gallery_8cpp-example.html) of multiple components. ([demo](https://arthursonzogni.com/FTXUI/examples/?file=component/gallery)) + +![image](https://user-images.githubusercontent.com/4759106/147247330-b60beb9f-e665-48b4-81c0-4b01ee95bc66.png) + +Predefined components are available in ["ftxui/dom/component.hpp"](./component_8hpp.html) \include ftxui/component/component.hpp -Element are stateless object. On the other side, components are used when an -internal state is needed. Components are used to interact with the user with -its keyboard. They handle keyboard navigation, including component focus. +## Input {#component-input} -## Input +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2input_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147247671-f1d6f606-1845-4e94-a4a0-d4273e9ae6bd.png) Produced by: `ftxui::Input()` from "ftxui/component/component.hpp" @@ -404,7 +567,12 @@ Produced by: `ftxui::Input()` from "ftxui/component/component.hpp" @endhtmlonly -## Menu +## Menu {#component-menu} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2menu_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147247822-0035fd6f-bb13-4b3a-b057-77eb9291582f.png) + Produced by: `ftxui::Menu()` from "ftxui/component/component.hpp" @@ -412,7 +580,11 @@ Produced by: `ftxui::Menu()` from "ftxui/component/component.hpp" @endhtmlonly -## Toggle. +## Toggle {#component-toggle} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2toggle_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147249383-e2201cf1-b7b8-4a5a-916f-d761e3e7ae40.png) Produced by: `ftxui::Toggle()` from "ftxui/component/component.hpp" @@ -420,7 +592,11 @@ Produced by: `ftxui::Toggle()` from "ftxui/component/component.hpp" @endhtmlonly -## CheckBox +## CheckBox {#component-checkbox} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2checkbox_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147246646-b86926a9-1ef9-4efb-af98-48a9b62acd81.png) Produced by: `ftxui::Checkbox()` from "ftxui/component/component.hpp" @@ -428,7 +604,11 @@ Produced by: `ftxui::Checkbox()` from "ftxui/component/component.hpp" @endhtmlonly -## RadioBox +## RadioBox {#component-radiobox} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2radiobox_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147246401-809d14a5-6621-4e36-8dd9-a2d75ef2a94e.png) Produced by: `ftxui::Radiobox()` from "ftxui/component/component.hpp" @@ -436,37 +616,154 @@ Produced by: `ftxui::Radiobox()` from "ftxui/component/component.hpp" @endhtmlonly -## Renderer +## Dropdown {#component-dropdown} -Produced by: `ftxui::Renderer()` from \ref "ftxui/component/component.hpp". This +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2dropdown_8cpp-example.html): + +![youtube-video-gif (3)](https://user-images.githubusercontent.com/4759106/147246982-1e821751-531c-4e1f-bc37-2fa290e143cd.gif) + +Produced by: `ftxui::Dropdown()` from "ftxui/component/component.hpp" + +## Slider {#component-slider} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2slider_8cpp-example.html): + +![image](https://user-images.githubusercontent.com/4759106/147249265-7e2cad75-082c-436e-affe-44a550c480ab.png) + +Produced by: `ftxui::Slider()` from "ftxui/component/component.hpp" + +## Renderer {#component-renderer} + +Produced by: `ftxui::Renderer()` from \ref 'ftxui/component/component.hpp'. This component decorate another one by using a different function to render an interface. -## CatchEvent +Example: +```cpp +auto inner = [...] -Produced by: `ftxui::CatchEvent()` from \ref "ftxui/component/component.hpp". +auto renderer = Renderer(inner, [&] { + return inner->Render() | border +}); +``` + +`ftxui::Renderer` also support the component decorator pattern: +```cpp +auto component = [...] +component = component + | Renderer([] (Element e) { return e | border)) + | Renderer(bold) +``` + +As a short hand, you can also compose a component with an element decorator: +```cpp +auto component = [...] +component = component | border | bold; +``` + +## CatchEvent {#component-catchevent} + +Produced by: `ftxui::CatchEvent()` from \ref 'ftxui/component/component.hpp'. This component decorate another one and catch the events before the underlying component. -## Container::Horizontal +Examples: +```cpp +auto screen = ScreenInteractive::TerminalOutput(); +auto renderer = Renderer([] { + return text("My interface"); +}); +auto component = CatchEvent(renderer, [&](Event event) { + if (event == Event::Character('q')) { + screen.ExitLoopClosure()(); + return true; + } + return false; +}); +screen.Loop(component); +``` + +The `ftxui::CatchEvent` can also be used as a decorator: +```cpp +component = component + | CatchEvent(handler_1) + | CatchEvent(handler_2) + | CatchEvent(handler_3) + ; +``` + +## Collapsible {#component-collapsible} + +Useful for section whose visibility can be toggle on/off by the user. +This is basically, a combinaison of a `ftxui::Checkbox` and a `ftxui::Maybe` +components. + +```cpp +auto collabsible = Collapsible("Show more", inner_element); +``` + +## Maybe {#component-maybe} + +Produced by: `ftxui::Maybe()` from \ref `ftxui/component/component.hpp`. +This component decorate another one, by showing/hiding it depending on a boolean +or a predicate. + +Example with a boolean: +```cpp +bool show = true; +auto component = Renderer([]{ return "Hello World!"; }); +auto maybe_component = Maybe(component, &show) +``` + +Example with a predicate: +```cpp +auto component = Renderer([]{ return "Hello World!"; }); +auto maybe_component = Maybe(component, [&] { return time > 10; }) +``` + +`ftxui::Maybe` can be used as a decorator. + +``` +component = component + | Maybe(&a_boolean) + | Maybe([&] { return time > 10; }) + ; +``` + +## Container {#component-container} + +### Horizontal {#component-horizontal} Produced by: `ftxui::Container::Horizontal()` from "ftxui/component/component.hpp". It displays a list of components horizontally and handle keyboard/mouse navigation. -## Container::Vertial +### Vertical {#component-vertical} Produced by: `ftxui::Container::Vertical()` from "ftxui/component/component.hpp". It displays a list of components vertically and handles keyboard/mouse navigation. -## Container::Tab +### Tab {#component-tab} Produced by: `ftxui::Container::Tab()` from "ftxui/component/component.hpp". It take a list of component and display only one of them. This is useful for implementing a tab bar. -## ResizableSplit::{Left, Right, Top, Bottom} +[Vertical](https://arthursonzogni.github.io/FTXUI/examples_2component_2tab_vertical_8cpp-example.html): + +![ezgif com-gif-maker (1)](https://user-images.githubusercontent.com/4759106/147250144-22ff044a-4773-4ff7-a49c-12ba4034acb4.gif) + +[Horizontal](https://arthursonzogni.github.io/FTXUI/examples_2component_2tab_horizontal_8cpp-example.html): + + ![ezgif com-gif-maker (2)](https://user-images.githubusercontent.com/4759106/147250217-fe447e0f-7a99-4e08-948a-995087d9b40e.gif) + + +## ResizableSplit::{Left, Right, Top, Bottom} {#component-resizable-split} + +[Example](https://arthursonzogni.github.io/FTXUI/examples_2component_2resizable_split_8cpp-example.html): + +![ezgif com-gif-maker](https://user-images.githubusercontent.com/4759106/147248372-c55512fe-9b96-4b08-a1df-d05cf2cae431.gif) Produced by: - `ftxui::ResizableSplitLeft()` @@ -483,7 +780,7 @@ mouse. @endhtmlonly -## Force a frame redraw. +## Force a frame redraw. {#component-force-redraw} Whenever a new group of events have been processed: keyboard, mouse, window resize, etc..., the `ftxui::ScreenInteractive::Loop()` is responsible for