@foolc made an additional request via a DM here on the forum for having this also display something in the status bar that tells you when a file is read only.
The change for that is pretty simple, but in the interests of keeping all of this information together in one place for future reference, here’s a complete new plugin that does all of the things outlined in the previous posts with the addition of this new feature. You should use this one rather than the fragments above unless you want to manually make the required modifications.
The plugin (instructions for installing a plugin if you’re unfamiliar can be found here) provides a command for toggling the read only state of a file, which will stop you from being able to type into it. Whenever a file is made read-only, the status bar will say [READONLY]
as an indication of this.
Additionally, there is also an event listener that will allow you to use the main menu augmentation outlined below to open a file in a read only state directly. How this works is explained in a post further up in this thread.
import sublime
import sublime_plugin
def _toggle_read_only(view):
"""
Toggle the read-only state of the provided view, and update the status bar
to provide an indication of the state.
"""
if view.is_read_only():
view.set_read_only(False)
view.erase_status('rostate')
else:
view.set_read_only(True)
view.set_status('rostate', '[READONLY]')
class ToggleReadOnlyCommand(sublime_plugin.ApplicationCommand):
def run(self):
_toggle_read_only(sublime.active_window().active_view())
def is_checked(self):
view = sublime.active_window().active_view()
if view and view.is_read_only():
return True
return False
def is_enabled(self):
return sublime.active_window().active_view() is not None
class ReadOnlyEventListener(sublime_plugin.EventListener):
def on_window_command(self, window, command, args):
if command in ("prompt_open_file", "prompt_open"):
readonly = False if args is None else args.get("readonly", False)
window.settings().set("_open_read_only",readonly)
def on_load(self, view):
if view.window() is not None:
readonly = view.window().settings().get("_open_read_only", False)
view.window().settings().erase("_open_read_only")
if readonly:
_toggle_read_only(view)
You can bind the command to a key easily. If you want an option in the context menu to toggle a file to be read only, create a file named Context.sublime-menu
in your User
package with this content in it (or add this command to an existing file, if you have one).
[
{ "command": "toggle_read_only", "caption": "Read-Only", "mnemonic": "R", "checkbox": true },
]
The menu item will have a checkmark next to it when the current file is read only, as an extra validation.
You can also create a ReadOnly.sublime-commands
file in your User
package with the following content (or choose any other filename; only the extension is important) to add the command to the command palette:
[
{ "caption": "Toggle Read Only", "command": "toggle_read_only" },
]
If you want to be able to open a file directly as a read-only file, create a file named Main.sublime-menu
in your User
package with this content (if you have such a file, you need to merge this in with your existing file):
[
{
"id": "file",
"children":
[
{ "caption": "-" },
{ "command": "prompt_open_file", "caption": "Open File (Read Only)…","platform": "!OSX", "args": {"readonly": true} },
{ "command": "prompt_open", "caption": "Open (Read Only)…", "platform": "OSX", "args": {"readonly": true} },
]
},
]
This will add a entry to the File
menu named Open File (Read Only)...
that will prompt you for a file, which will trigger the event listener in the plugin to toggle the read-only state directly.
As noted above, if you start to open a file and then cancel, followed by dragging a file into the window to open it, the dragged file will open read-only. The simplest expedient is to use the context menu or command palette entry (or key binding, if you made one) to flip the state. This probably won’t happen very often.