Skip to content

Commit 7265324

Browse files
committed
clean/hide chunk output block when no output is produced
1 parent cfaf485 commit 7265324

File tree

10 files changed

+89
-35
lines changed

10 files changed

+89
-35
lines changed

src/cpp/session/modules/rmarkdown/NotebookExec.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@ FilePath getNextOutputFile(const std::string& docId, const std::string& chunkId,
6060
} // anonymous namespace
6161

6262
ChunkExecContext::ChunkExecContext(const std::string& docId,
63-
const std::string& chunkId, const std::string& options, int pixelWidth,
64-
int charWidth):
63+
const std::string& chunkId, int execScope, const std::string& options,
64+
int pixelWidth, int charWidth):
6565
docId_(docId),
6666
chunkId_(chunkId),
6767
prevWorkingDir_(""),
6868
pixelWidth_(pixelWidth),
6969
charWidth_(charWidth),
7070
prevCharWidth_(0),
71+
execScope_(execScope),
7172
connected_(false),
7273
hasOutput_(false)
7374
{
@@ -107,6 +108,11 @@ void ChunkExecContext::connect()
107108
return;
108109
}
109110

111+
// if executing the whole chunk, initialize output right away (otherwise we
112+
// wait until we actually have output)
113+
if (execScope_ == kExecScopeChunk)
114+
initializeOutput();
115+
110116
// begin capturing plots
111117
connections_.push_back(events().onPlotOutput.connect(
112118
boost::bind(&ChunkExecContext::onFileOutput, this, _1, _2,
@@ -368,6 +374,10 @@ void ChunkExecContext::initializeOutput()
368374
hasOutput_ = true;
369375
}
370376

377+
int ChunkExecContext::execScope()
378+
{
379+
return execScope_;
380+
}
371381

372382
} // namespace notebook
373383
} // namespace rmarkdown

src/cpp/session/modules/rmarkdown/NotebookExec.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class ChunkExecContext
4242
public:
4343
// initialize a new execution context
4444
ChunkExecContext(const std::string& docId, const std::string& chunkId,
45-
const std::string& options, int pixelWidth, int charWidth);
45+
int execScope, const std::string& options, int pixelWidth,
46+
int charWidth);
4647
~ChunkExecContext();
4748

4849
// connect or disconnect the execution context to events
@@ -53,6 +54,7 @@ class ChunkExecContext
5354
std::string chunkId();
5455
std::string docId();
5556
bool connected();
57+
int execScope();
5658

5759
// inject console input manually
5860
void onConsoleInput(const std::string& input);
@@ -76,6 +78,7 @@ class ChunkExecContext
7678
int pixelWidth_;
7779
int charWidth_;
7880
int prevCharWidth_;
81+
int execScope_;
7982
r::sexp::PreservedSEXP prevWarn_;
8083

8184
bool connected_;

src/cpp/session/modules/rmarkdown/SessionRmdNotebook.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@
4646
#define kFinishedReplay 0
4747
#define kFinishedInteractive 1
4848

49-
// symmetric with client
50-
#define kExecModeSingle 0
51-
#define kExecModeBatch 1
52-
5349
using namespace rstudio::core;
5450

