# LinearType and ContextManager

**URL:** <https://forum.modular.com/t/lineartype-and-contextmanager/1910>\
**Category:** Mojo\
**Created:** [July 6, 2025, 7:02pm UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910 "2025-07-06T19:02:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rd4com](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@rd4com](https://forum.modular.com/u/rd4com)\
**Post date:** [July 6, 2025, 7:02pm UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/1 "2025-07-06T19:02:33Z")

</div>

Hello,  
i’d like to share an way to create an context-manager that uses LinearTypes.  
Also would appreciate any feedbacks from team on this.  
(ContextManager and requiring ` __copyinit__ ` or not)

This struct greatly improved the API of an UI i’m working on (by a lot),  
while retaining all the benefits that LinearTypes brings.

Example with emojis:

```mojo

#✏️ Note: the struct have no `Movable` `Copyable` !

struct MoveCursor[
    O:MutableOrigin=MutableOrigin.empty,
    border:StyledBorder = __StyleBorderNone,
    border_color: Fg= Fg.default
]():
    var ui: Pointer[UI, O]
    var m: StartedMeasurment[O] #LinearType ⚪
    var after: Bool #Switcher 🔀
    var storage_border: Border[O] #LinearType ⬜

    @staticmethod
    fn AfterThis[border:StyledBorder = __StyleBorderNone, border_color: Fg= Fg.default](
        mut ui:UI, 
        out ret: MoveCursor[__origin_of(ui), border, border_color]
    ):
        ret = __type_of(ret)(ui)
        ret.after=True #Set switch to after ➡️
    
    @staticmethod
    fn BelowThis[border:StyledBorder = __StyleBorderNone, border_color: Fg= Fg.default](
        mut ui:UI, 
        out ret: MoveCursor[__origin_of(ui), border, border_color]
    ):
        ret = __type_of(ret)(ui)
        ret.after=False #Set switch to below ⬇️
    
    fn __init__ (out self, ref[O]ui:UI):
        self.ui = Pointer(to=ui)
        self.m = ui.start_measuring()
        self.after = False #Default switch to ➡️
        @parameter
        if Self.__has_border[border]():
            #Initialize LinearType 🟩 for using it !
            self.storage_border = Border[O](self.ui[])
        else:
            #MarkInitialize LinearType 🟦 for __disable_del() later
            #Line is not here to not encourage unsafe things
            #Users can just initialize the type with an "Do nothing" parameter
    
    @staticmethod
    fn __has_border[b:StyledBorder]()->Bool:
        #If type is "none", return False (types-state)
        return not _type_is_eq[b, __StyleBorderNone]()

    fn __enter__ (mut self): ... #Nothing here, struct uses ` __init__ `
    fn __exit__ (mut self): ... #Nothing here, struct uses ` __del__ `
    
    fn __del__ (owned self):
        @parameter
        if Self.__has_border[border]():
            #Consume 1 🟩 with struct method that does something
            self.storage_border^.end_border[border](self.ui[], border_color)
        else:
            #Consume 2 🟦 with struct method that __disable_del
            self.storage_border^.__unsafe_del()
        
        # ⚪ Consume type into another LinearType (`CompletedMeasurement`)
        var tmp = self.m^.stop_measuring() 
        if self.after: #Check the switch 🔀
            tmp^.move_cursor_after() #Consume 1 🟢
        else:
            tmp^.move_cursor_below() #Consume 2 🔵

```

The result is this API:

```mojo
with MoveCursor.BelowThis[StyledBorderSimple](ui): 
    ...
with MoveCursor.BelowThis[StyledBorderSimple, Fg.magenta](ui):
    ...
with MoveCursor.BelowThis(ui): 
    ...
with MoveCursor.AfterThis[StyledBorderDouble](ui): 
    ...
with MoveCursor.AfterThis[StyledBorderDouble, Fg.magenta](ui): 
    ...
with MoveCursor.AfterThis(ui): 
    ...

```

And compared to the wrapped API:

```mojo
var m = ui.start_measuring()
var b = m.start_border() #b now have origin of m
"Hello world" in ui
b^.end_border[StyledBorderSimple, Fg.blue]() #b end before m
var m_stop = m^.stop_measuring()
m_stop^.move_cursor_below() #all measured, can move draw cursor!

```

Complete example:

> <https://github.com/rd4com/ui-terminal-mojo/commit/135f527253598adac588d1d8c9bb5e743ff6c1ba>
>
> It is an struct that currently does 3 things:
> \- start and stop measuring
> \- move …cursor below or after
> \- integrate optional border with style and colors
> 
> See example:
> \`📂 wip\_api\_playground/context\_managers.mojo\`

---

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [July 6, 2025, 7:29pm UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/2 "2025-07-06T19:29:47Z")

</div>

Your `MovCursor` isn’t annotated to be a Linear type, so instances of it will be deallocated even if they’re not used - breaking the only rule of Linearity: `Types MUST be used exactly once`.

---

<div class="post-metadata">

**Author:** ![rd4com](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@rd4com](https://forum.modular.com/u/rd4com)\
**Post date:** [July 6, 2025, 9:05pm UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/3 "2025-07-06T21:05:29Z")

</div>

Good thinking, linear types are used only once, and wait, here is the twist 😃

Type instances must be consumed only once, and in an specific way,  
either automatically (like this custom ` __del__ `, called by asap), or manually 👍

This ` __del__ ` handles two ways of consuming one type for example.  
(Does not leave any of the instances stored in any fields unconsumed)

Because the ` __del__ ` knows how to dispose of the types, in all branches,  
asap can do the cleanup, so i have to think this is correct.

One cool thing is that this is an ui,  
so if there was a bug, the ui screen would look like mr potato from the movies lol.

In the next example, if ` __del__ ` is removed/commented,  
mojo would have say, hey this lineartype is not del,  
let’s not build this, which is great:

```mojo
@explicit_destroy
struct MyLinear:
    var x: Int
    fn __init__ (out self): self.x=1
    fn remove(owned self): 
        __disable_del(self)

struct NotLinear: #⬅️ Not an linear type
    var val: MyLinear
    fn __init__ (out self): self.val=MyLinear()
    fn __del__ (owned self): self.val^.remove() #⬅️ Try comment this

fn main():
    var value = NotLinear()
    print(value.val.x)

```

Sorry if this is a long response,  
i could be wrong and i appreciate your thinking @melodyogonna ! 🤝  
(please double check this)

---

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [July 7, 2025, 7:45am UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/4 "2025-07-07T07:45:36Z")

</div>

I’m thinking about what happens if I initialize movecursor without doing anything with it, like this:

```python
fn main():
    var cursor = MoveCursor()

```

Your ` __del__ ` assumes I will always call belowThis or AfterThis, but nothing compels me to, so your logic has a soundness problem.

---

<div class="post-metadata">

**Author:** ![rd4com](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@rd4com](https://forum.modular.com/u/rd4com)\
**Post date:** [July 7, 2025, 10:19am UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/5 "2025-07-07T10:19:43Z")

</div>

> [@melodyogonna](#):
>
> `var cursor = MoveCursor()`

Huge thanks, yes that is an very valid observation, and it comes with a new feature!  
on a side note, you could not break the ui by going ahead and doing this:  
(but humbly it is work in progress, so it is far from ‘bug-free’)

```mojo
var cursor = MoveCursor(ui)
"hello" in ui
"dear" in ui
cursor^. __del__ ()
"world" in ui

```

```mojo
"Hello" in ui
for _ in range(100): MoveCursor(ui)
"World" in ui
# output:
# Hello
# World

```

It would move the cursor below, which is the default ui behaviour anyway when not measuring 😃  
(Also what happens when the measured area is [0,0] (width, height))

➡ Again thanks for this lol, it means we could make it movable for recursivity too and enter when needed!

I’d like to not entangle the ui too much in this thread tho,  
because this thread is really about LinearType and ContextManager,  
but that is really interesting, would you like to dive in the repo together sometime !?

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex001/uploads/modular/original/1X/2751e0fbdc595a99718b216730957e9db4448cfd.jpeg) [@system](https://forum.modular.com/u/system)\
**Post date:** [January 3, 2026, 10:20am UTC](https://forum.modular.com/t/lineartype-and-contextmanager/1910/6 "2026-01-03T10:20:17Z")

</div>

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
