in the GLib/GTK based C programs I’m working on the style guides usually demands a space to be inserted between the function and the opening parenthesis, f.e. g_free (some_variable);
Can anyone give me some pointers how to achieve such a thing?
What I’ve found out so far is that I can set company-completion-finish-hook to point to a custom function.
I’ve used a dummy function to play around with, but I’m not quite sure how to continue:
If I complete f.e. g_object_ref(Obj) I can see
args: (g_object_ref(Obj)) being printed to my messages buffer.
My idea was to use this hook (if it is the right one for the job) to do some string manipulation and insert a whitespace before the opening parenthesis, but I’m not sure if this is feasible (and if so, how to go about it).
Without knowing too much about company I would imagine that this could be achieved in two different ways:
Altering the list completion candidates
Manipulating the text after completion finishes
Any advice would be appreciated!
PS: Loving Doom Emacs so far :)
EDIT: Or maybe there’s a different package that can be leveraged for this kind of job?!
Hey @devrtz! The Docstring of company-completion-finish-hook states:
Documentation
Hook run when company successfully completes.
The hook is called with the selected candidate as an argument.
If you intend to use it to post-process candidates from a specific
backend, consider using the post-completion command instead.
Looks to me like you would have to see if the company-backend you are using has a post-completion argument that you can customize. If not, you can always create your own backend copy pasting the code of the backend and adding the post-completion argument to do as you want. Which backend does this use?
This seems like an XY problem. I believe the proper way to solve this is configuring a formatter, which will accomplish this more robustly because it doesn’t depend on you always using company to insert functions (and it’s syntax-aware). Unfortunately, I’m not too familiar with this, but I think you’d want to look into whether the upstream projects publish config files for formatters like clang-format, and then integrate that with Doom via the :editor format module. Maybe someone else has more info there?
I’m using company-capf and indeed it has a company--capf-post-completion function.
In your reply you wrote post-completionargument though which leaves me in a bit of a confused state about what needs changing ;)
(defun company--capf-post-completion (arg)
(let* ((res company-capf--current-completion-data)
(exit-function (plist-get (nthcdr 4 res) :exit-function))
(table (nth 3 res)))
(if exit-function
;; We can more or less know when the user is done with completion,
;; so we do something different than `completion--done'.
(funcall exit-function arg
;; FIXME: Should probably use an additional heuristic:
;; completion-at-point doesn't know when the user picked a
;; particular candidate explicitly (it only checks whether
;; further completions exist). Whereas company user can press
;; RET (or use implicit completion with company-tng).
(if (= (car (completion-boundaries arg table nil ""))
(length arg))
'sole
'finished)))))
Poking the code it seems like arg is only used with the exit-function and company-caps--current-completion-data is a global holding the completion data.
Enabling tracing of the function (thanks to SPChf) shows that it get’s called like so:
1 -> (company--capf-post-completion #("g_object_ref(Obj)" 0 1 (lsp-completion-item #4=#s(hash-table size 12 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("filterText" #("g_object_ref" 0 12 (match-data (0 7 0 1 1 2 2 3 3 4 4 5 5 6 6 7))) "insertText" "g_object_ref(${1:Obj})" "insertTextFormat" 2 "kind" 1 "label" "g_object_ref(Obj)" "score" 0.8436345458030701 "sortText" #1="40a80791g_object_ref" "textEdit" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("newText" "g_object_ref(${1:Obj})" "range" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("end" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("character" 9 "line" 649)) "start" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("character" 2 "line" 649)))))) "_emacsStartPoint" 19531)) lsp-sort-text #1# lsp-completion-start-point 19531 lsp-completion-markers #3=(19531 #<marker (moves after insertion) at 19548 in calls-srtp-utils.c>) lsp-completion-prefix #2="g_objec" face (completions-first-difference)) 1 17 (lsp-completion-item #4# lsp-sort-text #1# lsp-completion-start-point 19531 lsp-completion-markers #3# lsp-completion-prefix #2#)))
1 <- company--capf-post-completion: nil
Wow, quite a lot of information.
I’m (currently) at a bit of a loss at which parts need changing.
I’m not super familiar with how company-backends really works, so I am going of documentation and source. For what I can see, you can’t change the arguments (the args argument) that is feed into the company backend. However, you can change the way it’s processed If it it has a function you can advice, like you pointed out .
In the documentation for company-backends it says:
post-completion: Called after a completion candidate has been inserted
into the buffer. The second argument is the candidate. Can be used to
modify it, e.g. to expand a snippet.
So I am guessing you could add :after advice to company--capf-post-completion function and return the modified candidate. It seems pretty complicated though, you would have to detect the parenthesis and insert the space there, and I’m not sure if it would work.
I would take @liam 's approach, the formatter seems like a simpler approach. Not a C programmer so I don’t know if you could reuse an already existing tool, I’m guessing you could.
I found for clang-formatter you can use SpaceBeforeParens (SpaceBeforeParensStyle) clang-format 3.5 rule! I think it’s what you wnat @devrtz! This is the default formatter for c/c++ in :editor format module. Seems like you would just need to install the dependency and configure the .clang-format file
you might be right about the nature of the problem ;)
I’m pretty novice when it comes to customizing my emacs (apart from changing some variables) and my lisp-fu is certainly lacking aswell (I worked through David S. Touretsky’s book on Common Lisp, but that about covers my lisp experience).
However I’m not afraid to getting my hands dirty and thank you for the pointers toward configuring a formatter :)
As a matter of fact I’ve just come across clang-format configurator which will make this super nice for the projects I’m working on :)
Once I figured out all the necessary steps I will post them and mark as the solution.
EDIT: While drafting a post I realized there wasn’t really much more to it then the advice given already, so instead I’ll just mark an existing post as solution.