Vim, Visual Studio Code, and Jetbrains GoLand are probably your best bets out of the 11 options considered. 'Lightweight and fast' is the primary reason people pick Vim over the competition. This page is powered by a knowledgeable community that helps you make an informed decision. Goland has a B.A. From Harvard University and an M.D. From Columbia University College of Physicians & Surgeons. She was a resident and chief medical resident at NY-Presbyterian Hospital and did her endocrinology research training at Columbia University.
Vim, Visual Studio Code, and Jetbrains GoLand are probably your best bets out of the 11 options considered. 'Lightweight and fast' is the primary reason people pick Vim over the competition. This page is powered by a knowledgeable community that helps you make an informed decision. Even though GoLand supports running ‘go fmt’ on save, users regularly request making this option more discoverable or even enabling it by default.
Eugene Goland is an entrepreneur and executive with over 25 years of experience in the IT market. He is a co-founder of LSE-listed Mail.ru, one of the top five largest Internet companies in Russia, founded within DataArt and later sold to a private equity firm.
GoLandEven though GoLand supports running ‘go fmt’ on save, users regularly request making this option more discoverable or even enabling it by default. In this article, I’d like to describe some of the obstacles that make doing this difficult, analyze some solutions to the same problem from other IDEs, and reflect on the paths that GoLand can take to address this request. This blog post’s primary purpose is to collect as much user feedback as possible before implementing anything. If you believe that what GoLand provides now is not enough or could work better, please read the post and share your thoughts with us.
Note: For the sake of brevity, I’m assuming you know what ‘go fmt’ is. If you’re new to the language, you might want to familiarize yourself with the topic before continuing reading.
The current state
Currently, GoLand offers three ways to interact with ‘go fmt’: dedicated actions, before commit tools, and file watchers.
Under the Tools | Go Tools menu, you can find two actions related to code formatting: Go Fmt File and Go Fmt Project. Each has a shortcut assigned to it: Alt + Shift + Control + F (Alt + Shift + Cmd + F on macOS) and Alt + Shift + Control + P (Alt + Shift + Cmd + P), respectively. The sole purpose of these actions is to run ‘go fmt’, providing it with either file paths or a path to the project directory, and they only work when you invoke them manually.
There are several hooks that can be run before a commit. They can be configured via Settings (Preferences on macOS) | Version Control | Commit | Before Commit. There you can find Go fmt, which is enabled by default.
The third way is to configure a file watcher. Under Settings (Preferences), you can find Tools | File Watchers. It’s easy to add a new watcher by using the predefined ‘go fmt’ template. Whenever a Go file is changed, the command is executed on it. The key word in this case is “whenever,” as users don’t have full control over the precise moment a file gets modified. I’ll describe this problem in more detail in the next session.
Saving private files
There are many reasons why file contents can be changed, but we can roughly divide them into two groups: external (with respect to the IDE) and internal.
By an external reason, I mean a tool modifies file content on disk. It could be Git pulling updates, another editor modifying a file, and so on. A file watcher can be configured to run ‘go fmt’ on external changes, but this option is disabled by default. The main concern here is the user experience. Let’s imagine the following situation. You have no changes. Then you update the project using, say, ‘git pull’. Some files are changed on disk, so the IDE runs ‘go fmt’ on them. If they were committed with non-canonical formatting, they are updated. Thus you now have modified files even though your only intention was to update the project. While it might seem like a good idea to just go ahead and commit them, that’s probably not what you opened the IDE to do.
If you’ve never used GoLand before, you may be surprised that there is more than one internal reason to modify file content. Indeed, conventional text editors typically have a straightforward workflow. You open a file and modify it, and then you either explicitly save it or close the editor, losing your changes. IntelliJ-based IDEs, such as GoLand, work differently. They can save a file for a lot of different reasons. You can control some of these reasons, such as the option to save your file upon IDE frame deactivation, via Settings (Preferences) | Appearance & Behavior | System Settings | Autosave. Others are beyond the user’s control. Building/running, performing VCS operations, and closing a file are among such reasons. File | Local History is available to help you restore a previous file snapshot if necessary.
The conclusion I’d like to emphasize from the above description of the IDE’s behavior is that the meaning of “on-save” in GoLand is not quite the same as it is for other editors. Even if ‘go fmt’ is enabled by default in GoLand, the resulting experience will be different from what users expect. At this point, we should probably step back and think about why one might want to reformat code automatically and regularly. But that is a large topic that probably deserves a separate post. Also, I’m afraid that even if we find a satisfying answer for this question, there would still be yet another hurdle that is extremely hard to overcome – habit. Recently, more and more developers have been switching to GoLand from conventional editors. And though the IDE can’t support all of their workflows, we should still try to make them feel as comfortable as possible in the new environment.
Problems to solve
There are a few problems that appear when using an external tool to reformat code.
First of all, GoLand already has an embedded code formatter. Does it make sense to continue supporting it, or can it be replaced with ‘go fmt’ entirely? There are at least two reasons to keep it. First, the IDE sometimes needs to reformat blocks of code that don’t yet belong to project files. For instance, refactorings often create code snippets that have to be properly formatted before being inserted into a file. Using an external tool every time a case like this arises would be inefficient. Second, GoLand’s formatter has a couple of features that are missing from ‘go fmt’. For instance, the GoLand formatter works with syntactically incorrect code and can be invoked on an arbitrary block, automatically inserts semicolons, and wraps parameters and arguments. These factors suggest a significant, and we think unacceptable, downside to switching to ‘go fmt’ completely.
![GoLand GoLand](/uploads/1/3/4/8/134879703/304235396.jpg)
If we decide to keep both formatters, however, how should we make them work together? Several different workflows would need to be supported. For instance, there are existing users of JetBrains IDEs who are used to invoking the formatter manually. They are satisfied with how things are now, but they can get frustrated when automatic formatting intervenes at seemingly random moments. Then there are people who would like to have ‘go fmt’ on save but still want to benefit from GoLand’s additional formatter features. Other users might want to configure a combination of the two formatters, along with separate ways to run them. These all should probably be addressed by a potential configuration.
Finally, running ‘go fmt’ on a file requires first saving it on disk. This doesn’t seem to be a problem in terms of performance, since almost everyone uses SSD nowadays. But it doesn’t always work well in terms of UX. GoLand does its best to preserve caret position and selection after an external change, but this is not always possible. Keeping content modification on the IDE side could solve this problem, and this is how it’s done in the Prettier and Dart plugins. What I particularly like about ‘dartfmt’ is that it accepts a caret offset and selection, and returns them modified, so there’s no job left to do for the editor.
Possible action points
The first action point could be to implement the ability to run GoLand’s formatter when the IDE saves files, either automatically or when the user saves manually with Ctrl + S (Cmd + S). The main benefit is that this would allow the user to have an on-save formatter without losing the enhanced IDE formatting features. Excluding external changes makes it possible to preserve a consistent UX for the feature.
The second action point would be to add an option to enable a ‘go fmt’ pass after running GoLand’s formatter. This would allow the user to invoke both formatters using the same key combination, Ctrl + Alt + L (Cmd + Alt + L) by default. This has the advantage of offering the features of GoLand and the consistency of the language tooling. When combined with the first action point, it solves the original problem of running ‘go fmt’ on save.
The third possible action point is to migrate to ‘go fmt’, which is effectively ‘gofmt -l -w’, to ‘gofmt’ without options. This would allow the IDE to have better control over content modification. Additionally, it would be great to investigate whether it’s possible to delegate offset computation to ‘gofmt’ itself. This would make it possible to replace the IDE’s heuristics with exact numbers, as ‘gofmt’ could potentially track offsets using AST.
Conclusion
We have not yet started working on this feature, so now is the best time to provide your feedback on our thoughts and plans. What’s missing? Are there any workflows that are not supported? How could it work better? Every opinion is valuable. Please feel free to comment under this post, post your thoughts in the issue, or contact us in whateverway is the most comfortable for you. Thanks in advance, and thank you for reading.
I recently decided to buy the X-keys L-Trac Red Trackball because I just like track balls and this was one of the best reviewed trackballs I could find. Over all I’m happy with my purchase but I have had some issues and I wanted to explain in this article how I solved them. My hope is that others with similar issues can find this article and save themselves some time.
Goland Mq
The challenge with the L-Trac is that it only comes with three buttons (you can buy more though but other than the foot peddles that would take up more room than I want to use and don’t appear terribly easy to use). This left me a bit in the lurch because I really liked being able to navigate back in web browsers when I’m just using the Trackball and for some apps I use (like Balsamiq and Excel) the ability to left/right tilt is a requirement for a good experience.
My online research pointed to X-Mouse Button Control as the solution. This is a free piece of non-open source software that lets you remap mouse buttons in a dizzying variety of ways. The good new is that it solved my missing button problems. The bad news is that it took me a while to figure out how to make it work right. So I thought I would share what I learned to hopefully save others time in the future.
For Web Navigation the easiest solution appeared to be using chording. That is, to combine one button (I choose the left trackball button) to change the trackball scroll wheel into a navigation wheel (e.g. scroll up goes forward, scroll down goes back). This absolutely works but it’s kind of a pain because the super smooth scroll wheel has no clicks or other indications when it has incremented so it’s easy to over or under scroll and end up way more pages away than I intended. A much nicer solution was to chord the left button with the middle button as back and the right button as forward. To do this you have to:
- Go to Left button and set it to 'Button Chording'
- Go to the Right Button in the chording menu and set it to Forward
- Go to the Middle Button in the chording menu and set it to Back
- I unchecked 'Block' in the chording menu because I often hold down the left button and use it with the track ball to do selections so I didn’t want chording to interfere with dragging.
For simulating the tilt wheel left/right the obvious solution would be to use 'Change Movement to Scroll' feature which turns the track ball into a huge mouse up/mouse down, left tilt/right tilt sphere. But in practice I found the feature to be clunky. How far it scrolled depended on how far I moved the cursor and regardless of the sensitivity setting the scrolling always felt jumpy and hard to control. In the end I took a different route. I set up chording, this time with my right button and I programmed wheel up and wheel down to map to tilt left and tilt right. This proved to work really well and gave a really nice scroll experience. Setting this up requires:
- Go to Right Button and set to 'Button Chording'
- Go to Wheel Up and set to Mouse Wheel Tilt Left in the chording menu
- Go to Wheel Down and set to Mouse Wheel Tilt Right in the chording menu
- In this case I did activate 'Block' in the chording because otherwise I accidentally trigger the right click menu which is annoying.
One last problem I ran into is that I use Remote Desktop a lot and I wanted my trackball to work properly there. To get this to work right I had to:
- On the machine I’m Remote Desktoping from go to 'Add' on the Application / Windows Profiles menu
- Select 'mstsc.exe' as the app (this is easiest if you have Remote Desktop running so you can select it from the Process Menu)
- Then set everything to 'No Change' for the remote desktop profile on the machine I’m remote desktoping from The idea is to completely disable X-Mouse Button Control on the machine I’m Remote Desktoping from when I’m using Remote Desktop.
Golandam
Then on the machine I’m Remote Desktoping to:
- Install X-Mouse Button Control
- Configure all the chording on the machine I’m remote desktoping to as given at the start of this post
Now my trackball behaves itself just fine both on my primary box and my remote desktop box and I have a nice forward/back navigation experience as well as a nice left/right tilt experience. It took me quite a bit of experimentation to figure this all out so I’m hoping that this post will help save other folks some time if they if they have similar problems.