Code Monkey home page Code Monkey logo

textmate2-ruff-linter's Introduction

Version TextMate macOS macOS M2 M3 Ruff Powered by Rake

Python Ruff Linter for TextMate2

Ruff is an extremely fast Python linter, written in Rust. This is the TextMate bundle implementation of ruff linter with fantastic features 🎉

Demo 1


Installation

You need to install ruff. I prefer brew. It’s also available via pip. Set the TM_PYRUFF variable to your ruff binary. There is a fall-back mechanism, if you have already installed ruff, bundle check the command existance with command -v ruff if TM_PYRUFF is not set. If both fails, you need to set the value of TM_PYRUFF by hand :)

brew install ruff
cd "${HOME}/Library/Application\ Support/TextMate/Bundles/"
git clone https://github.com/vigo/textmate2-ruff-linter.git Python-Ruff-Linter.tmbundle

TextMate sometimes doesn’t apply environment variable creation from command-line. If this doesn’t work, you need to apply/set manually from TextMate > Settings > Variables pull down menu.

$ defaults write com.macromates.TextMate environmentVariables \
    -array-add "{enabled = 1; value = \"$(command -v ruff)\"; name = \"TM_PYRUFF\"; }"

# enable auto fix
$ defaults write com.macromates.TextMate environmentVariables \
    -array-add "{enabled = 1; value = \"true\"; name = \"TM_PYRUFF_ENABLE_AUTOFIX\"; }"

You can set environment variables on a project basis if you prefer. For this, you can use the .tm_properties file under anywhere in your project root:

.tm_properties example:

TM_PYRUFF=/path/to/bin/ruff
TM_PYRUFF_ENABLE_AUTOFIX=1   # if you want to enable autofix by default

For older users like myself, you can define the tooltip to make it easier to read:

defaults write com.macromates.TextMate NSToolTipsFontSize 24

Bonus

When you press ⌥ (option) + R error reporting pops. TextMate’s built-in markdown parser is super outdated, this is normal. I’ve modified the original Markdown.pl file and shared under Goodies/ folder. Just copy the file under correct location:

# backup the original first :)
cp "~/Library/Application Support/TextMate/Managed/Bundles/Bundle Support.tmbundle/Support/shared/bin/Markdown.pl" "~/Library/Application Support/TextMate/Managed/Bundles/Bundle Support.tmbundle/Support/shared/bin/Markdown-original.pl"

# replace with new one.
cp Goodies/Markdown.pl "~/Library/Application Support/TextMate/Managed/Bundles/Bundle Support.tmbundle/Support/shared/bin/"

You should see fancy code-blocks parsed as expected:

Better Markdown Preview


TextMate Variables

Variable Default Value Description
ENABLE_LOGGING Set for development purposes
TM_PYRUFF Binary path of ruff
TM_PYRUFF_DISABLE Disable bundle
TM_PYRUFF_ENABLE_AUTOFIX Autofix fixables on save
TM_PYRUFF_OPTIONS Pass custom options if there is no config file
TM_PYRUFF_GFM_ZOOM_FACTOR 100% Zoom factor for report errors screen

Demo 3

Usage

After setting the TM_PYRUFF variable, you need to select the language as Python Ruff.

IMPORTANT: Bundle ships with TextMate grammar: Python Ruff. You must set your language scope to Python Ruff for the bundle to function/work properly. Scope automatically loads source.python and source.python.django grammars. Due to TextMate’s callback flow, I was forced to create a separate scope. Otherwise, it would conflict with all bundles that use source.python. Due to this situation, previous version was working too slow.

When you hit + S (save the file) bundle runs:

  • Import sorting
  • Code formatting
  • Autofixing autofixable errors if TM_PYRUFF_ENABLE_AUTOFIX is set.

You don’t need to enable TM_PYRUFF_ENABLE_AUTOFIX by default. You can manually trigger by pressing + A (Option + A)

If you have lint errors, you can directly navigate error by pressing + G (Option + G). User cursor keys (Up/Down) and hit enter to jump related line:column.

Enable / Disable Bundle or Features

To completely disable the bundle, simply assign a value to TM_PYRUFF_DISABLE. This allows you to proceed as if the bundle does not exist. Additionally, if the first line of your Python file contains comment TM_PYRUFF_DISABLE:

# TM_PYRUFF_DISABLE
print('ok')

If you want to enable autofix set TM_PYRUFF_ENABLE_AUTOFIX variable (any value):

TM_PYRUFF_ENABLE_AUTOFIX=1

You can also pass extra options with using TM_PYRUFF_OPTIONS variable. If you don’t have .ruff.toml, you can set TM_PYRUFF_OPTIONS for custom format or custom check operations (via .tm_properties or TextMate > Settings > Variables):

.tm_properties file:

TM_PYRUFF_OPTIONS="--config \"format.quote-style = 'single'\""

TextMate > Settings > Variables (you don’t need to escape quotes):

TM_PYRUFF_OPTIONS  --config "format.quote-style = 'single'"

Keep in mind, TM_PYRUFF_OPTIONS passed on format and check operations.


Hot Keys and Snippets

Hot Keys and TAB Completions Description
+ F (option + F) Trigger autofix manually
+ A (option + A) Add # NOQA to all problematic lines
+ G (option + G) Go to error marked line/column
+ T (option + T) tm_properties helper
+ T (option + T) .ruff.toml config helper
+ D (option + D) Enable / Disable (toggle) format for selected lines
+ R (option + R) Report errors (rule descriptions) for current errors
disable + (type "disable") Adds # TM_PYRUFF_DISABLE text
noq + (type "noq") Some noqa options
envi + (type "envi") Insert environment variables, works in tm_properties

