Skip to content

Commit

Permalink
fix: added full screen mode and fixed crash on copy (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
idoavrah authored Mar 2, 2024
1 parent 34a3efd commit 970bd17
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ With its latest version you can easily visualize the complete state tree, gainin
- [x] Added dynamic value for "targets" checkbox (checkbox is marked when resources are selected)
- [x] Added a short summary of the suggested plan before applying it
- [x] Added a redacted error tracker on unhandeled exceptions (only when usage reporting is enabled)
- [x] Added a fullscreen mode to allow easier copying of resource / plan parts
- [x] Fixed: search through full module names
- [x] Fixed: Copy to clipboard crashes on some systems

### Version 0.11

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "tftui"
version = "0.12.5"
version = "0.12.6"
description = "Terraform Textual User Interface"
authors = ["Ido Avraham"]
license = "Apache-2.0"
Expand Down
33 changes: 26 additions & 7 deletions tftui/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tftui.state import State, Block, execute_async, split_resource_name
from tftui.plan import PlanScreen
from tftui.debug_log import setup_logging
from tftui.modal import HelpModal, YesNoModal, PlanInputsModal
from tftui.modal import HelpModal, YesNoModal, PlanInputsModal, FullTextModal
from textual import work
from textual.app import App, Binding
from textual.containers import Horizontal
Expand Down Expand Up @@ -224,6 +224,7 @@ def __init__(self, *args, **kwargs):
Binding("escape", "back", "Back"),
("s", "select", "Select"),
Binding("spacebar", "select", "Select"),
("f", "fullscreen", "FullScreen"),
("d", "delete", "Delete"),
("t", "taint", "Taint"),
("u", "untaint", "Untaint"),
Expand Down Expand Up @@ -463,12 +464,17 @@ async def action_untaint(self) -> None:
await self.action_manipulate_resources("untaint")

def action_copy(self) -> None:
if self.switcher.current == "resource":
pyperclip.copy(self.app.tree.current_node.data.contents)
self.notify("Copied resource definition to clipboard")
elif self.switcher.current == "tree":
pyperclip.copy(self.app.tree.current_node.label.plain)
self.notify("Copied resource name to clipboard")
try:
if self.switcher.current == "resource":
pyperclip.copy(self.app.tree.current_node.data.contents)
self.notify("Copied resource definition to clipboard")
elif self.switcher.current == "tree":
pyperclip.copy(self.app.tree.current_node.label.plain)
self.notify("Copied resource name to clipboard")
except Exception:
self.notify(
"Copy to clipboard is unsupported in this terminal", severity="warning"
)

def action_refresh(self) -> None:
self.switcher.current = "tree"
Expand Down Expand Up @@ -506,6 +512,19 @@ def action_search(self) -> None:
self.switcher.current = "tree"
self.search.focus()

def action_fullscreen(self) -> None:
if self.switcher.current not in ("plan", "resource"):
return
self.push_screen(
FullTextModal(
self.tree.current_node.data.contents
if self.switcher.current == "resource"
else self.plan.fulltext,
self.switcher.current == "resource",
)
)
self.plan.focus()

def _handle_exception(self, exception: Exception) -> None:
self.error_message = "".join(
traceback.format_exception(
Expand Down
25 changes: 25 additions & 0 deletions tftui/modal.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@
from textual.containers import Horizontal


class FullTextModal(ModalScreen):
contents = None
is_resource = False

def __init__(self, contents: str, is_resource: bool, *args, **kwargs):
self.contents = contents
self.is_resource = is_resource
super().__init__(*args, **kwargs)

def compose(self) -> ComposeResult:
fullscreen = RichLog(auto_scroll=False)
if self.is_resource:
fullscreen.highlight = True
fullscreen.markup = True
fullscreen.wrap = True

fullscreen.write(self.contents)
yield fullscreen

def on_key(self, event) -> None:
if event.key in ("f", "escape"):
self.app.pop_screen()


class YesNoModal(ModalScreen):
contents = None

Expand Down Expand Up @@ -88,6 +112,7 @@ class HelpModal(ModalScreen):
("ENTER", "View resource details"),
("ESC", "Go back"),
("S / Space", "Select current resource (toggle)"),
("F", "Show resource/plan on full screen; Hold SHIFT/OPTIONS to copy text"),
("D", "Delete selected resources, or highlighted resource if none is selected"),
("T", "Taint selected resources, or highlighted resource if none is selected"),
(
Expand Down
10 changes: 10 additions & 0 deletions tftui/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
class PlanScreen(RichLog):
executable = None
active_plan = None
fulltext = None

BINDINGS = []

Expand All @@ -25,6 +26,7 @@ async def create_plan(self, varfile, targets, destroy="") -> None:
self.active_plan = Text("")
self.auto_scroll = False
self.parent.loading = True
self.fulltext = None
self.clear()
command = [
self.executable,
Expand Down Expand Up @@ -56,6 +58,7 @@ async def create_plan(self, varfile, targets, destroy="") -> None:
data = await proc.stdout.readline()
if not data:
break

self.parent.loading = False
stripped_line = data.decode("utf-8").rstrip()
stylzed_line = Text(stripped_line)
Expand All @@ -66,6 +69,7 @@ async def create_plan(self, varfile, targets, destroy="") -> None:
):
self.clear()
self.auto_scroll = False
self.fulltext = Text("")

if stripped_line == "":
block_color = ""
Expand Down Expand Up @@ -110,6 +114,10 @@ async def create_plan(self, varfile, targets, destroy="") -> None:
stylzed_line.stylize(block_color)

self.write(stylzed_line)

if self.fulltext is not None:
self.fulltext += stylzed_line + Text("\n")

finally:
await proc.wait()
if proc.returncode != 2:
Expand All @@ -121,6 +129,7 @@ async def create_plan(self, varfile, targets, destroy="") -> None:
async def execute_apply(self) -> None:
self.parent.loading = True
self.auto_scroll = True
self.fulltext = Text("")
command = [self.executable, "apply", "-no-color", "tftui.plan"]

logger.debug(f"Executing command: {command}")
Expand All @@ -142,6 +151,7 @@ async def execute_apply(self) -> None:
if text.plain.startswith("Apply complete!"):
text.stylize("bold white")
self.write(text)
self.fulltext += text + Text("\n")
finally:
await proc.wait()
self.active_plan = ""
Expand Down
2 changes: 1 addition & 1 deletion tftui/ui.tcss
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ HelpModal {
grid-rows: 1fr 3;
padding: 0 1;
width: 88;
height: 22;
height: 23;
border: thick $background 80%;
background: $surface;
}
Expand Down

0 comments on commit 970bd17

Please sign in to comment.