TfTHacker / obsidian42-text-transporter

Text Transporter - advanced text management for Obsidian.
https://tfthacker.com/transporter
MIT License
204 stars 10 forks source link

Feature request: "Bidirectional" Pushing of Block Reference #3

Closed chrisgrieser closed 3 years ago

chrisgrieser commented 3 years ago

I was very happy to see you linking this plugin in Discord, as I have been tinkering with Templater to achieve something similar. I am not sure what would be the proper name for it, but what I was trying to accomplish some sort of "bidirectional linking command" – to push an embedded block reference to a target note, but also leave a link to the target note at the end of the block of the current note. (probably easier to show via code than to explain it, so I attached the relevant part of the templater script.)

Linking this way is actually quite useful, as it allows to replicate the so called "coding" of qualitative analysis software like atlas.ti or MAXQDA. This would get Obsidian a big step closer to the idea of being used as qualitative analysis software, as described by @ryanjamurphy in this blog post.

As your plugin is already very close to what my Templater Script is trying to achieve, could you maybe add this sort of "bidirectional" linking to this plugin's features? It wouldn't be just a "nice-to-have" feature, but rather a feature for which there already is a very real use case.

<%*
// set delimiter Icon for meta-information at the end of a block
const delimiter = "♦︎";

// the search scope is restricted to notes beginning with the string set here.
const filterString = "°";

// select target note
var targetNote = await tp.system.suggester((item) => item.path, this.app.vault.getMarkdownFiles().filter(file => file.name.startsWith(filterString)), true);

// select & get current Block
let cmEditorAct = this.app.workspace.activeLeaf.view.editor;
const curLine = cmEditorAct.getCursor().line;
cmEditorAct.setSelection({ line: curLine, ch: 0 }, { line: curLine, ch: 9999 });
let blockText = tp.file.selection();

//Create link to target note
let targetNoteLink = "[[" + targetNote.name.replace (/\.md$/,"") + "]]";

//function to create block-ID
function createBlockHash() {
   let result = '';
   var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
   var charactersLength = characters.length;
   for ( var i = 0; i < 8; i++ ) {
       result += characters.charAt(Math.floor(Math.random() * charactersLength));
   }
   return result;
}

// Check whether block already has already been referenced
// append accordingly to source note
let blockIDExists = (blockText.match(/\^\w*$/) != null)
if (blockIDExists == true){
   var id = blockText.match(/\^\w*$/)[0];
   tR = blockText.split(delimiter)[0] + delimiter + blockText.split(delimiter)[1] + targetNoteLink + " " + delimiter + " " + id + "\n";
} else {
   var id = "^" + createBlockHash();
   tR = blockText + " " + delimiter + " " + targetNoteLink + " " + delimiter + " " + `${id}`;
}

// write to target note
let blockRef = `![[${tp.file.title}#${id}]]`;
const curContent = await this.app.vault.read(targetNote);
let newContents = curContent + "**" + tp.file.title + "** " + blockRef + "\n\n";
await this.app.vault.modify(targetNote, newContents);
%>
TfTHacker commented 3 years ago

So this is fascinating. Could you do a loom walking through how it would look?

But if i follow, it is similar to “push a block ref” to another file, but also block ref the destination in the current file?

Sorry if I didn’t get it right.

BricoleurSoul commented 3 years ago

I came to suggest a bidirectional link only to find it apparently covered! I think this would be a game changer when in a refactoring exercise.

TfTHacker commented 3 years ago

I am going to add this, just need a little more info about how it would work. Can you provide me with your description?

chrisgrieser commented 3 years ago

But if i follow, it is similar to “push a block ref” to another file, but also block ref the destination in the current file?

You got it quite right actually. So here a brief explanation on how qualitative analysis works. It may sound a bit abstract, but I also recorded a short loom where I show exactly what I am trying to describe here.

So the basic purpose behind coding in qualitative analysis that you have a huge amount of text, e.g. 30 transcripts of really long interviews you did for a research project. To "tame" that huge pile of data, qualitative analysis uses a practice called "coding". That is basically a little bit similar to assigning a hashtag, but you do it not on the whole document, but rather smaller sections of text (hence block references). The idea is for example that you "code" on text segment as topic climate, which means that the interviewee is talking about climate. in the next paragraph, they are talking about poverty, so you assign the code topic poverty to it.

After going through all the data you have, you now want to see every text segment where you assigned the code topic poverty. So what I did is to have notes of the type "code" that are basically a list of embedded block references, e.g. titled "topic poverty". Going to that note in preview mode enables me to see all text sections where someone talks about poverty. It also includes a backlink to the proper section in the original interview, to reread context. So you can jump between original interview notes and "only where someone talks about topic x" pages. Structuring a data set in such a way is key to be able to conduct qualitative analysis in many social scientific disciplines.

But you also want to directly see which other codes have been assigned to the same text segment. You might for example be interested in questions like "are the segments with climate issues also poverty issues at the same time"? (i.e., co-occurrences of two topics, the qualitative-analysis-equivalent to statistical correlations). That is why it is important to append the wikilinks to the topic-pages next to the block references, so you can clearly see in both "modes" (original interviews / topic pages) whether a certain segment has also been coded with something else.

Again, this may sound a bit abstract, here is a short loom I recorded where I demonstrate the idea.

(Note that I added small stuff like highlighting a text section in case there is a selection, just to reduce friction a little bit more – I left that part out of my Templater script above.)

Since the practice of "coding" is a very idiosyncratic way of structuring data, there is specialized software to accomplish that, the two most popular being atlas.ti and MAXQDA. But obviously, they have pretty low customizability, are hugely overpriced, etc. So if we would have a plugin that simply implements that functionality, this would be super great – let alone for students who often do not have the money to get the expensive qualitative analysis licenses. Also being able to make use of other Obsidian features, e.g. the graph view (!) might be a game changer. (Let alone using plugins like dataview.)

chrisgrieser commented 3 years ago

Hope this is enough explanation without too much digressing! If you have any questions regarding this don't hesitate to ask! :)

ryanjamurphy commented 3 years ago

@chrisgrieser Good overview!

In pursuit of further clarity: is the goal of this idea to make it easier to navigate from a piece of data (i.e., the block) to the location of that block's link in the code file, and vice versa?

chrisgrieser commented 3 years ago

@ryanjamurphy Thanks! The main goal of my Templater Script was to enable the assignment of codes to specific blocks instead of whole documents. That entailed block references, embedded blocks, etc. But the specific way everything is linked bidirectionally should also ensure the easy switch between codes and documents, yes. and also to navigate from one code to another, when there is a code-co-occurence.

ryanjamurphy commented 3 years ago

I wonder if the new Block Reference Counter is a better solution to this issue?

https://github.com/shabegom/obsidian-reference-count

chrisgrieser commented 3 years ago

I think it goes into a similar direction, but adding the code-wikilink in-text has in my view several advantages:

TfTHacker commented 3 years ago

As we discussed, thank you for this idea. but it is to specific for the broader target audience.