Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[flake8]
max-line-length = 88
max-line-length = 120
extend-ignore = E203, W503, E402, E722, F401, F811
exclude =
.git,
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ repos:
hooks:
- id: black
language_version: python3
args: [--line-length=120]

- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
args: [--max-line-length=88, --extend-ignore=E203,W503]

- repo: local
hooks:
Expand Down
7 changes: 7 additions & 0 deletions Agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

We love python fire for commands

Never replace a command that is a binnary like entries_editor edit key for its python prefixed version like python -m pythonsearch.entries_editor edit key


We highly prefer to use python fire to otehr ways of interacting with the program in teh cli. Always check if there is a binary to interact with th program already if so use it.
165 changes: 165 additions & 0 deletions docs/adaptive_window_sizing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Adaptive Window Sizing

PythonSearch now supports adaptive window sizing that automatically adjusts the terminal window size based on your display characteristics. This ensures the search interface looks consistent and appropriately sized across different monitors and resolutions.

## Features

### Automatic Display Detection
- **macOS**: Uses `osascript` and `system_profiler` to detect display resolution and characteristics
- **Linux**: Uses `xrandr` (X11) or `wlr-randr` (Wayland) to get display information
- **Cross-platform**: Falls back to sensible defaults on unsupported platforms

### Adaptive Sizing Algorithm
The adaptive sizing algorithm considers:
- Display resolution (width × height)
- DPI (dots per inch) when available
- Display scale factor for high-DPI displays
- Maintains reasonable bounds to ensure usability

### Display Categories
Windows are automatically sized based on display categories:
- **Small displays** (≤1366px width): Laptops, small monitors
- **Standard HD** (≤1920px width): Most desktop monitors
- **QHD displays** (≤2560px width): High-resolution monitors
- **4K+ displays** (>2560px width): Ultra-high resolution displays

## Configuration Options

### 1. Automatic Adaptive Sizing (Default)
```python
from python_search.configuration.configuration import PythonSearchConfiguration

config = PythonSearchConfiguration(
adaptive_window_sizing=True # This is the default
)
```

### 2. Preset Sizes
Choose from predefined size categories:
```python
config = PythonSearchConfiguration(
adaptive_window_sizing=True,
window_size_preset="medium" # Options: "small", "medium", "large"
)
```

### 3. Custom Fixed Size
Override adaptive sizing with a fixed size:
```python
config = PythonSearchConfiguration(
custom_window_size=(100, 15) # (width_chars, height_chars)
)
```

### 4. Disable Adaptive Sizing
```python
config = PythonSearchConfiguration(
adaptive_window_sizing=False
)
# This will use the default size (86c × 10c)
```

## Environment Variable Overrides

You can override window sizing and display detection at runtime using environment variables:

### Custom Window Size
```bash
export PYTHON_SEARCH_WINDOW_WIDTH='120c'
export PYTHON_SEARCH_WINDOW_HEIGHT='15c'
python_search
```

### Preset Size
```bash
export PYTHON_SEARCH_WINDOW_PRESET='large'
python_search
```

### Display Detection Override
If automatic display detection fails or you want to override it:
```bash
export DISPLAY_WIDTH='2560'
export DISPLAY_HEIGHT='1440'
python_search
```

### Combined Example
```bash
# Force specific display size and use large preset
export DISPLAY_WIDTH='3840'
export DISPLAY_HEIGHT='2160'
export PYTHON_SEARCH_WINDOW_PRESET='large'
python_search
```

## Testing Display Detection

Use the test script to check how your display is detected:

```bash
cd python_search/host_system
python test_display_detection.py
```

This will show:
- Your display resolution and characteristics
- Calculated adaptive window sizes
- Available preset sizes for your display
- Environment variable examples

## Example Output

```
=== Display Detection Test ===
Display Resolution: 2560x1440
DPI: 109.0
Scale Factor: 1.0

=== Adaptive Window Sizing Test ===
Adaptive Window Size: 103c x 12c
Small Adaptive Size: 72c x 10c
Large Adaptive Size: 144c x 18c

=== Preset Sizes ===
Small: 80c x 10c
Medium: 110c x 13c
Large: 150c x 18c
```

## Troubleshooting

### Display Detection Issues
If display detection fails, the system will:
1. Log a warning message
2. Fall back to default dimensions (1920×1080)
3. Use standard preset sizes

### Platform-Specific Notes

#### macOS
- Requires `osascript` for resolution detection
- May need accessibility permissions for some features
- Works best on macOS 10.14+

#### Linux
- Requires `xrandr` for X11 systems
- Requires `wlr-randr` for Wayland systems
- Falls back to environment variables if tools unavailable

#### Windows
- Currently uses fallback values
- Future versions may add Windows-specific detection

### Performance
- Display detection runs once per application launch
- Results are cached for the session
- Minimal performance impact on startup

## Migration from Fixed Sizing

If you were previously using custom window sizes, your configuration will continue to work unchanged. The adaptive sizing only activates when:
1. No `custom_window_size` is specified, AND
2. `adaptive_window_sizing` is True (default)

To migrate to adaptive sizing, simply remove the `custom_window_size` parameter from your configuration.
53 changes: 0 additions & 53 deletions fix_flake8.py

This file was deleted.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ include = ["python_search"] # package names should match these glob patterns ([
exclude = [] # exclude packages matching these glob patterns (empty by default)
namespaces = false # to disable scanning PEP 420 namespaces (true by default)

[tool.black]
line-length = 120

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Expand All @@ -65,3 +68,4 @@ run_key = 'python_search.entry_runner:main'
term_ui = 'python_search.search.search_ui.terminal_ui:main'
register_new_launch_ui = 'python_search.entry_capture.entry_inserter_gui.register_new_gui:launch_ui'
google_it = 'python_search.apps.google_it:main'
share_entry = 'python_search.share_entry:main'
31 changes: 28 additions & 3 deletions python_search/configuration/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
class PythonSearchConfiguration(EntriesGroup):
"""
The main configuration of Python Search
Everything to customize about the application is configurable via code through this class
Everything to customize about the application is configurable via code
through this class
"""

APPLICATION_TITLE = "PythonSearchWindow"
Expand All @@ -34,6 +35,8 @@ def __init__(
tags_dependent_inserter_marks: Optional[dict[str, Tuple[str, str]]] = None,
default_text_editor: Optional[str] = None,
custom_window_size: Optional[Tuple[int, int]] = None,
adaptive_window_sizing: bool = True,
window_size_preset: Optional[Literal["small", "medium", "large"]] = None,
collect_data: bool = False,
entry_generation=False,
privacy_sensitive_terms: Optional[List[str]] = None,
Expand All @@ -45,9 +48,15 @@ def __init__(
:param default_tags:
:param tags_dependent_inserter_marks:
:param default_text_editor:
:param custom_window_size: the size of the fzf window
:param custom_window_size: the size of the fzf window (overrides
adaptive sizing)
:param adaptive_window_sizing: if True, automatically adjust window
size based on display
:param window_size_preset: preset size category ("small", "medium",
"large") when using adaptive sizing
:param use_webservice: if True, the ranking will be generated via a webservice
:param collect_data: if True, we will collect data about the entries you run in your machine
:param collect_data: if True, we will collect data about the entries
you run in your machine
"""
if entries:
self.commands = entries
Expand All @@ -67,6 +76,9 @@ def __init__(
if custom_window_size:
self._custom_window_size = custom_window_size

self.adaptive_window_sizing = adaptive_window_sizing
self.window_size_preset = window_size_preset

self.collect_data = collect_data
self.entry_generation = entry_generation
self.privacy_sensitive_terms = privacy_sensitive_terms
Expand Down Expand Up @@ -97,3 +109,16 @@ def get_fzf_theme(self) -> str:
def get_window_size(self):
if hasattr(self, "_custom_window_size"):
return self._custom_window_size

# Return None to indicate adaptive sizing should be used
return None

def should_use_adaptive_sizing(self) -> bool:
"""Check if adaptive window sizing should be used"""
return getattr(self, "adaptive_window_sizing", True) and not hasattr(
self, "_custom_window_size"
)

def get_window_size_preset(self) -> Optional[str]:
"""Get the window size preset if specified"""
return getattr(self, "window_size_preset", None)
27 changes: 19 additions & 8 deletions python_search/entry_capture/entries_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,29 @@ class EntriesEditor:
Open an ide to edit the entries
"""

ACK_PATH = "/opt/homebrew/bin/ack"

def __init__(self, configuration=None):
if not configuration:
from python_search.configuration.loader import ConfigurationLoader

configuration = ConfigurationLoader().load_config()
self.configuration = configuration

# Ensure ripgrep is available for file searching
self._search_cmd = self._get_search_command()

def _get_search_command(self) -> str:
"""
Ensure ripgrep is available for file searching.
"""
return "/opt/homebrew/bin/rg"

def _build_search_command(self, key: str) -> str:
"""
Build the ripgrep search command.
"""
project_root = self.configuration.get_project_root()
return f"/opt/homebrew/bin/rg -n -i --type py '{key}' {project_root} || true"

def edit_key(self, key_expr: str):
"""
Edits the configuration files by searching the text
Expand All @@ -39,10 +53,7 @@ def edit_key(self, key_expr: str):
return

# needs to be case-insensitive search
cmd = (
f"{EntriesEditor.ACK_PATH} -i '{key}' "
f"{self.configuration.get_project_root()} --python || true"
)
cmd = self._build_search_command(key)
logging.info(f"Command: {cmd}")
result_shell = subprocess.check_output(cmd, shell=True, text=True)

Expand All @@ -54,7 +65,7 @@ def edit_key(self, key_expr: str):
file, line, *_ = result_shell.split(":")
print(f"Editing file and line {file}, {line}")

self._edit_file(file, line)
self._edit_file(file, int(line))

def edit_default(self):
import os
Expand Down Expand Up @@ -88,7 +99,7 @@ def _edit_file(self, file_name: str, line: Optional[int] = 30, dry_run=False):

def _get_open_text_editor_command(self, file, line):
# vim only supported
return f"vim {file} +{line}'"
return f"vim {file} +{line}"


def main():
Expand Down
Loading
Loading