unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Indenting with the tab key like everyone else
       [not found] <1019418503.3900238.1559510385829.ref@mail.yahoo.com>
@ 2019-06-02 21:19 ` R. Diez via help-gnu-emacs
  2019-06-04  1:19   ` Emanuel Berg via help-gnu-emacs
  2019-06-04  4:29   ` YUE Daian
  0 siblings, 2 replies; 6+ messages in thread
From: R. Diez via help-gnu-emacs @ 2019-06-02 21:19 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Hi all:

I want to change the indenting behaviour of the tab key when writing source code like C++, Perl or Bash. But I am a little confused, so I need some help.

When in C mode, the Tab key is bound to c-indent-line-or-region . When in Perl mode, it is bound to indent-for-tab-command, which is a rather complicated function.

I want the same behaviour as most other IDEs I know: If I just press tab, it should "intelligently" indent the current line of code as usual. But if I select several lines with the shift key, I want to rigidly indent the selected block of lines. At the moment, Emacs tries to reindent the selected lines, which often does nothing, because it thinks the lines are already properly indented.

If I want to intelligently reindent a block of lines, I would rather manually call the right function, something like "reindent-code". I could create an alias or a new function just for that purpose.

I never got used to Emacs "prefix" mechanism, so I do not want to use it. And I do not want to retrain my "muscle memory". I want the same behaviour as everywhere else.

What would be the best way to achieve this? I know a little Lisp, but not enough for complex things.

Many thanks in advance,
  rdiez



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Indenting with the tab key like everyone else
  2019-06-02 21:19 ` Indenting with the tab key like everyone else R. Diez via help-gnu-emacs
@ 2019-06-04  1:19   ` Emanuel Berg via help-gnu-emacs
  2019-06-04  4:29   ` YUE Daian
  1 sibling, 0 replies; 6+ messages in thread
From: Emanuel Berg via help-gnu-emacs @ 2019-06-04  1:19 UTC (permalink / raw)
  To: help-gnu-emacs

R. Diez via help-gnu-emacs wrote:

> I want the same behaviour as most other IDEs
> I know: If I just press tab, it should
> "intelligently" indent the current line of
> code as usual. But if I select several lines
> with the shift key, I want to rigidly indent
> the selected block of lines. At the moment,
> Emacs tries to reindent the selected lines,
> which often does nothing, because it thinks
> the lines are already properly indented.

TAB is the "intelligent" way and that works for
regions as well. This makes sense IMO.

If you want to just mechanically move a region
forward or backward, first set the region, then
do

`C-u C-x TAB' for 4 steps

`C-u C-u C-x TAB' for 4**2=16 steps (and so on),

and for arbitrary values, do, e.g.,

`C-u 3 C-x TAB' for 3 steps (and so on).

You can also do `C-u -2 C-x TAB' to move back
two steps, for example.

-- 
underground experts united
http://user.it.uu.se/~embe8573
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Indenting with the tab key like everyone else
  2019-06-02 21:19 ` Indenting with the tab key like everyone else R. Diez via help-gnu-emacs
  2019-06-04  1:19   ` Emanuel Berg via help-gnu-emacs
@ 2019-06-04  4:29   ` YUE Daian
  2019-06-25  8:09     ` R. Diez via help-gnu-emacs
  1 sibling, 1 reply; 6+ messages in thread
From: YUE Daian @ 2019-06-04  4:29 UTC (permalink / raw)
  To: R. Diez, help-gnu-emacs@gnu.org

On 2019-06-02 21:19, "R. Diez via help-gnu-emacs" <help-gnu-emacs@gnu.org> wrote:
> Hi all:
>
> I want to change the indenting behaviour of the tab key when writing source code like C++, Perl or Bash. But I am a little confused, so I need some help.
>
> When in C mode, the Tab key is bound to c-indent-line-or-region . When in Perl mode, it is bound to indent-for-tab-command, which is a rather complicated function.
>
> I want the same behaviour as most other IDEs I know: If I just press tab, it should "intelligently" indent the current line of code as usual. But if I select several lines with the shift key, I want to rigidly indent the selected block of lines. At the moment, Emacs tries to reindent the selected lines, which often does nothing, because it thinks the lines are already properly indented.
>
> If I want to intelligently reindent a block of lines, I would rather manually call the right function, something like "reindent-code". I could create an alias or a new function just for that purpose.
>
> I never got used to Emacs "prefix" mechanism, so I do not want to use it. And I do not want to retrain my "muscle memory". I want the same behaviour as everywhere else.
>
> What would be the best way to achieve this? I know a little Lisp, but not enough for complex things.
>
> Many thanks in advance,
>   rdiez

Well, Emacs TAB key facility is a little bit complicated.

I had similar requirement to yours when I was using Emacs 23.
I wrote a function exactly for this.

It triggers company-mode completion when the "current" character
satisfies the regex.
Otherwise, it just indent the line.
Or when yasnippet is active, it moves to the next field.
AFAIK `company-indent-or-complete-common` does not support it.

--- BEGIN ---
(defcustom company-begin-regex "[0-9a-zA-Z_.>:-]"
	"Used by function `complete-or-indent' to decide whether or not to start
completion."
	:type 'string
	:group 'none
	:safe t)

  ;; Bind company complete to <TAB> in a smart way.
  ;; TODO Remove this snippet later...
  (defun complete-or-indent ()
	"Complete using company-mode or indent current line by checking "
	(interactive)
	(cond
	 ;; When in region, indent the region.
	 ((use-region-p)
	  (indent-region (region-beginning) (region-end)))
	 ;; When yasnippet is active, move to next field.
	 ((yas-active-snippets)
	  (yas-next-field))
	 ;; When it is possible to complete, do it.
	 ((and (string-match-p company-begin-regex (char-to-string (char-before)))
           (call-when-defined 'company-manual-begin))
	  (call-when-defined 'company-complete-common))
	 (t (indent-for-tab-command))))
--- END ---

Hope that helps.

Danny



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Indenting with the tab key like everyone else
  2019-06-04  4:29   ` YUE Daian
@ 2019-06-25  8:09     ` R. Diez via help-gnu-emacs
  2019-07-01  4:29       ` YUE Daian
  0 siblings, 1 reply; 6+ messages in thread
From: R. Diez via help-gnu-emacs @ 2019-06-25  8:09 UTC (permalink / raw)
  To: YUE Daian; +Cc: help-gnu-emacs@gnu.org

Hallo Danny:

Thanks for your help. I got a little further, see the code I came up with below (I used some code I found on the Internet too).

There is a little issue I have not been able to fix yet. Say I place the cursor at the beginning of a line, and select a few lines by 
keeping the "shift" key pressed and hitting the down arrow key a few times. I call this selecting lines "downwards". Then indenting by 
hitting the tab key multiple times works fine.

However, if I select/mark the lines "upwards" (by using the up arrow key), then 'my-indent-rigidly' loses the selection after indenting the 
first time.

I am confused with the terms 'region', 'mark' and 'transient mark', and my Lisp skills are not very good either. Have you got any ideas on 
how to fix that?


The Lisp code is here:

; This routine keeps the region/mark/transient mark (?) when doing an indent-rigidly.
(defun my-indent-rigidly (amount) ""
   (save-excursion
     (let ((deactivate-mark nil)
           (beg (region-beginning)))
       (move-beginning-of-line nil)
       (indent-rigidly beg (region-end) amount)
       (push-mark beg t t))))


; Shift-Tab to decrease the indentation.
; As an alternative, block-select the columns of spaces you want to delete, and press the Del key.
(defun unindent-rigidly nil ""
   (interactive)
   (my-indent-rigidly -1)
)

(global-set-key [S-tab] 'unindent-rigidly)
; Sometimes "S-tab" does not work, use [backtab] instead:
(global-set-key [backtab] 'unindent-rigidly)


; The Tab key has 2 functions:
; - If some text is selected, ridigly increases indentation.
; - Otherwise, intelligently indent the current line.
(defun my-tab-indent nil ""
   (interactive)
   (if (use-region-p)
     (my-indent-rigidly 1)
     (indent-for-tab-command)))

(global-set-key (kbd "TAB") 'my-tab-indent)


Best regards,
   rdiez



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Indenting with the tab key like everyone else
  2019-06-25  8:09     ` R. Diez via help-gnu-emacs
@ 2019-07-01  4:29       ` YUE Daian
  2019-07-16  7:23         ` R. Diez
  0 siblings, 1 reply; 6+ messages in thread
From: YUE Daian @ 2019-07-01  4:29 UTC (permalink / raw)
  To: R. Diez; +Cc: help-gnu-emacs@gnu.org

On 2019-06-25 10:09, "R. Diez" <rdiezmail-emacs@yahoo.de> wrote:
> Hallo Danny:
>
> Thanks for your help. I got a little further, see the code I came up with below (I used some code I found on the Internet too).
>
> There is a little issue I have not been able to fix yet. Say I place the cursor at the beginning of a line, and select a few lines by 
> keeping the "shift" key pressed and hitting the down arrow key a few times. I call this selecting lines "downwards". Then indenting by 
> hitting the tab key multiple times works fine.
>
> However, if I select/mark the lines "upwards" (by using the up arrow key), then 'my-indent-rigidly' loses the selection after indenting the 
> first time.
>
> I am confused with the terms 'region', 'mark' and 'transient mark', and my Lisp skills are not very good either. Have you got any ideas on 
> how to fix that?
>
>
> The Lisp code is here:
>
> ; This routine keeps the region/mark/transient mark (?) when doing an indent-rigidly.
> (defun my-indent-rigidly (amount) ""
>    (save-excursion
>      (let ((deactivate-mark nil)
>            (beg (region-beginning)))
>        (move-beginning-of-line nil)
>        (indent-rigidly beg (region-end) amount)
>        (push-mark beg t t))))
>
>
> ; Shift-Tab to decrease the indentation.
> ; As an alternative, block-select the columns of spaces you want to delete, and press the Del key.
> (defun unindent-rigidly nil ""
>    (interactive)
>    (my-indent-rigidly -1)
> )
>
> (global-set-key [S-tab] 'unindent-rigidly)
> ; Sometimes "S-tab" does not work, use [backtab] instead:
> (global-set-key [backtab] 'unindent-rigidly)
>
>
> ; The Tab key has 2 functions:
> ; - If some text is selected, ridigly increases indentation.
> ; - Otherwise, intelligently indent the current line.
> (defun my-tab-indent nil ""
>    (interactive)
>    (if (use-region-p)
>      (my-indent-rigidly 1)
>      (indent-for-tab-command)))
>
> (global-set-key (kbd "TAB") 'my-tab-indent)
>
>
> Best regards,
>    rdiez

Sorry for the late reply.

I am not sure what you really want to do exactly. There are some tips I
thought of based on the code:

- If you look at the document of the function `push-mark`, you may
  notice that "Novice Emacs Lisp programmers often try to use the mark
  for the wrong purposes". I am not sure if this is the case but I
  presume that the weird behavior relates to it.

- Key binding Tab can be obtained by calling `(kbd "<tab>")` and
  back-tab using `(kbd "S-<tab>")`. I tried your function and both
  selecting downwards and upwards work. Please check the real key
  binding by typing `C-h k <tab>` and see if your function got
  called. The global key binding can be overrode by mode-map.

- If you want to edit multiple lines, you may consider using the
  multi-cursors package.

- It is very unusual to use `nil` instead of `()` for argument
  list. Also document string usually remains below the header line of a
  function.

Please describe what you want to achieve exactly so that more specific
help could be given.

Cheers.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Indenting with the tab key like everyone else
  2019-07-01  4:29       ` YUE Daian
@ 2019-07-16  7:23         ` R. Diez
  0 siblings, 0 replies; 6+ messages in thread
From: R. Diez @ 2019-07-16  7:23 UTC (permalink / raw)
  To: YUE Daian; +Cc: help-gnu-emacs@gnu.org


> I am not sure what you really want to do exactly. There are some tips I
> thought of based on the code:
 > [...]

After much fighting with Emacs, I think I narrowed the problem down to a weird side-effect of calling (use-region-p). I have written this 
routine for test purposes. I would be interested to know if you can reproduce it on your Emacs.

   ; This routine lets you test the surprising side-effect of calling (use-region-p).
   ;
   ; Before calling this routine, select a few text lines by going to the beginning of a line
   ; (column 0) and pressing Shift + <cursor down> a few times. The lines will be highlighted.
   ;
   ; Then call this routine interactively a few times in a row. The lines will indent one character at a time.
   ; The first time, the highlighting will disappear, but the selection will somehow stay, so that
   ; further calls will still indent the same lines.
   ;
   ; After the test above, change "(if t" below to "(if (use-region-p)", and repeat the test.
   ; The first time, the text will indent one character, but the second call will not indent anymore,
   ; because the selection is completely lost.


   (defun indentation-test nil ""
     (interactive)

     (if t
     ; (if (use-region-p)
       (indent-rigidly (region-beginning) (region-end) 1)
       (message "Skipping because there is no selection.")
     )
   )

Best regards,
   rdiez



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-07-16  7:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1019418503.3900238.1559510385829.ref@mail.yahoo.com>
2019-06-02 21:19 ` Indenting with the tab key like everyone else R. Diez via help-gnu-emacs
2019-06-04  1:19   ` Emanuel Berg via help-gnu-emacs
2019-06-04  4:29   ` YUE Daian
2019-06-25  8:09     ` R. Diez via help-gnu-emacs
2019-07-01  4:29       ` YUE Daian
2019-07-16  7:23         ` R. Diez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).