5551
namespace rstudio {
@@ -116,13 +112,15 @@ Error refreshChunkOutput(const json::JsonRpcRequest& request,
116112
return Success();
117113
}
118114

119-
void emitOutputFinished(const std::string& docId, const std::string& chunkId)
115+
void emitOutputFinished(const std::string& docId, const std::string& chunkId,
116+
int scope)
120117
{
121118
json::Object result;
122-
result["doc_id"] = docId;
119+
result["doc_id"] = docId;
123120
result["request_id"] = "";
124-
result["chunk_id"] = chunkId;
125-
result["type"] = kFinishedInteractive;
121+
result["chunk_id"] = chunkId;
122+
result["type"] = kFinishedInteractive;
123+
result["scope"] = scope;
126124
ClientEvent event(client_events::kChunkOutputFinished, result);
127125
module_context::enqueClientEvent(event);
128126
}
@@ -152,25 +150,28 @@ void onChunkExecCompleted(const std::string& docId,
152150
const std::string& chunkId,
153151
const std::string& nbCtxId)
154152
{
155-
emitOutputFinished(docId, chunkId);
156-
157153
// if this event belonged to the current execution context, destroy it
158154
if (s_execContext &&
159155
s_execContext->docId() == docId &&
160156
s_execContext->chunkId() == chunkId)
161157
{
158+
emitOutputFinished(docId, chunkId, s_execContext->execScope());
162159
s_execContext.reset();
163160
}
161+
else
162+
{
163+
emitOutputFinished(docId, chunkId, kExecScopeChunk);
164+
}
164165
}
165166

166167
// called by the client to set the active chunk console
167168
Error setChunkConsole(const json::JsonRpcRequest& request,
168169
json::JsonRpcResponse* pResponse)
169170
{
170171
std::string docId, chunkId, options;
171-
int pixelWidth = 0, charWidth = 0, execMode = 0;
172+
int pixelWidth = 0, charWidth = 0, execMode = 0, execScope = 0;
172173
Error error = json::readParams(request.params, &docId, &chunkId, &execMode,
173-
&options, &pixelWidth, &charWidth);
174+
&execScope, &options, &pixelWidth, &charWidth);
174175
if (error)
175176
return error;
176177

@@ -208,7 +209,7 @@ Error setChunkConsole(const json::JsonRpcRequest& request,
208209
s_execContext->disconnect();
209210

210211
// create the execution context and connect it immediately if necessary
211-
s_execContext.reset(new ChunkExecContext(docId, chunkId, options,
212+
s_execContext.reset(new ChunkExecContext(docId, chunkId, execScope, options,
212213
pixelWidth, charWidth));
213214
if (s_activeConsole == chunkId)
214215
s_execContext->connect();

src/cpp/session/modules/rmarkdown/SessionRmdNotebook.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323

2424
#define kChunkLibDir "lib"
2525

26+
// symmetric with client
27+
#define kExecModeSingle 0
28+
#define kExecModeBatch 1
29+
#define kExecScopeChunk 0
30+
#define kExecScopePartial 1
31+
2632
namespace rstudio {
2733
namespace core {
2834
class Error;

src/gwt/src/org/rstudio/studio/client/rmarkdown/events/RmdChunkOutputFinishedEvent.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public final native String getRequestId() /*-{
4848
public final native int getType() /*-{
4949
return this.type;
5050
}-*/;
51+
52+
public final native int getScope() /*-{
53+
return this.scope;
54+
}-*/;
5155
}
5256

5357
public RmdChunkOutputFinishedEvent(Data data)

src/gwt/src/org/rstudio/studio/client/rmarkdown/model/RMarkdownServerOperations.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ void refreshChunkOutput(String docPath, String docId, String contextId,
7474
String requestId,
7575
ServerRequestCallback<Void> requestCallback);
7676

77-
void setChunkConsole(String docId, String chunkId, int execMode,
78-
String options, int pixelWidth, int characterWidth,
77+
void setChunkConsole(String docId, String chunkId, int execMode,
78+
int execScope, String options, int pixelWidth,
79+
int characterWidth,
7980
ServerRequestCallback<RmdChunkOptions> requestCallback);
8081

8182
void createNotebookFromCache(String rmdPath, String outputPath, ServerRequestCallback<Void> requestCallback);

src/gwt/src/org/rstudio/studio/client/rmarkdown/model/RmdChunkOutput.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,7 @@ public final boolean isReplay()
6464

6565
public static final int TYPE_SINGLE_UNIT = 0;
6666
public static final int TYPE_MULTIPLE_UNIT = 1;
67+
68+
public static final int EXEC_CHUNK_BODY = 0;
69+
public static final int EXEC_CHUNK_SECTION = 1;
6770
}

src/gwt/src/org/rstudio/studio/client/server/remote/RemoteServer.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4216,17 +4216,18 @@ public void refreshChunkOutput(String docPath, String docId,
42164216
}
42174217

42184218
@Override
4219-
public void setChunkConsole(String docId, String chunkId, int execMode,
4220-
String options, int pixelWidth, int charWidth,
4219+
public void setChunkConsole(String docId, String chunkId, int execMode,
4220+
int execScope, String options, int pixelWidth, int charWidth,
42214221
ServerRequestCallback<RmdChunkOptions> requestCallback)
42224222
{
42234223
JSONArray params = new JSONArray();
42244224
params.set(0, new JSONString(docId));
42254225
params.set(1, new JSONString(chunkId));
42264226
params.set(2, new JSONNumber(execMode));
4227-
params.set(3, new JSONString(options));
4228-
params.set(4, new JSONNumber(pixelWidth));
4229-
params.set(5, new JSONNumber(charWidth));
4227+
params.set(3, new JSONNumber(execScope));
4228+
params.set(4, new JSONString(options));
4229+
params.set(5, new JSONNumber(pixelWidth));
4230+
params.set(6, new JSONNumber(charWidth));
42304231
sendRequest(RPC_SCOPE,
42314232
"set_chunk_console",
42324233
params,

src/gwt/src/org/rstudio/studio/client/workbench/views/source/editors/text/ChunkOutputWidget.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public HandlerRegistration addExpansionStateChangeHandler(
229229
return expansionState_.addValueChangeHandler(handler);
230230
}
231231

232-
public void showChunkOutput(RmdChunkOutput output, int mode,
232+
public void showChunkOutput(RmdChunkOutput output, int mode, int scope,
233233
boolean ensureVisible)
234234
{
235235
if (output.getType() == RmdChunkOutput.TYPE_MULTIPLE_UNIT)
@@ -248,7 +248,7 @@ public void showChunkOutput(RmdChunkOutput output, int mode,
248248
}
249249

250250
// ensure the output is visible if requested
251-
onOutputFinished(ensureVisible);
251+
onOutputFinished(ensureVisible, scope);
252252
}
253253
else if (output.getType() == RmdChunkOutput.TYPE_SINGLE_UNIT)
254254
{
@@ -270,6 +270,10 @@ public void syncHeight(boolean scrollToBottom, boolean ensureVisible)
270270
return;
271271
}
272272

273+
// don't sync if not visible and no output yet
274+
if (!isVisible() && (state_ == CHUNK_EMPTY || state_ == CHUNK_PRE_OUTPUT))
275+
return;
276+
273277
setVisible(true);
274278

275279
// clamp chunk height to min/max (the +19 is the sum of the vertical
@@ -308,14 +312,28 @@ public static boolean isEditorStyleCached()
308312
s_outlineColor != null;
309313
}
310314

311-
public void onOutputFinished(boolean ensureVisible)
315+
public void onOutputFinished(boolean ensureVisible, int execScope)
312316
{
313317
// flush any remaining queued errors
314318
flushQueuedErrors(ensureVisible);
315319

316-
// if we got some output, synchronize the chunk's height to accommodate it
317320
if (state_ != CHUNK_PRE_OUTPUT)
321+
{
322+
// if we got some output, synchronize the chunk's height to accommodate
323+
// it
318324
syncHeight(true, ensureVisible);
325+
}
326+
else if (execScope == TextEditingTargetNotebook.SCOPE_CHUNK)
327+
{
328+
// if executing the whole chunk but no output was received, clean up
329+
// any prior output and hide the output
330+
root_.clear();
331+
if (vconsole_ != null)
332+
vconsole_.clear();
333+
renderedHeight_ = 0;
334+
setVisible(false);
335+
host_.onOutputHeightChanged(0, ensureVisible);
336+
}
319337

320338
state_ = CHUNK_READY;
321339
lastOutputType_ = RmdChunkOutputUnit.TYPE_NONE;
@@ -495,7 +513,7 @@ public void onRestartStatus(RestartStatusEvent event)
495513
// as though the server told us it's done
496514
if (state_ != CHUNK_READY)
497515
{
498-
onOutputFinished(false);
516+
onOutputFinished(false, TextEditingTargetNotebook.SCOPE_PARTIAL);
499517
}
500518
}
501519

src/gwt/src/org/rstudio/studio/client/workbench/views/source/editors/text/rmd/TextEditingTargetNotebook.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,9 @@ public void onSendToChunkConsole(final SendToChunkConsoleEvent event)
631631
// have the server start recording output from this chunk
632632
syncWidth();
633633
server_.setChunkConsole(docUpdateSentinel_.getId(),
634-
chunkDef.getChunkId(), MODE_SINGLE, options, getPlotWidth(),
635-
charWidth_, new ServerRequestCallback<RmdChunkOptions>()
634+
chunkDef.getChunkId(), MODE_SINGLE, SCOPE_PARTIAL, options,
635+
getPlotWidth(), charWidth_,
636+
new ServerRequestCallback<RmdChunkOptions>()
636637
{
637638
@Override
638639
public void onResponseReceived(RmdChunkOptions options)
@@ -715,7 +716,8 @@ public void onRmdChunkOutput(RmdChunkOutputEvent event)
715716

716717
outputs_.get(chunkId).getOutputWidget()
717718
.showChunkOutput(event.getOutput(), mode,
718-
ensureVisible);
719+
TextEditingTargetNotebook.SCOPE_PARTIAL,
720+
ensureVisible);
719721
}
720722
}
721723

@@ -765,7 +767,7 @@ else if (data.getType() == RmdChunkOutputFinishedEvent.TYPE_INTERACTIVE &&
765767
if (outputs_.containsKey(data.getChunkId()))
766768
{
767769
outputs_.get(data.getChunkId()).getOutputWidget()
768-
.onOutputFinished(ensureVisible);
770+
.onOutputFinished(ensureVisible, data.getScope());
769771

770772
// mark the document dirty (if it isn't already) since it now
771773
// contains notebook cache changes that haven't been committed
@@ -1120,7 +1122,8 @@ private void cleanCurrentExecChunk()
11201122
if (outputs_.containsKey(executingChunk_.chunkId))
11211123
{
11221124
outputs_.get(executingChunk_.chunkId)
1123-
.getOutputWidget().onOutputFinished(false);
1125+
.getOutputWidget().onOutputFinished(false,
1126+
TextEditingTargetNotebook.SCOPE_PARTIAL);
11241127
}
11251128
cleanChunkExecState(executingChunk_.chunkId);
11261129
executingChunk_ = null;
@@ -1179,9 +1182,10 @@ private void processChunkExecQueue()
11791182
ChunkContextToolbar.STATE_EXECUTING);
11801183
}
11811184

1182-
server_.setChunkConsole(docUpdateSentinel_.getId(),
1183-
unit.chunkId,
1185+
server_.setChunkConsole(docUpdateSentinel_.getId(),
1186+
unit.chunkId,
11841187
unit.mode,
1188+
SCOPE_CHUNK,
11851189
unit.options,
11861190
getPlotWidth(),
11871191
charWidth_,
@@ -1830,4 +1834,7 @@ public void execute()
18301834

18311835
public final static int MODE_SINGLE = 0;
18321836
public final static int MODE_BATCH = 1;
1837+
1838+
public final static int SCOPE_CHUNK = 0;
1839+
public final static int SCOPE_PARTIAL = 1;
18331840
}

0 commit comments

Comments
 (0)