304 Commits
Author SHA1 Message Date
Neko Box Coder 393cf24858 Fixing commandbar/plugin autocomplete regression from #4028 (#4200)
PR #4028 moved the check for autocomplete from action autocomplete to
the buffer one, which caused a few regression for upstream callers
(commandbar autocomplete & plugins that use buffer autocomplete)
that use the buffer autocomplete.

This commit restores pre #4028 behavior by adding a callback variant
for buffer autocomplete functions while keeping the multi-cursor
autocomplete function.
2026-09-01 00:32:35 +02:00
usfbih8uandusfbih8u 1e666bd44e docs(internal/buffer): remove the reference to the old ToCharPos function (#4182)
The function was removed in commit `dc68183fc114ab2911d6ba934cf5df019566d0cf`.

Co-authored-by: usfbih8u <>
2026-08-27 18:03:27 +02:00
redstiandredsti 4c47a2713a Autocomplete support for multiple cursors (#4028)
Co-authored-by: redsti <[email protected]>
2026-08-24 18:45:24 +02:00
usfbih8u 1c8b82b32e fix(buffer/eventhandler): MultipleReplace() comment (#4169) 2026-08-09 13:50:30 +02:00
Jöran Karl ee8f6de484 buffer: Remove buffer invalidation in CloseOpenBuffers() (#4133)
This resolves issue #4131, and a local copy is used to prevent the issue
resolved by #2898 from recurring.
2026-07-09 18:48:34 +02:00
Jöran Karl 253065a4af Merge pull request #3997 from JoeKar/fix/symlinks
buffer: Store potential resolved symlinks as `AbsPath`
2026-05-04 19:07:24 +02:00
Jöran Karl 2cb49c4653 buffer: Resolve symlinks in file paths
Otherwise we can't identify if we have the same file open multiple times via
different symlinks.
The test must be adapted to resolve symlinks in `findBuffer()`.
2026-04-28 19:20:51 +02:00
Jöran Karl e323cde09c buffer: Don't Serialize in case the buffer is shared
Otherwise we unnecessarily serialize the shared buffer every time when closing
a bufpane with this buffer, so every such serialize overwrites the previous one,
thus only the last serialize (when closing the last instance of the buffer, i.e.
when actually closing the file, i.e. when the buffer is not shared anymore) will
be used anyway.
2026-04-08 16:17:38 +02:00
Jöran Karl ef57bdcf9b buffer: Don't cancel the backup in case the buffer is shared
Otherwise it will be removed async, which shouldn't happen in case there is
still one buffer open with the same modified file.
2026-04-08 16:17:38 +02:00
Nilton Perim Neto 8f14c3c315 buffer: check sudo binary exists before creating backup
Verify the sudo command is available via exec.LookPath() before
creating the backup in safeWrite(). This avoids bogus backup files
when the sudo binary is not found.

Signed-off-by: Nilton Perim Neto <[email protected]>
2026-04-02 13:59:00 -03:00
Nilton Perim Neto d9ad8310b2 buffer: fix sudo TTY race on privileged file save
When saving a protected file, micro spawned two sudo dd subprocesses
concurrently: a truncation dd and a write dd. Both competed for the
TTY to prompt for the sudo password, racing on TCGETS2/TCSETS2 ioctls
and deadlocking stdin routing. This strictly fails with sudo-rs, which
enforces auditable escalation boundaries.

Fix by removing notrunc and the separate truncation subprocess entirely.
A single dd subprocess now handles truncation and write in one shot,
making the race impossible by construction. The conv=fsync guarantee is
preserved on platforms that support it.

Move writeBackup() before openFile() in safeWrite() for the sudo path
so the backup always exists before dd truncates the file. If openFile()
fails after the backup is created, return OverwriteError so the user
knows their data is safe in the backup. The non-sudo path is unchanged.

Link: https://github.com/micro-editor/micro/issues/4050
Signed-off-by: Nilton Perim Neto <[email protected]>
2026-04-02 13:59:00 -03:00
bibaka 4ddf4fe2b1 Rewrite Loc.MoveLA(n): do not call util.Abs(n) in cycle, cleaner code 2026-03-28 02:12:08 +03:00
bibaka 1be75cc697 Fix documentation for Loc.LessThan() and other similar functions 2026-03-28 02:09:00 +03:00
Dmytro Maluka 4aa706cbc5 serialize: Don't save undo stack if saveundo=off (#4003)
Micro always saves the undo stack information into the serialized buffer
file as long as either `saveundo` or `savecursor` is enabled. Whereas in
the case when only `savecursor` is enabled, while `saveundo` is
disabled, this information is not used afterwards, so it only wastes the
disk space in `~/.config/micro/buffers`. (And given that currently micro
never automatically removes any serialized buffer files, it may
significantly contribute to the overall ever growing size of the
`~/.config/micro/buffers` directory.)

So avoid saving the undo info if `saveundo` is disabled. This makes the
size of each serialized buffer file with savecursor=on saveundo=off
small and predictable, e.g. around 600 bytes in my observations (whereas
without this fix, it may grow indefinitely big, depending on the number
of modifications the user made before saving the file).
2026-02-10 20:32:16 +01:00
Jöran Karl ab8c242044 gofmt after renaming the URL 2026-01-21 20:29:57 +01:00
Jöran Karl 4ead0e453b Change zyedidia/micro to micro-editor/micro 2026-01-21 20:29:55 +01:00
Dmytro Maluka 118f5a3e35 gofmt fix 2025-12-03 01:19:35 +01:00
matthias314 a577fc95ff handle regexps with missing \E (quick fix for #3700) 2025-11-25 17:19:26 -05:00
Jöran Karl bab39079b3 save: Remove a possible written backup in case the path has changed 2025-10-18 21:07:07 +02:00
Jöran Karl 02611f4ad2 backup: Keep path of stored & hashed backup files in a own $hash.path file
Since full escaped backup paths can become longer than the maximum filename size
and hashed filenames cannot be restored it is helpful to have a lookup file for
the user to resolve the hashed path.
2025-10-18 21:07:06 +02:00
Jöran Karl 1ce2202d9a util: Convert suffix added with AppendBackupSuffix() to simple constant 2025-10-18 21:06:47 +02:00
niten94 85b4b2b788 Disable sudo save prompt on Windows
Display message stating that saving with sudo is unsupported on Windows,
immediately without a prompt when permission is denied.
2025-09-21 00:30:07 +08:00
Luca Stefani e9f241af71 micro: Handle +/regex search from args (#3767)
This is a feature found in vim and commonly used
by Linux kernel test robots to give context about
warnings and/or failures.

e.g. vim +/imem_size +623 drivers/net/ipa/ipa_mem.c

The order in which the commands appear in the args
determines in which order the "goto line:column"
and search will be executed.
2025-09-05 20:53:37 +02:00
deepdring b8057f28c6 refactor: use a more modern writing style to simplify code (#3834)
Signed-off-by: deepdring <[email protected]>
2025-08-26 02:00:51 +02:00
Jöran Karl 1dbb058773 Merge pull request #3814 from JoeKar/fix/sudo-save
save: Use `dd` with the `notrunc` & `fsync` and postpone truncation
2025-08-12 19:37:16 +02:00
Jöran Karl 165a5a4896 save: Use dd with the notrunc & fsync option
Using notrunc  will stop the overall truncation of the target file done by sudo.
We need to do this because dd, like other coreutils, already truncates the file
on open(). In case we can't store the backup file afterwards we would end up in
a truncated file for which the user has no write permission by default.
Instead we use a second call of `dd` to perform the necessary truncation
on the command line.
With the fsync option we force the dd process to synchronize the written file
to the underlying device.
2025-08-06 20:13:36 +02:00
Dmytro Maluka 0a9fa4f2ea Always use temporary file when writing backup
When writing a backup file, we should write it atomically (i.e. use a
temporary file + rename) in all cases, not only when replacing an
existing backup. Just like we do in util.SafeWrite(). Otherwise, if
micro crashes while writing this backup, even if that doesn't result
in corrupting an existing good backup, it still results in creating
an undesired backup with invalid contents.
2025-08-03 18:41:34 +02:00
Dmytro Maluka a862c9709e Unify backup write logic
Use the same backup write helper function for both periodic
background backups and for temporary backups in safeWrite().

Besides just removing code duplication, this brings the advantages
of both together:

- Temporary backups in safeWrite() now use the same atomic mechanism
  when replacing an already existing backup. So that if micro crashes
  in the middle of writing the backup in safeWrite(), this corrupted
  backup will not overwrite a previous good backup.

- Better error handling for periodic backups.
2025-08-03 18:37:00 +02:00
Dmytro Maluka 04b878bc2d Ignore the backup option when removing backup
When we need to remove existing backup for whatever reason (e.g. because
we've just successfully saved the file), we should do that regardless of
whether backups are enabled or not, since a backup may exist regardless
(it could have been created before the `backup` option got disabled).
2025-08-03 16:32:25 +02:00
Dmytro Maluka 7aa495fd3f Remove backup when buffer becomes unmodified
We should cancel previously requested periodic backup (and remove this
backup if it has already been created) not only when saving or closing
the buffer but also in other cases when the buffer's state changes from
modified to unmodified, i.e. when the user undoes all unsaved changes.

Otherwise, if micro terminates abnormally before the buffer is closed,
this backup will not get removed (so next time micro will suggest the
user to recover this file), even though all changes to this file were
successfully saved.
2025-08-03 16:17:53 +02:00
Dmytro Maluka 2c010afbe4 Fix races between removing backups and creating periodic backups
Micro's logic for periodic backup creation is racy and may cause
spurious backups of unmodified buffers, at least for the following
reasons:

1. When a buffer is closed, its backup is removed by the main goroutine,
   without any synchronization with the backup/save goroutine which
   creates periodic backups in the background.

   A part of the problem here is that the main goroutine removes the
   backup before setting b.fini to true, not after it, so the
   backup/save goroutine may start creating a new backup even after it
   has been removed by the main goroutine. But even if we move the
   b.RemoveBackup() call after setting b.fini, it will not solve the
   problem, since the backup/save goroutine may have already started
   creating a new periodic backup just before b.fini was set to true.

2. When a buffer is successfully saved and thus its backup is removed,
   if there was a periodic backup for this buffer requested by the main
   goroutine but not saved by the backup/save goroutine yet (i.e. this
   request is still pending in backupRequestChan), micro doesn't cancel
   this pending request, so a backup is unexpectedly saved a couple of
   seconds after the file itself was saved.

   Although usually this erroneous backup is removed later, when the
   buffer is closed. But if micro terminates abnormally and the buffer
   is not properly closed, this backup is not removed. Also if this
   issue occurs in combination with the race issue #1 described above,
   this backup may not be successfully removed either.

So, to fix these issues:

1. Do the backup removal in the backup/save goroutine (at requests from
   the main goroutine), not directly in the main goroutine.

2. Make the communication between these goroutines fully synchronous:

2a. Instead of using the buffered channel backupRequestChan as a storage
    for pending requests for periodic backups, let the backup/save
    goroutine itself store this information, in the requestesBackups
    map. Then, backupRequestChan can be made non-buffered.

2b. Make saveRequestChan a non-buffered channel as well. (There was no
    point in making it buffered in the first place, actually.) Once both
    channels are non-buffered, the backup/save goroutine receives both
    backup and save requests from the main goroutine in exactly the same
    order as the main goroutine sends them, so we can guarantee that
    saving the buffer will cancel the previous pending backup request
    for this buffer.
2025-08-03 16:17:03 +02:00
Dmytro Maluka e84d44d451 Move backup & save related stuff from Buffer to SharedBuffer
Various methods of Buffer should be rather methods of SharedBuffer. This
commit doesn't move all of them to SharedBuffer yet, only those that
need to be moved to SharedBuffer in order to be able to request creating
or removing backups in other SharedBuffer methods.
2025-08-03 14:53:29 +02:00
Dmytro Maluka f938f62e31 Make isModified reflect actual modified/unmodified state of buffer
Instead of calculating the hash of the buffer every time Modified() is
called, do that every time b.isModified is updated (i.e. every time the
buffer is modified) and set b.isModified value accordingly.

This change means that the hash will be recalculated every time the user
types or deletes a character. But that is what already happens anyway,
since inserting or deleting characters triggers redrawing the display,
in particular redrawing the status line, which triggers Modified() in
order to show the up-to-date modified/unmodified status in the status
line. And with this change, we will be able to check this status
more than once during a single "handle event & redraw" cycle, while
still recalculating the hash only once.
2025-08-03 14:48:26 +02:00
Dmytro Maluka 4ade5cdf24 Make calcHash() a method of SharedBuffer
This will make it easier to use calcHash() in other SharedBuffer
methods.
2025-08-03 14:47:27 +02:00
Jöran Karl 87ce5738e1 save: gofmt 2025-07-23 22:00:10 +02:00
Neko Box Coder d7e43d4974 Adding missing file closes, rewriting safeWrite() to be more robust (#3807) 2025-07-22 22:58:18 +02:00
cutelisp 3a7705a090 Enhance GetNativeValue 2025-07-11 11:21:40 +02:00
Jöran Karl 1eef4bb3e0 Convert leftover usages of path to filepath 2025-04-26 20:37:49 +02:00
niten94 0d5b2b73e3 Skip save on open or term command if buffer is shared 2025-04-18 19:19:19 +08:00
Dmytro Maluka eadc402ae0 Import paths: fix non-alphabetic order
Make gofmt happy about that.
2025-03-24 23:01:48 +01:00
Neko Box Coder 82b700390d ReloadSettings only when we need to when saving a file (#3688) 2025-03-12 22:06:24 +01:00
Jöran Karl 8b21724c6e buffer: Store the encoding inside the buffer 2025-02-28 19:02:16 +01:00
Jöran Karl 6164050425 save: Update the modification time of the buffer only in case of file changes 2025-02-28 18:57:53 +01:00
Jöran Karl 49aebe8aca save+util: Provide a meaningful error message for safe (over-)write fails 2025-02-28 18:57:53 +01:00
Jöran Karl 79ce93fb7d backup: Clear the requested backup upon completion notification
Now the main go routine takes care of the backup synchronization.
2025-02-28 18:57:53 +01:00
Jöran Karl 771aab251c save+backup: Process the save & backup with a sequential channel
As advantage we don't need to synchonize them any longer and
don't need further insufficient lock mechanisms.
2025-02-28 18:57:53 +01:00
Jöran Karl 35d295dd04 buffer: Remove superfluous backupTime 2025-02-28 18:57:53 +01:00
Jöran Karl 8c883c6210 backup: Rearrange and extend BackupMsg 2025-02-28 18:57:53 +01:00
Jöran Karl c4dcef3e66 micro: Provide recovery of settings.json & bindings.json 2025-02-28 18:57:53 +01:00
Jöran Karl 9592bb1549 save: Further rework of overwriteFile()
- extract the open logic into `openFile()` and return a `wrappedFile`
- extract the closing logic into `Close()` and make a method of `wrappedFile`
- rename `writeFile()` into `Write()` and make a method of `wrappedFile`

This allows to use the split parts alone while keeping overwriteFile() as simple
interface to use all in a row.
2025-02-28 18:57:53 +01:00