Re: [code] [textadept] Working with clipboard

From: Mitchell <m.att.foicica.com>
Date: Tue, 17 Sep 2019 13:07:23 -0400 (EDT)

Hi Qwerky,

On Tue, 17 Sep 2019, Qwerky wrote:

> Hi Mitchell,
>
> On 2019-09-17 10:16, Mitchell wrote:
>> Hi Qwerky,
>>
>> On Sun, 15 Sep 2019, Qwerky wrote:
>>
>>> Hi Mitchell,
>>>
>>> On 2019-09-15 13:35, Mitchell wrote:
>>>> Hi Qwerky,
>>>>
>>>> On Sun, 15 Sep 2019, Qwerky wrote:
>>>>
>>>>> Hi Mitchell,
>>>>>
>>>>> On 2019-09-15 09:08, Mitchell wrote:
>>>>>> Hi Qwerky,
>>>>>>
>>>>>> On Sat, 14 Sep 2019, Qwerky wrote:
>>>>>>
>>>>>>> Hi Mitchell,
>>>>>>>
>>>>>>> What is needed to make use of buffer.copy_text(), to write text to the
>>>>>>> clipboard?  I've used `cliptext = ui.clipboard_text` to read the
>>>>>>> clipboard
>>>>>>> text to a string, and then `for line in cliptext:gmatch('.-\n') do` to
>>>>>>> read
>>>>>>> the lines of text from the string into a table.
>>>>>>>
>>>>>>> After that, `cliptext = table.concat(cliplines, '\n')` to join the
>>>>>>> table
>>>>>>> lines, and `buffer.copy_text(cliptext)` to write that string back to
>>>>>>> the
>>>>>>> clipboard.
>>>>>>>
>>>>>>> Although this text looks the same on the clipboard, when it is pasted
>>>>>>> into
>>>>>>> some other text, the result is not the same as pasting the original
>>>>>>> clipboard
>>>>>>> text into some other text.  Specifically, when the original text is
>>>>>>> rectangular, and is pasted into some other text, it pastes each line
>>>>>>> into
>>>>>>> succeeding lines of the other text.  But after the above operation,
>>>>>>> the
>>>>>>> text
>>>>>>> is pasted as a group of lines at a single place, rather than
>>>>>>> individual
>>>>>>> lines
>>>>>>> going into succeeding lines of the receiving text.
>>>>>>>
>>>>>>> How can I keep the text rectangular after writing it back to the
>>>>>>> clipboard?
>>>>>>
>>>>>> This is not possible with Scintilla, unfortunately. You cannot put
>>>>>> rectangular or multi-selected text on the clipboard. Only Scintilla can
>>>>>> do
>>>>>> it. It's like a one-way thing.
>>>>>>
>>>>>> Cheers,
>>>>>> Mitchell
>>>>>
>>>>> Hmm... blocked at every turn.  But wait, I'm not sure that the problem
>>>>> lies
>>>>> with putting the text on the clipboard, but rather with /reading it
>>>>> back/
>>>>> in
>>>>> a rectangular format (see my earlier follow-up to this thread, about
>>>>> `buffer.selection_is_rectangle`).  I'll quote it here:
>>>>>
>>>>> "My working theory is that `buffer.selection_is_rectangle`, which is
>>>>> read-only, is used to keep track of whether or not the selection is
>>>>> rectangular, and controls how the text is pasted.  And further, that it
>>>>> is
>>>>> being reset by `buffer.copy_text()`, so that even though the text was
>>>>> originally selected as rectangular, after using `buffer.copy_text()`, it
>>>>> will
>>>>> always be pasted as stream.  Since `buffer.selection_is_rectangle` is
>>>>> read-only, I'm not sure how to work around this.  Does this theory sound
>>>>> correct?"
>>>>>
>>>>> When I modify the clipboard text in a Lua module, as described above,
>>>>> and
>>>>> then paste it into text in a different text editor, it can be made to
>>>>> appear
>>>>> correctly (depends on the text editor, and upon its settings). It seems
>>>>> to
>>>>> me that Scintilla is keeping track of the clipboard contents, and will
>>>>> paste
>>>>> back as rectangular only when it believes it has put rectangular data
>>>>> there.
>>>>> Also, I think it must be monitoring the clipboard, and becomes aware
>>>>> when
>>>>> another application places something on the clipboard, in which case it
>>>>> won't
>>>>> paste back as rectangular (or as line), but only as stream.
>>>>>
>>>>> So whether the limitation is in writing or reading the clipboard, the
>>>>> end
>>>>> result (and perhaps the answer as well) may be the same: Scintilla won't
>>>>> allow it!
>>>>
>>>> Think about it for a minute: clipboard text is just a sequence of bytes
>>>> to
>>>> pass between applications. It is up to the applications how they want to
>>>> interpret it. Scintilla doesn't try to do anything fancy. Its
>>>> documentation
>>>> states how it outputs rectangular selections and multiple selections on
>>>> the
>>>> clipboard. It is then up to clients or external applications to figure
>>>> out
>>>> what to do with it.
>>>>
>>>> The same idea applies to incoming clipboard text. Just because there is a
>>>> rectangular or multiple selection in play when text is pasted doesn't
>>>> mean
>>>> Scintilla should try and be "smart" about what to do with said text.
>>>> Incoming text with newlines could legitimately not be a rectangular
>>>> selection, even if there is one currently.
>>>>
>>>>> This is a real blow, as this issue with rectangular selections is the
>>>>> last
>>>>> major obstacle that I have with Scintilla.  And just when I thought I
>>>>> had
>>>>> a
>>>>> solution (by padding the rectangle in a module), it is blocked again.
>>>>
>>>> You could try writing your own Lua code that interprets your clipboard
>>>> text
>>>> in a special way, determines rectangular selection bounds, and then
>>>> pastes
>>>> as you expect. I think this is kind of what Scintilla expects client
>>>> applications to do, as clipboard formats are not standardized, as I
>>>> alluded
>>>> to above.
>>>>
>>>>> Well, I've posted on the Scintilla list, and we'll see what Neil says
>>>>> about
>>>>> it in October, when he gets back.  If there are any other Textadept
>>>>> users
>>>>> who
>>>>> would like this feature, you may wish to add your voice as well.
>>>>>
>>>>> Thanks for you help, Mitchell.  Hopefully a solution will arrive.
>>>>>
>>>>> Oh, a thought just came up: `buffer.selection_is_rectangle` is read-only
>>>>> in
>>>>> Textadept (and presumably so is its counterpart in Scintilla). Would you
>>>>> be
>>>>> able to make it read/write, which may help?
>>>>
>>>> Making it writable will not help. Scintilla just does not interpret text
>>>> put on the clipboard for a reason.
>>>>
>>>> Cheers,
>>>> Mitchell
>>>
>>> Although I do agree mostly with what you wrote, Scintilla does interpret
>>> /it's own/ rectangular selections and pastes them back as rectangular.  I
>>> thought that perhaps Scintilla's counterpart of
>>> `buffer.selection_is_rectangle` is what it uses to make that
>>> determination.
>>> However, if you say that that is not the case, so be it.
>>>
>>> As to writing Lua code to handle it, I am quite willing to give it a shot.
>>> I've already figured out how to read/pad/write the clipboard data to make
>>> it
>>> a proper rectangle.  But I'm not sure how to /paste/ that data into a
>>> Textadept buffer, which I suppose would need to be done line-by-line--any
>>> pointers along those lines would be appreciated.
>>
>> You could try to use `buffer.rectangular_selection_{anchor,caret}` to
>> determine the row and column extents of the rectangular selection, then
>> iterate over those lines, using `buffer:set_target_range()` and
>> `buffer:replace_target()` coupled with your text to paste. Wrap all of this
>> in `buffer:{begin,end}_undo_action()` of course. Then re-bind the
>> `buffer.paste` key to a custom function that checks for a rectangular
>> selection on the clipboard or whatever, and if so, call your custom
>> function. Otherwise call `buffer:paste()`.
>>
>> This is off the top of my head and might need some tweaking.
>>
>> Cheers,
>> Mitchell
>
> Thanks so much for the response.  I am using
> `buffer.rectangular_selection_{anchor,caret}` in my cut/copy functions to
> determine width, and then padding the clipboard text so that every line is
> the same length.  I am doing the padding in cut/copy so that the text on the
> clipboard is padded, and may be inserted as rectangular into other
> applications as well.
>
> In my paste function, I am using `buffer.selection_n_{anchor,caret}` to
> determine width and height (number of lines), and iterating over those lines
> using buffer.insert_text, after first clearing any existing selection. There
> are so many considerations, such as whether or not there is an existing
> selection, and most importantly, whether or not the caret is in virtual space
> (important in both cut/copy and in paste).  What I have so far is actually
> working quite well.  I am just trying to get the end position of the caret to
> be consistent.
>
> Although I have looked at `buffer:set_target_range()` and
> `buffer:replace_target()` before, I really do not understand how `target` is
> used in Textadept, even after studying the API documentation!  I would
> appreciate a pointer or some additional help to understand that.  I'm sure
> your code would be much better than mine.

The "target" functions pretty much like a selection, only it doesn't alter the actual selection. Textadept makes use of this in a lot of instances where it wants to manipulate text without affecting whatever is currently selected.

Cheers,
Mitchell

-- 
You are subscribed to code.att.foicica.com.
To change subscription settings, send an e-mail to code+help.att.foicica.com.
To unsubscribe, send an e-mail to code+unsubscribe.att.foicica.com.
Received on Tue 17 Sep 2019 - 13:07:23 EDT

This archive was generated by hypermail 2.2.0 : Wed 18 Sep 2019 - 06:33:06 EDT