Loading ...
Sorry, an error occurred while loading the content.

Auto-indentation for Python

Expand Messages
  • Sakari Tanhua
    Hi, I ve been using GNU Emacs for many years, but due to various reasons I got frustrated in it and started looking for alternatives. Jasspa s MicroEmacs seems
    Message 1 of 6 , May 19 6:47 AM
    • 0 Attachment
      Hi,

      I've been using GNU Emacs for many years, but due to various reasons I got
      frustrated in it and started looking for alternatives. Jasspa's MicroEmacs
      seems like a very nice editor, and I was a bit surprised a _micro_ emacs has
      way more advanced built-in features than its bloatware cousins. Nice.

      But alas, after trying to edit some Python code I realized there's no auto
      indent for Python. Big deal, I'll implement it myself---or so I thought. You
      know, Python has this peculiar indentation which has no end tag at the end
      of a block:

      if foo == bar:
      yay()
      foo()

      if bar == foo:
      blah()

      Actually it'd be dead easy to write an auto indent logic for Python code,
      and I almost made it with this one:

      indent .hilight.python n ":$" 4

      Works just like a charm: every line ending with a colon starts a new block
      and the next lines should be indented. Now when I want to end a block, I hit
      backspace on the next "empty" line (i.e. containing only whitespaces) and
      what I'd like it to do is to eat one indentation level, 4 spaces that is.
      Well, it doesn't do that by default, but I already found the
      backward-delete-tab function, so it's obviously trivial to write a function
      which combines it with the backward-delete-char (with some simple logic) and
      bind it to backspace. So that's not really a problem.

      The problem is what happens next. Because the indentation system has no idea
      that the block ended, it naturally reindents the new line as soon as I press
      enter. I read the manual of indent(2) but couldn't figure out how to write a
      rule for this. So, you ME gurus, is it possible to do this by using the
      indentation system of ME? If not, any ideas what'd be the best approach in
      improving it so that it could handle cases like this? Of course I could
      write some custom macros to handle this, but I'd rather use/improve indent
      because otherwise I'd have to reinvent also the "b" and "c" indent types.

      Any ideas?

      --
      Sakari Tanhua
    • Steven Phillips
      Sakari, Welcome to ME, I hope that we can sort out the indentation to support python. It s my first look at python and its syntax, from first impressions
      Message 2 of 6 , May 19 8:03 AM
      • 0 Attachment
        Sakari,

        Welcome to ME, I hope that we can sort out the indentation to support python.
        It's my first look at python and its syntax, from first impressions rather you
        than me!

        I would have expected the following to help/work

        indent .hilight.python o "^$" -4

        Which in theory should make a blank line reduce the indentation by 4. But this
        does not work and I suspect this is a 'feature' of the indentation code, I
        will investigate this. However, while I was playing around I found this chunk
        of python code:

        def checkop(expr, a, b, value, fuzz = 1e-6):
        import sys
        print ' ', a, 'and', b,
        try:
        result = eval(expr)
        except:
        result = sys.exc_type
        print '->', result
        if (type(result) == type('') or type(value) == type('')):
        ok = result == value
        else:
        ok = abs(result - value) <= fuzz
        if not ok:
        print '!!\t!!\t!! should be', value, 'diff', abs(result - value)

        Is this indented correctly? If so why is the second 'if' not part of the
        'else:'? Does another ':' line also end the block? If so I assume nested if's
        are not possible? What about if's in for loops?

        Seems a pretty restrictive language...

        Steve


        > Subject: [jasspa] Auto-indentation for Python
        > From: Sakari Tanhua <stanhua@...>
        > Date: Wednesday, May 19, 2004, 2:47:00 PM
        > To: jasspa@yahoogroups.com
        > Hi,

        > I've been using GNU Emacs for many years, but due to various reasons I got
        > frustrated in it and started looking for alternatives. Jasspa's MicroEmacs
        > seems like a very nice editor, and I was a bit surprised a _micro_ emacs has
        > way more advanced built-in features than its bloatware cousins. Nice.

        > But alas, after trying to edit some Python code I realized there's no auto
        > indent for Python. Big deal, I'll implement it myself---or so I thought. You
        > know, Python has this peculiar indentation which has no end tag at the end
        > of a block:

        > if foo == bar:
        > yay()
        > foo()

        > if bar == foo:
        > blah()

        > Actually it'd be dead easy to write an auto indent logic for Python code,
        > and I almost made it with this one:

        > indent .hilight.python n ":$" 4

        > Works just like a charm: every line ending with a colon starts a new block
        > and the next lines should be indented. Now when I want to end a block, I hit
        > backspace on the next "empty" line (i.e. containing only whitespaces) and
        > what I'd like it to do is to eat one indentation level, 4 spaces that is.
        > Well, it doesn't do that by default, but I already found the
        > backward-delete-tab function, so it's obviously trivial to write a function
        > which combines it with the backward-delete-char (with some simple logic) and
        > bind it to backspace. So that's not really a problem.

        > The problem is what happens next. Because the indentation system has no idea
        > that the block ended, it naturally reindents the new line as soon as I press
        > enter. I read the manual of indent(2) but couldn't figure out how to write a
        > rule for this. So, you ME gurus, is it possible to do this by using the
        > indentation system of ME? If not, any ideas what'd be the best approach in
        > improving it so that it could handle cases like this? Of course I could
        > write some custom macros to handle this, but I'd rather use/improve indent
        > because otherwise I'd have to reinvent also the "b" and "c" indent types.

        > Any ideas?
      • Sakari Tanhua
        Hi Steven, ... I first thought of something like that, too, but the problem is (in addition to the fact that it doesn t work :) ) that it wouldn t allow empty
        Message 3 of 6 , May 19 9:11 AM
        • 0 Attachment
          Hi Steven,

          > I would have expected the following to help/work
          >
          > indent .hilight.python o "^$" -4
          >
          > Which in theory should make a blank line reduce the indentation by 4.

          I first thought of something like that, too, but the problem is (in addition
          to the fact that it doesn't work :) ) that it wouldn't allow empty lines in
          the code between other statements belonging to the same block.

          > if (type(result) == type('') or type(value) == type('')):
          > ok = result == value
          > else:
          > ok = abs(result - value) <= fuzz
          > if not ok:
          > print '!!\t!!\t!! should be', value, 'diff', abs(result - value)
          >
          > Is this indented correctly?

          Yes

          > If so why is the second 'if' not part of the 'else:'?

          Python seems a bit weird language at first because the indentation is a
          critical part of the code. So the second 'if' is not part of the 'else'
          simply because it's not indented at the 'else' block level!

          if (type(result) == type('') or type(value) == type('')):
          ok = result == value
          else:
          ok = abs(result - value) <= fuzz

          if not ok:
          print '!!\t!!\t!! should be', value, 'diff', abs(result - value)

          Now it would belong to the else block, so it's now a totally different
          program, and I only added some whitespace to it. This is Python. :)

          This is also the root of all evil (well, at least from indent's point of
          view), as it's impossible for a program to predict how a given line should
          be indented. But the good thing is that auto indentation for Python is
          really simple to implement:

          1. If the previous line ends with a colon, the second line should be
          indented one level more.

          2. Otherwise, always maintain the previous indentation level, regardless
          whether or not the previous line contains anything else than
          whitespaces.

          3. The "b" and "c" type indentations (indent(2) terminology) should behave
          like in C.

          I guess that'd pretty much do the trick. It should also be noted that the
          indentation level in Python doesn't necessarily have to be exactly 4 spaces.
          It can be anything, even \t's, but it must be uniform in one block. The
          style guide favors 4 spaces.

          After all, maybe it's not wise to try to modify ME's indentation code to
          support this, but write some macros to change the behavior of backspace and
          enter?

          Sakari
        • first last
          From what you are saying (and for what I know of Python, I haven t used it for a long, long time) the probable best way to do what you want is to map a key to
          Message 4 of 6 , May 20 1:33 AM
          • 0 Attachment
            From what you are saying (and for what I know of Python, I haven't used
            it for a long, long time) the probable best way to do what you want is
            to map a key to decrease the indent index (or whatever you call the
            variable indent uses to keep track of how many levels of indentation
            has to use for a line).

            In C-like languages you can have automatic indentation because {} take
            care of telling ME where to start/end the block, in Python you have to
            tell the program where you want the indentation, as it is meaningful to
            the language and it cannot second guess (apart from : starting a
            block).

            Correct me if I am wrong but ME just goes to the current indent level
            when you press enter, so if we have a key (shift + backspace?) that
            changes the indentation level it should work exactly as expected.

            Hope this message is helpful...

            Gabriel

            --- Sakari Tanhua <stanhua@...> wrote:
            ---------------------------------
            Hi Steven,

            > I would have expected the following to help/work
            >
            > indent .hilight.python o "^$" -4
            >
            > Which in theory should make a blank line reduce the indentation by 4.

            I first thought of something like that, too, but the problem is (in
            addition
            to the fact that it doesn't work :) ) that it wouldn't allow empty
            lines in
            the code between other statements belonging to the same block.

            > if (type(result) == type('') or type(value) == type('')):
            > ok = result == value
            > else:
            > ok = abs(result - value) <= fuzz
            > if not ok:
            > print '!!\t!!\t!! should be', value, 'diff', abs(result -
            value)
            >
            > Is this indented correctly?

            Yes

            > If so why is the second 'if' not part of the 'else:'?

            Python seems a bit weird language at first because the indentation is a
            critical part of the code. So the second 'if' is not part of the 'else'
            simply because it's not indented at the 'else' block level!

            if (type(result) == type('') or type(value) == type('')):
            ok = result == value
            else:
            ok = abs(result - value) <= fuzz

            if not ok:
            print '!!\t!!\t!! should be', value, 'diff', abs(result -
            value)

            Now it would belong to the else block, so it's now a totally different
            program, and I only added some whitespace to it. This is Python. :)

            This is also the root of all evil (well, at least from indent's point
            of
            view), as it's impossible for a program to predict how a given line
            should
            be indented. But the good thing is that auto indentation for Python is
            really simple to implement:

            1. If the previous line ends with a colon, the second line should be
            indented one level more.

            2. Otherwise, always maintain the previous indentation level,
            regardless
            whether or not the previous line contains anything else than
            whitespaces.

            3. The "b" and "c" type indentations (indent(2) terminology) should
            behave
            like in C.

            I guess that'd pretty much do the trick. It should also be noted that
            the
            indentation level in Python doesn't necessarily have to be exactly 4
            spaces.
            It can be anything, even \t's, but it must be uniform in one block. The
            style guide favors 4 spaces.

            After all, maybe it's not wise to try to modify ME's indentation code
            to
            support this, but write some macros to change the behavior of backspace
            and
            enter?

            Sakari


            __________________________________________________________________________

            This is an unmoderated list. JASSPA is not responsible for the content
            of
            any material posted to this list.

            To unsubscribe, send a mail message to

            mailto:jasspa-unsubscribe@yahoogroups.com

            or visit http://groups.yahoo.com/group/jasspa and
            modify your account settings manually.





            Yahoo! Groups Sponsor ADVERTISEMENT


            ---------------------------------
            Yahoo! Groups Links

            To visit your group on the web, go to:
            http://groups.yahoo.com/group/jasspa/

            To unsubscribe from this group, send an email to:
            jasspa-unsubscribe@yahoogroups.com

            Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.






            ____________________________________________________________
            Yahoo! Messenger - Communicate instantly..."Ping"
            your friends today! Download Messenger Now
            http://uk.messenger.yahoo.com/download/index.html
          • Phillips, Steven
            I m kind of in agreement here, by using the indent mode pressing enter will start a new line with the same indent as the previous line then you can either
            Message 5 of 6 , May 20 5:31 AM
            • 0 Attachment
              I'm kind of in agreement here, by using the 'indent' mode pressing enter will start a new line with the same indent as the previous line then you can either press 'tab' to indent more or 'S-tab' (shift-tab) to reduce the indent. Creating an indent rule would suggest that a 'restyle-buffer' should work but this clearly cannot work as the meaning of the program is determined by the indentation and therefore cannot be automatically worked out (otherwise we'd have monkeys writing programs :)

              The one thing that I think could be useful is doing a semi-automatic indentation when the enter key is pressed. In this situation it could do some vaguely useful things, i.e. if the current line ends in a ':' then create a new line with an extra indent, if the current line is blank (just has white spaces) then remove all white spaces on the current line and create a new empty line with no indentation - and I think that is as much as I would dare do considering how important the indentation is. This would best be implemented as a simple macro bound to the return key in python buffers.

              Sakari - How does this sound? If this is okay I will create said macro.

              Steve

              > -----Original Message-----
              > From: first last [mailto:prelude_2_murder@...]
              > Sent: 20 May 2004 09:34
              > To: jasspa@yahoogroups.com
              > Subject: Re: [jasspa] Auto-indentation for Python
              >
              >
              > From what you are saying (and for what I know of Python, I
              > haven't used
              > it for a long, long time) the probable best way to do what you want is
              > to map a key to decrease the indent index (or whatever you call the
              > variable indent uses to keep track of how many levels of indentation
              > has to use for a line).
              >
              > In C-like languages you can have automatic indentation because {} take
              > care of telling ME where to start/end the block, in Python you have to
              > tell the program where you want the indentation, as it is
              > meaningful to
              > the language and it cannot second guess (apart from : starting a
              > block).
              >
              > Correct me if I am wrong but ME just goes to the current indent level
              > when you press enter, so if we have a key (shift + backspace?) that
              > changes the indentation level it should work exactly as expected.
              >
              > Hope this message is helpful...
              >
              > Gabriel
              >
              > --- Sakari Tanhua <stanhua@...> wrote:
              > ---------------------------------
              > Hi Steven,
              >
              > > I would have expected the following to help/work
              > >
              > > indent .hilight.python o "^$" -4
              > >
              > > Which in theory should make a blank line reduce the
              > indentation by 4.
              >
              > I first thought of something like that, too, but the problem is (in
              > addition
              > to the fact that it doesn't work :) ) that it wouldn't allow empty
              > lines in
              > the code between other statements belonging to the same block.
              >
              > > if (type(result) == type('') or type(value) == type('')):
              > > ok = result == value
              > > else:
              > > ok = abs(result - value) <= fuzz
              > > if not ok:
              > > print '!!\t!!\t!! should be', value, 'diff', abs(result -
              > value)
              > >
              > > Is this indented correctly?
              >
              > Yes
              >
              > > If so why is the second 'if' not part of the 'else:'?
              >
              > Python seems a bit weird language at first because the
              > indentation is a
              > critical part of the code. So the second 'if' is not part of
              > the 'else'
              > simply because it's not indented at the 'else' block level!
              >
              > if (type(result) == type('') or type(value) == type('')):
              > ok = result == value
              > else:
              > ok = abs(result - value) <= fuzz
              >
              > if not ok:
              > print '!!\t!!\t!! should be', value, 'diff', abs(result -
              > value)
              >
              > Now it would belong to the else block, so it's now a totally different
              > program, and I only added some whitespace to it. This is Python. :)
              >
              > This is also the root of all evil (well, at least from indent's point
              > of
              > view), as it's impossible for a program to predict how a given line
              > should
              > be indented. But the good thing is that auto indentation for Python is
              > really simple to implement:
              >
              > 1. If the previous line ends with a colon, the second line should be
              > indented one level more.
              >
              > 2. Otherwise, always maintain the previous indentation level,
              > regardless
              > whether or not the previous line contains anything else than
              > whitespaces.
              >
              > 3. The "b" and "c" type indentations (indent(2) terminology) should
              > behave
              > like in C.
              >
              > I guess that'd pretty much do the trick. It should also be noted that
              > the
              > indentation level in Python doesn't necessarily have to be exactly 4
              > spaces.
              > It can be anything, even \t's, but it must be uniform in one
              > block. The
              > style guide favors 4 spaces.
              >
              > After all, maybe it's not wise to try to modify ME's indentation code
              > to
              > support this, but write some macros to change the behavior of
              > backspace
              > and
              > enter?
              >
              > Sakari
              >
              >
              > ______________________________________________________________
              > ____________
              >
              > This is an unmoderated list. JASSPA is not responsible for the content
              > of
              > any material posted to this list.
              >
              > To unsubscribe, send a mail message to
              >
              > mailto:jasspa-unsubscribe@yahoogroups.com
              >
              > or visit http://groups.yahoo.com/group/jasspa and
              > modify your account settings manually.
              >
              >
              >
              >
              >
              > Yahoo! Groups Sponsor ADVERTISEMENT
              >
              >
              > ---------------------------------
              > Yahoo! Groups Links
              >
              > To visit your group on the web, go to:
              > http://groups.yahoo.com/group/jasspa/
              >
              > To unsubscribe from this group, send an email to:
              > jasspa-unsubscribe@yahoogroups.com
              >
              > Your use of Yahoo! Groups is subject to the Yahoo! Terms
              > of Service.
              >
              >
              >
              >
              >
              >
              > ____________________________________________________________
              > Yahoo! Messenger - Communicate instantly..."Ping"
              > your friends today! Download Messenger Now
              > http://uk.messenger.yahoo.com/download/index.html
              >
              >
              > ------------------------ Yahoo! Groups Sponsor
              > ---------------------~-->
              > Make a clean sweep of pop-up ads. Yahoo! Companion Toolbar.
              > Now with Pop-Up Blocker. Get it for free!
              > http://us.click.yahoo.com/L5YrjA/eSIIAA/yQLSAA/89EolB/TM
              > --------------------------------------------------------------
              > -------~->
              >
              > ______________________________________________________________
              > ____________
              >
              > This is an unmoderated list. JASSPA is not responsible for
              > the content of
              > any material posted to this list.
              >
              > To unsubscribe, send a mail message to
              >
              > mailto:jasspa-unsubscribe@yahoogroups.com
              >
              > or visit http://groups.yahoo.com/group/jasspa and
              > modify your account settings manually.
              >
              >
              >
              > Yahoo! Groups Links
              >
              >
              >
              >
              >
              >
            • Sakari Tanhua
              Steven and Gabriel, ... But why does it lose the indentation level if the previous line contains only whitespaces? I often want to leave empty lines between
              Message 6 of 6 , May 21 8:36 AM
              • 0 Attachment
                Steven and Gabriel,

                > I'm kind of in agreement here, by using the 'indent' mode pressing enter
                > will start a new line with the same indent as the previous line then you
                > can either press 'tab' to indent more or 'S-tab' (shift-tab) to reduce the
                > indent.

                But why does it lose the indentation level if the previous line contains
                only whitespaces? I often want to leave empty lines between statements which
                are at the same indentation level, and after the empty line I certainly
                don't want to hit tab several times to get back to the same indentation
                level.

                I tried to find the code which implements the 'indent' mode but couldn't
                find it. I guess it's written in C but emode.def's MDINDEN was about the
                only thing I could find. Sure I grepped for MDINDEN but didn't find anything
                interesting. Is there already a way to pass parameters to modes to finetune
                their behavior? It'd be nice if the 'indent' mode could be configured to
                maintain the indentation even when the previous line contains only
                whitespaces.

                > Creating an indent rule would suggest that a 'restyle-buffer' should work

                Indeed, so no indent mode for Python then.

                > The one thing that I think could be useful is doing a semi-automatic
                > indentation when the enter key is pressed. In this situation it could do
                > some vaguely useful things, i.e. if the current line ends in a ':' then
                > create a new line with an extra indent,

                Yes, that's good.

                > if the current line is blank (just has white spaces) then remove all white
                > spaces on the current line and create a new empty line with no indentation

                But I don't like this. IMHO it shouldn't remove whitespaces from the current
                line, and it definitely shouldn't lose the indentation on the next line.
                Assuming that's what you meant by "no indentation", i.e. that the next line
                wouldn't contain any whitespaces and the cursor would be at column 0.

                It'd be much better if it would simply retain the indentation level even
                when the previous line contains only whitespaces. That's exactly what GNU
                Emacs does and I never need to hit tab when coding with it, which is nice.
                Furthermore, to reduce the indentation by one level, there's no separate key
                combination for it (like S-tab) but instead I simply hit backspace and it
                eats one indentation level. (Assuming the cursor is right after the
                indentation, of course.)

                I actually wrote a quite primitive auto indentation because I wanted to
                learn the macro language. It's long enough that I don't want to include it
                in this mail, but it can be found here:

                http://www.hut.fi/~stanhua/mypython.emf

                It's probably a bit amateurishly coded because I don't know all the tricks
                of the language. For example, is there a better way to return values from a
                macro than to set #p? variables? If I understood correctly, !return can
                return only boolean values.

                Anyway, it seems to work pretty much the way I like, and though it still
                needs lots of improvements, it's already usable.

                Sakari
              Your message has been successfully submitted and would be delivered to recipients shortly.