Demo 2


Bug Report

Please set/enable the logger via setting ENABLE_LOGGING=1. Logs are written to the /tmp/textmate-ruff.log file. You can tail while running via; tail -f /tmp/textmate-ruff.log in another Terminal tab. You can see live what’s going on. Please provide the log information for bug reporting.

After you fix the source code (next run) bundle removes those files if there is no error. According to you bug report, you can tail or copy/paste the contents of error file to issue.

Also, while running bundle script (which is TextMate’s default ruby 1.8.7), if error occurs, TextMate pops up an alert window. Please add that screen shot or try to copy error text from modal dialog.

Logger output should look like this:

[2024-05-11 00:49:07][Python-RUFF][WARN][storage.rb->destroy]: storage.destroy not found for 097AA1A0-89C7-4686-A3BC-F0585962E974 - (/tmp/textmate-ruff-097AA1A0-89C7-4686-A3BC-F0585962E974.error)
[2024-05-11 00:49:07][Python-RUFF][INFO][storage.rb->destroy]: storage.destroy for 097AA1A0-89C7-4686-A3BC-F0585962E974 - (/tmp/textmate-ruff-097AA1A0-89C7-4686-A3BC-F0585962E974.goto)
[2024-05-11 00:49:07][Python-RUFF][DEBUG][linter.rb->run]: cmd: /opt/homebrew/bin/ruff | nil input: true | args: ["check", "--add-noqa"]
[2024-05-11 00:49:07][Python-RUFF][WARN][linter.rb->noqalize]: err: "Added 5 noqa directives.\n"
[2024-05-11 00:49:15][Python-RUFF][WARN][storage.rb->destroy]: storage.destroy not found for 097AA1A0-89C7-4686-A3BC-F0585962E974 - (/tmp/textmate-ruff-097AA1A0-89C7-4686-A3BC-F0585962E974.error)
[2024-05-11 00:49:15][Python-RUFF][DEBUG][linter.rb->run]: cmd: /opt/homebrew/bin/ruff | nil input: false | args: ["check", "--select", "I", "--fix", "-"]
[2024-05-11 00:49:15][Python-RUFF][DEBUG][linter.rb->run]: cmd: /opt/homebrew/bin/ruff | nil input: false | args: ["format", "-"]
[2024-05-11 00:49:15][Python-RUFF][ERROR][ruff_linter.rb->run_document_will_save]: errors_format_code: nil
[2024-05-11 00:49:15][Python-RUFF][WARN][storage.rb->get]: storage.get not found for 097AA1A0-89C7-4686-A3BC-F0585962E974 (/tmp/textmate-ruff-097AA1A0-89C7-4686-A3BC-F0585962E974.error)
[2024-05-11 00:49:15][Python-RUFF][DEBUG][linter.rb->run]: cmd: /opt/homebrew/bin/ruff | nil input: true | args: ["check", "--output-format", "grouped"]

Keep in mind that when logging is enabled, there may be some performance degradation due to file I/O operations.


Personal Notes

I know and unfortunately, this wonderful editor, TextMate, is now in its final days. I could not use many of the beauties from the UI library that it spawned. The built-in Ruby 1.8.7, Ruby 2 have always been compiled according to the old CPU architecture and when I use nib files, TextMate randomly hangs and crashes at random times.

I couldn’t use the built-in autocompletion features and similar alert mechanisms. (I can generate tooltips in HTML format, but it crashes after a while).

If you are still using TextMate like me, I eagerly await your comments, bug reports, and feature requests.


Change Log

2024-05-29

  • Add ruff version to results
  • Add Disable Ruff for file with noq+TAB (adds # ruff: noqa)

2024-05-14

  • Improve code structure (modules)
  • Add report errors (rule description) preview with option+R
  • Add import sort disabler (noq<TAB>)

You can read the whole story here.


Contributor(s)


Contribute

All PR’s are welcome!

  1. fork (https://github.com/vigo/textmate2-ruff-linter/fork)
  2. Create your branch (git checkout -b my-features)
  3. commit yours (git commit -am 'implement new features')
  4. push your branch (git push origin my-features)
  5. Than create a new Pull Request!

This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.


License

This project is licensed under MIT


textmate2-ruff-linter's People

Contributors

dwt avatar vigo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

dwt

textmate2-ruff-linter's Issues

[BUG] Error message is appended to current file when E999 syntax error is found

Describe the bug

When a "E999 syntax error" is found, the text of the error is appended to the end of the current file. This additional text must be removed by hand to continue.

To Reproduce

Steps to reproduce the behavior:

  1. Open a TextMate file in Python Ruff mode
  2. Type syntaxically incorrect text eg a single line "1 = a"
  3. Save file
  4. The text Error error: Failed to parse test.py:1:1: Invalid assignment targettest.py: 1:1 E999 SyntaxError: Invalid assignment targetFound 1 error. is appended at the end to the opened file
    Untitled

Expected behavior

The error should only appear in the hovering window

Logs

Environment (please complete the following information):

  • OS: macOS 14.5 (23F79)
  • CPU: M3
  • TextMate version: 2.0.23
  • Bundle version: 1.1.5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.