4

In some projects I'm working with, there are coding rules that don't allow C++ operators such as == (for fear of being confused with = I suppose, but oh well...). Instead, special macros such as _EQ_ have to be inserted, which #define to ==. There are other #defines as well, such as _SH_LEFT_, _BITAND_ and so on.

Needless to say, this is all quite tedious to write and I would love to have a meachanism that makes me type == as I'm used to and have it automatically replaced by _EQ_.

I tried abbrev-mode, but as this answer explains, abbrevs can only be defined for words, and I don't really want to change the definition all the required syntax entries. Also, it would be nice if I don't have to type a space after the keyword, but have the macro appear as soon as I hit the last char of the "forbidden" sequence.

Is there any way to achieve this, maybe a "more aggressive" abbrev-mode or some package?

EDIT: Here are some replacements that need to be performed:

I type:            I want:        
=                  =              (works with key-combo)
==                 _EQ_           (works with key-combo)
&                  _BITAND_       (works with key-combo)
&&                 _AND_          (works with key-combo)
|                  _BITOR_        (works with key-combo)
||                 _OR_           (works with key-combo)
!                  _NOT_          (works with key-combo)
!=                 _NOT_EQ_       (doesn't work with key-combo)
  • 1
    I think _BITAND_ is rather problematic since & is also the reference operator. – Tobias May 11 '15 at 10:55
  • @Tobias: You're right. Because BITAND is rather rare, I'd exclude it. – Geier May 11 '15 at 11:55
7

You could define a dedicated input-method, unless you're already using one.

(quail-define-package "C++-operator" "C" "Cop")

(quail-define-rules
 ("==" ["_EQ_"])
 ("&" ["_BITAND_"])
 ("&&" ["_AND_"])
 ("|" ["_BITOR_"])
 ("||" ["_OR_"])
 ("!" ["_NOT_"])
 ("!=" ["_NOT_EQ_"]))

Activating it with C-u C-\ C++-operator RET. Note that you can still insert the original characters by using C-q as a prefix. (Just an idea I had and posted it, beeing suprised that it seems to work so easily.)

You can activate this automatically for c++-mode in the following way:

(defun my-activate-C++-operator ()
  (interactive)
  (quail-activate "C++-operator"))
(add-hook 'c++-mode-hook  'my-activate-C++-operator)
  • That works nicely! How can I activate this mode automatically when I enter C++-mode? – Geier May 8 '15 at 13:53
3

There is key-combo which allows for the desired behavior

(key-combo-define c++-mode-map  "="  '("= " "_EQ_ " "=="))

As I understand it, this is not straightforward with key-combo. What I would do is just:

(key-combo-define c++-mode-map "!"  '("! " "_NOT_EQ_ "=! "))

After all, it's easier to press "!!" than "!=" and shouldn't conflict with C++ syntax as far as I know. You can also put a function in the list supplied as third arg to key-combo-define.

So you could do:

(defun insert-noteq-or-eq ()
  (if (eq (preceding-char) ?\!)
      (progn 
        (backward-delete-char 1)
        (insert "_NOT_EQ_ "))
    (insert "=")))

(key-combo-define c++-mode-map "="  '(insert-noteq-or-eq "_EQ_ "))

This leads to the undesired behavior of the "!" reappearing when pressing "=" after "_NOT_EQ_ " has been inserted, but you get the idea.

  • Thanks, that works nicely for ==, but what about other macros? Can I also have != replaced by _NOT_EQ_ etc.? I edited the original question to clarify that those are also needed. – Geier May 7 '15 at 17:57
  • You can automatically activate the method proposed by politza in the following way: – cogsci May 8 '15 at 14:31
  • which way...? :P – Geier May 8 '15 at 19:39
  • 1
    Sorry, my bad. I added it to the answer. – cogsci May 10 '15 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.