-
-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support editing #6
Comments
I'm curious about this as well. Would love to be able to create and edit org files using this application. It's the best org viewer for mobile yet, IMO! |
Thanks for the request. Here's what I wrote about editing previously: Editing would be a very big stretch goal. File access I don’t think is the main hurdle. Off the top of my head the main barriers are:
That said, I may get the itch to do something a bit smaller in scope, such as allowing checking checkboxes or toggling todo status. |
Markor has been suggested as inspiration for implementing editing. |
I made my own parser for Orgro in Dart. Organice's org_parser is written in Clojure, and I can't see any path to making that run on iOS, so it's a non-starter as a replacement. It could be useful as inspiration for e.g. AST representation. |
My attraction to this software is I can quickly view org files on my mobile device. I don't necassarily want to edit. I am liking the fact that a simple "git pull" (e.g. using Mgit) gets my latest files without messing with conflict resolution because of something Orgzly did to my files (NOTHING against Orgzly - love it, but it can complicate workflow). I can see something like "org capture" that appends a headline with some other data (e.g. default TODO state, scheduled "today", etc). This would make it perfectly usable for me. N = 1, of course. I was thinking a separate app that only did that formatted append might be useful (I am guessing I could gear up something with Automate or Tasker to do this pretty easily). |
Sure, "just support appending new sections" is a useful reduction in scope that would be easier than supporting general editing. |
N=2, that is a great idea and goes along with @amake's comment on each node being a flutter widget. All the existing nodes can be read-only and allow a "capture" of a new node in plain text as an append to the file. Once the file is saved and rendered then any org formatting that was typed in will be displayed as intended! |
No problem from me regarding targeting simple section appending. That covers my use-case for a desktop GTD + mobile companion workflow. If we're going with appending new sections as the main editing functionality though... I would like to chip in a request to be able to also cycle TODO states. |
What about passing the file to an editor? and re reading on save or change. thus allowing the use of next|own cloud dropbox or other to handle the sync editor of choice to edit and orgro to view. |
Maybe you can toggle the mode, so that wherever "point" is, you toggle to edit mode which takes you to a plain text version of the file, no parsing, and you're positioned to edit the same text where you were at previously, up to glitches. Then edit, save, and toggle back to parsed view. I've also wondered if there's a way to pass "point" to open the file in an external editor at the right position. Sort of like toggling between |
The main issue I see with doing a bimodal editing scheme like that is that for large documents parsing is already very slow. So either the UX would become quite poor for large documents, or I have to create the machinery to allow editing partial subtrees of the document. The latter could work, but right now the parsed representation doesn't remember its exact text representation, so the round trip would have to be lossy. |
maybe there can be certain forms of editing that are "easier". So rather than allowing free text editing, have some predefined edit actions and only go for the ones that give most value with least effort. Here are in my opinion the most valuable edit actions aside from free flow typing text:
Maybe those can be achieved without having to deal with difficult UI where you need to free render text but rather only change one flutter element per edit action the user can take |
``` ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════ The following assertion was thrown during a scheduler callback: Layer OffsetEngineLayer was previously used as oldLayer. Once a layer is used as oldLayer, it may not be used again. Instead, after calling one of the SceneBuilder.push* methods and passing an oldLayer to it, use the layer returned by the method as oldLayer in subsequent frames. 'dart:ui/compositing.dart': Failed assertion: line 110 pos 9: '<optimized out>' Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause. In either case, please report this assertion by filing a bug on GitHub: https://github.com/flutter/flutter/issues/new?template=2_bug.md When the exception was thrown, this was the stack: #2 _EngineLayerWrapper._debugCheckNotUsedAsOldLayer (dart:ui/compositing.dart:110:9) #3 SceneBuilder.addRetained.<anonymous closure>.recursivelyCheckChildrenUsedOnce (dart:ui/compositing.dart:695:21) #4 List.forEach (dart:core-patch/growable_array.dart:416:8) #5 SceneBuilder.addRetained.<anonymous closure>.recursivelyCheckChildrenUsedOnce (dart:ui/compositing.dart:701:18) #6 SceneBuilder.addRetained.<anonymous closure> (dart:ui/compositing.dart:704:7) #7 SceneBuilder.addRetained (dart:ui/compositing.dart:707:6) #8 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:671:15) #9 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #10 OffsetLayer.addToScene (package:flutter/src/rendering/layer.dart:1421:5) #11 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:674:5) #12 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #13 ClipRectLayer.addToScene (package:flutter/src/rendering/layer.dart:1590:5) #14 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:674:5) #15 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #16 OffsetLayer.addToScene (package:flutter/src/rendering/layer.dart:1421:5) #17 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:674:5) #18 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #19 OffsetLayer.addToScene (package:flutter/src/rendering/layer.dart:1421:5) #20 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:674:5) #21 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #22 OffsetLayer.addToScene (package:flutter/src/rendering/layer.dart:1421:5) #23 Layer._addToSceneWithRetainedRendering (package:flutter/src/rendering/layer.dart:674:5) #24 ContainerLayer.addChildrenToScene (package:flutter/src/rendering/layer.dart:1284:13) #25 TransformLayer.addToScene (package:flutter/src/rendering/layer.dart:1914:5) #26 ContainerLayer.buildScene (package:flutter/src/rendering/layer.dart:1097:5) #27 RenderView.compositeFrame (package:flutter/src/rendering/view.dart:231:37) #28 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:514:18) #29 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:869:13) #30 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:375:5) #31 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1271:15) #32 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1200:9) #33 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1058:5) #34 _invoke (dart:ui/hooks.dart:145:13) #35 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5) #36 _drawFrame (dart:ui/hooks.dart:112:31) (elided 2 frames from class _AssertionError) ════════════════════════════════════════════════════════════════════════════════════════════════════ ```
I've been playing with this a bit and I find that it's quite cumbersome to adjust org_parser to retain all whitespace. What is the best practice for parsing with an eye to reproducing the original document verbatim? If there was a clear pattern to adopt, that would probably help. Another thought is that there should really be a tree-parser grammar for Org syntax; tree-sitter seems more suited to this application and the parser produced could be used pretty much everywhere. |
Relevant discussion: petitparser/dart-petitparser#142 |
Update: I've gotten org_parser to the point where it can successfully round-trip verbatim some well-formed Org documents. The next hurdle is how to implement programmatic editing of the AST. Currently the AST is immutable. The easy thing would be to allow mutation, but I'm also looking into zippers. |
Zippers have proven to be fruitful. If they have a problem it's performance, as they inherently cause a lot of object allocations. So far it seems OK though. Locally I have implemented:
I'm worried about mangling user files, but unfortunately I can't easily back up a file before saving (I would have to prompt the user for permissions on the backup file). I will have to think about how to do this. Edit: I may be able to back up the file if I have directory permissions. |
v1.32.0 is now available for beta testing at the above links. |
v1.32.0 is now released on the App Store and Google Play. It will be on F-Droid whenever the next build cycle completes. |
v1.33.3 is now available everywhere. I'm going to close this ticket. For improvements to editing please open new tickets or discussion threads. |
Currently, it seems the app only allows for viewing of org files. Are there any plans to provide write functionality in the app? If so, perhaps we should figure out a roadmap of desirable editing features to provide?
The text was updated successfully, but these errors were encountered: