{"id":13862785,"url":"https://github.com/abo-abo/lpy","last_synced_at":"2025-04-13T04:13:16.869Z","repository":{"id":63112602,"uuid":"59753842","full_name":"abo-abo/lpy","owner":"abo-abo","description":"Minimal Python IDE for GNU Emacs","archived":false,"fork":false,"pushed_at":"2024-03-03T13:09:39.000Z","size":175,"stargazers_count":190,"open_issues_count":21,"forks_count":16,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-04-13T04:12:58.003Z","etag":null,"topics":["emacs","ide","python"],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abo-abo.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-26T13:47:35.000Z","updated_at":"2025-03-24T13:02:52.000Z","dependencies_parsed_at":"2024-04-08T16:58:54.893Z","dependency_job_id":"f62f424a-10c0-4a42-9c8a-6a2c707f9084","html_url":"https://github.com/abo-abo/lpy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abo-abo%2Flpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abo-abo%2Flpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abo-abo%2Flpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abo-abo%2Flpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abo-abo","download_url":"https://codeload.github.com/abo-abo/lpy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248661721,"owners_count":21141451,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","ide","python"],"created_at":"2024-08-05T06:01:52.513Z","updated_at":"2025-04-13T04:13:16.844Z","avatar_url":"https://github.com/abo-abo.png","language":"Emacs Lisp","readme":"* lpy\n\nDeceptively minimalistic Python IDE for GNU Emacs.\n\n* Setup\nInstall from MELPA and enable =lpy-mode=.\n\n* Introduction\nQ: How many keys does it take to define/redefine a Python function?\nA: One - ~e~.\n\n** Arrow navigation\nQ: Does this also apply to classes, import statements, for loops and\nplain one liners?\nA: Of course.\n\nQ: How many keys does it take to move to the next Python function?\nA: One - ~j~.\n\nQ: Does this also apply to classes, import statements, for loops and\nplain one liners?\nA: Of course.\n\nQ: So, how do I eval a statement, move to the second statement, and\neval the second statement?\nA: ~eje~.\n\nQ: How to move back to the first statement?\nA: ~k~.\n\nQ: How do I descent into a compound statement, like =def=?\nA: ~l~.\n\nQ: How do I ascent back?\nA: ~h~.\n\nQ: Back to eval, how do I eval something that's not a compound\nstatement?\nA: Mark as much legal code as you like with a region and press ~e~.\n\nQ: Any shortcut for marking a symbol in order to eval it?\nA: ~M-m~.\n\n** Semantic navigation\nQ: How can I select a top-level symbol in the current file?\nA: ~g~.\n\nQ: How do I follow to the current symbol's definition?\nA: ~M-.~.\n\nQ: How do I go back from there?\nA: =M-,=.\n\nQ: Does =M-,= also bring me back after ~g~?\nA: Yes.\n\n** Eval in more detail\nQ: Where do I see the result of the eval?\nA: In the minibuffer.\n\nQ: What if the result of the operation is =None=?\nA: Then =(ok)= is printed to confirm that the operation went through.\n\nQ: What if an uncaught exception is thrown?\nA: The exception will be displayed in the minibuffer, highlighted in\nred.\n\nQ: Is it possible to be productive without ever seeing the REPL\nbuffer?\nA: Yes.\n\nQ: How do I see the REPL buffer?\nA: ~C-c C-z~.\n\nQ: Can I have more than one REPL session?\nA: Yes, use ~xp~ to select session or start a new one.\n\nQ: Does pressing ~e~ on a variable assignment output nothing because the\nresult is =None=?\nA: No, magic is used to make it print the new value of the variable.\n\nQ: Where else is ~e~ magical?\nA: ~e~ on  =__file__= will print the actual file name.\n\nQ: Any more?\nA: ~e~ on a single line =return= statement will print the return result.\n\nQ: How do I insert the result of the eval into the buffer?\nA: ~E~.\n\nQ: How do I insert the result of the eval into the buffer as a\ncomment?\nA: ~2e~.\n\nQ: Howto easily select things to eval?\nA: ~M-m~ to get into special. Then ~+~ and ~-~ to expand/shrink selection with =expand-region=.\n\n** Debugging\nQ: How do I step into an expression?\nA: ~xj~.\n\nQ: Where does this work?\nA: Function or method call, possibly with the result being assigned to\na variable.\n\nQ: What does that do exactly?\nA: Evaluate the function arguments, jump to the function definition,\nand store the function arguments into global variable with appropriate\nnames.\n\nQ: So if all I have is =sys.argv= I can use ~xj~ (combined with ~j~, ~l~ and\n~e~) to step into my program as deep as I want?\nA: Yes.\n\nQ: What if I just want to place a breakpoint to speed things up?\nA: To place a breakpoint, throw any exception. Then, enter\n=lp.pm()= into the REPL.\n\nQ: =lp.pm()= sounds weird, how can I see how it works?\nA: Enter into the REPL: =os.path.realpath(42)= which will raise an\nexception a few functions down the line. Then enter =lp.pm()=.\n\nQ: Wait, so this is like =pdb=?\nA: Yes, very similar.\n\nQ: So why go through the trouble?\nA: To get global variable context and proceed with ~e~ and ~j~.\n\nQ: Got it. Anyway, I see =File \"/usr/lib/python2.7/posixpath.py\",\nline 61, Frame [3/3]:=, what does it mean?\nA: =realpath= called =_joinrealpath=, which called =isabs=, which raised an\nException.\n\nQ: Three functions (=realpath=, =_joinrealpath=, and =isabs=), that's what\n3/3 means. And I'm in =isabs= now?\nA: Yes.\n\nQ: How do I open the source code for =isabs=?\nA: It's a link: use the mouse or =ace-link= or =next-error=.\n\nQ: I'm at the definition of =isabs= now, was its argument value stored\nsomewhere?\nA: Yes, if you eval =s=, you get =42= - the value that propagated from\n=os.path.realpath(42)=.\n\nQ: =isabs= is boring. How do I go up the stack?\nA: Enter =up= into the REPL.\n\nQ: I entered up, and now the frame is 2/3 and\nI'm at =def _joinrealpath(path, rest, seen)=. Does this mean I can eval\n=path=, =rest=, and =seen= since they were propagated from the\n=os.path.realpath(42)= call?\nA: Yes.\n\nQ: And entering =up= again will bring me to 1/3 and =realpath=?\nA: Yes.\n\nQ: How do I go back down stack?\nA: Enter =dn=.\n\n** Notebooks\nQ: Is this like IPython?\nA: Yes.\n\nQ: But it's different how?\nA: You use Emacs instead of a browser, and the cells are\nself-contained in comments.\n\nQ: Sounds nice, but I'm not sold yet?\nA: It's like Org-mode embedded in Python code.\n\nQ: So I can fold / unfold each cell?\nA: Yes.\n\nQ: And eval/reeval it with ~e~?\nA: Yes.\n\nQ: How about organizing cells in a hierarchy?\nA: Also possible.\n\nQ: And ~e~ works on the hierarchy as well?\nA: Yes.\n\nQ: Are cells actually called different or something?\nA: Yes, they're outlines.\n\nQ: How do I make an outline named =Includes=?\nA: Enter =#* Includes=.\n\nQ: And like in Org-mode, the amount of stars is that outline's level?\nA: Yes.\n\nQ: Do ~M-left~ and ~M-right~ work like in Org-mode for promotion/demotion?\nA: Yes.\n\nQ: How to fold/unfold an outline?\nA: ~i~.\n\nQ: How do I fold/unfold all outlines?\nA: ~I~.\n\nQ: How do I make a table of contents?\nA: ~2I~.\n\nQ: When I press ~e~ on an outline it evaluates itself and the result is\nechoed; how do I make the result insert itself into the buffer\ninstead?\nA: End the outline name in =:= (semicolon)\n\nQ: How do I clean up all inserted results?\nA: ~M-x~ =lpy-clean=.\n\nQ: Any more neat stuff about outlines?\nA: Yes, outlines are structured statements and parents to the\ntop-level statements.\n\nQ: So ~j~ / ~k~ and ~h~ / ~l~, and even ~e~ treat outlines as statements? Neat.\nA: Yeah.\n\n** Completion\nQ: How do I get completion at point?\nA: Press ~C-M-i~.\n\nQ: Is this static completion or does it depend on the REPL state?\nA: Both. The static one is more convenient and is tried first. But the\ndynamic one is very reliable, since it knows exactly on which type of\nobject you're operating.\n\nQ: But dynamic completion won't work unless my current object has a\nvalue in the REPL?\nA: Correct.\n\nQ: What's used for static completion?\nA: Jedi.\n\n** Inline hints\nQ: How do I look up the function arguments of the current function?\nA: Toggle ~C-2~.\n\nQ: What about the docstring?\nA: Toggle ~C-1~.\n","funding_links":[],"categories":["Emacs Lisp"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabo-abo%2Flpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabo-abo%2Flpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabo-abo%2Flpy/lists"}