basic package aware autocomplete

This commit is contained in:
Nate Stemen 2017-10-12 15:33:14 +01:00
parent cfca4b5d6c
commit f113ba6342
13 changed files with 120 additions and 113 deletions

View file

@ -1,28 +0,0 @@
EditorRealTimeController = require "../Editor/EditorRealTimeController"
LabelsHandler = require './LabelsHandler'
logger = require 'logger-sharelatex'
module.exports = LabelsController =
getAllLabels: (req, res, next) ->
project_id = req.params.project_id
logger.log {project_id}, "getting all labels for project"
LabelsHandler.getAllMetaForProject project_id, (err, projectMeta) ->
if err?
logger.err {project_id, err}, "[LabelsController] error getting all labels from project"
return next(err)
res.json {projectId: project_id, projectMeta: projectMeta}
broadcastLabelsForDoc: (req, res, next) ->
project_id = req.params.project_id
doc_id = req.params.doc_id
logger.log {project_id, doc_id}, "getting labels for doc"
LabelsHandler.getMetaForDoc project_id, doc_id, (err, docMeta) ->
if err?
logger.err {project_id, doc_id, err}, "[LabelsController] error getting labels from doc"
return next(err)
EditorRealTimeController.emitToRoom project_id, 'broadcastDocMeta', {
docId: doc_id, meta: docMeta
}
res.sendStatus(200)

View file

@ -0,0 +1,29 @@
EditorRealTimeController = require "../Editor/EditorRealTimeController"
MetaHandler = require './MetaHandler'
logger = require 'logger-sharelatex'
module.exports = MetaController =
getMetadata: (req, res, next) ->
project_id = req.params.project_id
logger.log {project_id}, "getting all labels for project"
MetaHandler.getAllMetaForProject project_id, (err, projectMeta) ->
if err?
logger.err {project_id, err}, "[MetaController] error getting all labels from project"
return next err
res.json {projectId: project_id, projectMeta: projectMeta}
broadcastMetadataForDoc: (req, res, next) ->
project_id = req.params.project_id
doc_id = req.params.doc_id
logger.log {project_id, doc_id}, "getting labels for doc"
MetaHandler.getMetaForDoc project_id, doc_id, (err, docMeta) ->
if err?
logger.err {project_id, doc_id, err}, "[MetaController] error getting labels from doc"
return next err
EditorRealTimeController.emitToRoom project_id, 'broadcastDocMeta', {
docId: doc_id, meta: docMeta
}
res.sendStatus 200
MetaController

View file

@ -2,7 +2,7 @@ ProjectEntityHandler = require "../Project/ProjectEntityHandler"
DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
module.exports = LabelsHandler =
module.exports = MetaHandler =
labelCaptureRegex: () ->
/\\label\{([^\}\n\\]{0,80})\}/g
@ -17,7 +17,7 @@ module.exports = LabelsHandler =
ProjectEntityHandler.getAllDocs projectId, (err, docs) ->
if err?
return callback err
projectMeta = LabelsHandler.extractMetaFromProjectDocs docs
projectMeta = MetaHandler.extractMetaFromProjectDocs docs
callback null, projectMeta
getMetaForDoc: (projectId, docId, callback=(err, docMeta)->) ->
@ -27,13 +27,13 @@ module.exports = LabelsHandler =
ProjectEntityHandler.getDoc projectId, docId, (err, lines) ->
if err?
return callback err
docMeta = LabelsHandler.extractMetaFromDoc lines
docMeta = MetaHandler.extractMetaFromDoc lines
callback null, docMeta
extractMetaFromDoc: (lines) ->
docMeta = {labels: [], packages: []}
label_re = LabelsHandler.labelCaptureRegex()
package_re = LabelsHandler.packageCaptureRegex()
label_re = MetaHandler.labelCaptureRegex()
package_re = MetaHandler.packageCaptureRegex()
for line in lines
while labelMatch = label_re.exec line
if labelMatch[1]
@ -41,11 +41,12 @@ module.exports = LabelsHandler =
while packageMatch = package_re.exec line
if packageMatch[2]
for pkg in packageMatch[2].split ','
docMeta.packages.push pkg.trim()
if pkg.trim()
docMeta.packages.push pkg.trim()
return docMeta
extractMetaFromProjectDocs: (projectDocs) ->
projectMeta = {}
for _path, doc of projectDocs
projectMeta[doc._id] = LabelsHandler.extractMetaFromDoc doc.lines
projectMeta[doc._id] = MetaHandler.extractMetaFromDoc doc.lines
return projectMeta

View file

@ -43,8 +43,7 @@ SudoModeController = require('./Features/SudoMode/SudoModeController')
SudoModeMiddlewear = require('./Features/SudoMode/SudoModeMiddlewear')
AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
AnnouncementsController = require("./Features/Announcements/AnnouncementsController")
LabelsController = require('./Features/Labels/LabelsController')
# MetadataController = require('./Features/ProjectMetadata/MetadataController')
MetaController = require('./Features/Metadata/MetaController')
logger = require("logger-sharelatex")
_ = require("underscore")
@ -202,8 +201,8 @@ module.exports = class Router
webRouter.get '/Project/:Project_id/download/zip', AuthorizationMiddlewear.ensureUserCanReadProject, ProjectDownloadsController.downloadProject
webRouter.get '/project/download/zip', AuthorizationMiddlewear.ensureUserCanReadMultipleProjects, ProjectDownloadsController.downloadMultipleProjects
webRouter.get '/project/:project_id/labels', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), LabelsController.getAllLabels
webRouter.post '/project/:project_id/doc/:doc_id/labels', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), LabelsController.broadcastLabelsForDoc
webRouter.get '/project/:project_id/metadata', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), MetaController.getMetadata
webRouter.post '/project/:project_id/doc/:doc_id/metadata', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), MetaController.broadcastMetadataForDoc
webRouter.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
webRouter.post '/tag', AuthenticationController.requireLogin(), TagsController.createTag

View file

@ -9,7 +9,7 @@ define [
"ide/pdf/PdfManager"
"ide/binary-files/BinaryFilesManager"
"ide/references/ReferencesManager"
"ide/labels/LabelsManager"
"ide/metadata/MetadataManager"
"ide/review-panel/ReviewPanelManager"
"ide/SafariScrollPatcher"
"ide/FeatureOnboardingController",
@ -47,12 +47,12 @@ define [
PdfManager
BinaryFilesManager
ReferencesManager
LabelsManager
MetadataManager
ReviewPanelManager
SafariScrollPatcher
) ->
App.controller "IdeController", ($scope, $timeout, ide, localStorage, sixpack, event_tracking, labels) ->
App.controller "IdeController", ($scope, $timeout, ide, localStorage, sixpack, event_tracking, metadata) ->
# Don't freak out if we're already in an apply callback
$scope.$originalApply = $scope.$apply
$scope.$apply = (fn = () ->) ->
@ -72,10 +72,10 @@ define [
view: "editor"
chatOpen: false
pdfLayout: 'sideBySide'
pdfHidden: false,
pdfWidth: 0,
reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}"),
miniReviewPanelVisible: false,
pdfHidden: false
pdfWidth: 0
reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}")
miniReviewPanelVisible: false
}
$scope.onboarding = {
autoCompile: if window.user.betaProgram and window.showAutoCompileOnboarding then 'unseen' else 'dismissed'
@ -140,7 +140,7 @@ define [
ide.pdfManager = new PdfManager(ide, $scope)
ide.permissionsManager = new PermissionsManager(ide, $scope)
ide.binaryFilesManager = new BinaryFilesManager(ide, $scope)
ide.labelsManager = new LabelsManager(ide, $scope, labels)
ide.metadataManager = new MetadataManager(ide, $scope, metadata)
inited = false
$scope.$on "project:joined", () ->
@ -155,7 +155,7 @@ define [
$timeout(
() ->
if $scope.permissions.write
ide.labelsManager.loadProjectLabelsFromServer()
ide.metadataManager.loadProjectMetaFromServer()
_labelsInitialLoadDone = true
, 200
)

View file

@ -9,11 +9,11 @@ define [
"ide/editor/directives/aceEditor/highlights/HighlightsManager"
"ide/editor/directives/aceEditor/cursor-position/CursorPositionManager"
"ide/editor/directives/aceEditor/track-changes/TrackChangesManager"
"ide/editor/directives/aceEditor/labels/LabelsManager"
"ide/labels/services/labels"
"ide/editor/directives/aceEditor/metadata/MetadataManager"
"ide/metadata/services/metadata"
"ide/graphics/services/graphics"
"ide/preamble/services/preamble"
], (App, Ace, SearchBox, ModeList, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager, TrackChangesManager, LabelsManager) ->
], (App, Ace, SearchBox, ModeList, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager, TrackChangesManager, MetadataManager) ->
EditSession = ace.require('ace/edit_session').EditSession
ModeList = ace.require('ace/ext/modelist')
@ -35,9 +35,8 @@ define [
url = ace.config._moduleUrl(args...) + "?fingerprint=#{window.aceFingerprint}"
return url
# console.log 'making it to right before aceEditor'
App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, labels, graphics, preamble) ->
App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, metadata, graphics, preamble) ->
monkeyPatchSearch($rootScope, $compile)
return {
@ -104,8 +103,8 @@ define [
highlightsManager = new HighlightsManager(scope, editor, element)
cursorPositionManager = new CursorPositionManager(scope, editor, element, localStorage)
trackChangesManager = new TrackChangesManager(scope, editor, element)
labelsManager = new LabelsManager(scope, editor, element, labels)
autoCompleteManager = new AutoCompleteManager(scope, editor, element, labelsManager, graphics, preamble)
metadataManager = new MetadataManager(scope, editor, element, metadata)
autoCompleteManager = new AutoCompleteManager(scope, editor, element, metadataManager, graphics, preamble)
# Prevert Ctrl|Cmd-S from triggering save dialog

View file

@ -9,8 +9,7 @@ define [
aceSnippetManager = ace.require('ace/snippets').snippetManager
class AutoCompleteManager
constructor: (@$scope, @editor, @element, @labelsManager, @graphics, @preamble) ->
@suggestionManager = new CommandManager(@labelsManager)
constructor: (@$scope, @editor, @element, @metadataManager, @graphics, @preamble) ->
@monkeyPatchAutocomplete()
@ -34,7 +33,7 @@ define [
enableLiveAutocompletion: false
})
# metadataManager = @metadataManager
commandCompleter = new CommandManager(@metadataManager)
SnippetCompleter = new EnvironmentManager()
@ -65,7 +64,7 @@ define [
}
callback null, result
labelsManager = @labelsManager
metadataManager = @metadataManager
LabelsCompleter =
getCompletions: (editor, session, pos, prefix, callback) ->
context = Helpers.getContext(editor, pos)
@ -83,7 +82,7 @@ define [
meta: "cross-reference",
score: 60
}
for label in labelsManager.getAllLabels()
for label in metadataManager.getAllLabels()
result.push {
caption: "\\#{commandName}{#{label}#{if needsClosingBrace then '}' else ''}",
value: "\\#{commandName}{#{label}#{if needsClosingBrace then '}' else ''}",
@ -129,10 +128,10 @@ define [
callback null, result
@editor.completers = [
@suggestionManager,
SnippetCompleter,
ReferencesCompleter,
LabelsCompleter,
commandCompleter
SnippetCompleter
ReferencesCompleter
LabelsCompleter
GraphicsCompleter
]

View file

@ -1,4 +1,6 @@
define [], () ->
define [
"./package_definitions"
], (packageCommandMappings) ->
noArgumentCommands = [
'item', 'hline', 'lipsum', 'centering', 'noindent', 'textwidth', 'draw',
'maketitle', 'newpage', 'verb', 'bibliography', 'hfill', 'par',
@ -77,10 +79,10 @@ define [], () ->
special
)
packageCommandMappings = {
amsmath: ['holyshititworks', 'mathematics']
natbib: ['somebibliographystuff']
}
# packageCommandMappings = {
# amsmath: ['holyshititworks', 'mathematics']
# natbib: ['somebibliographystuff']
# }
class Parser
constructor: (@doc, @prefix) ->
@ -171,10 +173,10 @@ define [], () ->
return false
class CommandManager
constructor: (@labelsManager) ->
constructor: (@metadataManager) ->
getCompletions: (editor, session, pos, prefix, callback) ->
packages = @labelsManager.getAllPackages()
packages = @metadataManager.getAllPackages()
packageCommands = []
for pkg in packages
if packageCommandMappings[pkg]?
@ -182,7 +184,8 @@ define [], () ->
packageCommands.push {
caption: "\\#{cmd}"
snippet: "\\#{cmd}"
meta: "cmd"
meta: "#{pkg}-cmd"
score: 60
}
doc = session.getValue()

File diff suppressed because one or more lines are too long

View file

@ -9,8 +9,8 @@ define [
else
return null
class LabelsManager
constructor: (@$scope, @editor, @element, @Labels) ->
class MetadataManager
constructor: (@$scope, @editor, @element, @Metadata) ->
@debouncer = {} # DocId => Timeout
onChange = (change) =>
@ -21,8 +21,12 @@ define [
cursorPosition = @editor.getCursorPosition()
end = change.end
range = new Range(end.row, 0, end.row, end.column)
lineUpToCursor = @editor.getSession().getTextRange(range)
commandFragment = getLastCommandFragment(lineUpToCursor)
lineUpToCursor = @editor.getSession().getTextRange range
if lineUpToCursor.trim() == '%' or lineUpToCursor.startsWith '\\'
# fix in case change is just (un)comment out a package
range = new Range end.row, 0, end.row, end.column + 80
lineUpToCursor = @editor.getSession().getTextRange range
commandFragment = getLastCommandFragment lineUpToCursor
linesContainPackage = _.any(
change.lines,
@ -39,20 +43,20 @@ define [
lastCommandFragmentIsMeta = lastCommandFragmentIsPackage or lastCommandFragmentIsLabel
if linesContainMeta or lastCommandFragmentIsMeta
@scheduleLoadCurrentDocLabelsFromServer()
@scheduleLoadCurrentDocMetaFromServer()
@editor.on "changeSession", (e) =>
e.oldSession.off "change", onChange
e.session.on "change", onChange
loadCurrentDocLabelsFromServer: () ->
currentDocId = @$scope.docId
@Labels.loadDocLabelsFromServer currentDocId
# loadCurrentDocLabelsFromServer: () ->
# currentDocId = @$scope.docId
# @Metadata.loadDocMetaFromServer currentDocId
loadDocLabelsFromServer: (docId) ->
@Labels.loadDocLabelsFromServer docId
loadDocMetaFromServer: (docId) ->
@Metadata.loadDocMetaFromServer docId
scheduleLoadCurrentDocLabelsFromServer: () ->
scheduleLoadCurrentDocMetaFromServer: () ->
# De-bounce loading labels with a timeout
currentDocId = @$scope.docId
existingTimeout = @debouncer[currentDocId]
@ -61,14 +65,14 @@ define [
delete @debouncer[currentDocId]
@debouncer[currentDocId] = setTimeout(
() =>
@loadDocLabelsFromServer currentDocId
@loadDocMetaFromServer currentDocId
delete @debouncer[currentDocId]
, 1000
, this
)
getAllLabels: () ->
@Labels.getAllLabels()
@Metadata.getAllLabels()
getAllPackages: () ->
@Labels.getAllPackages()
@Metadata.getAllPackages()

View file

@ -1,13 +0,0 @@
define [], () ->
class LabelsManager
constructor: (@ide, @$scope, @labels) ->
@ide.socket.on 'broadcastDocMeta', (data) =>
@labels.onBroadcastDocLabels data
@$scope.$on 'entity:deleted', @labels.onEntityDeleted
@$scope.$on 'file:upload:complete', @labels.fileUploadComplete
loadProjectLabelsFromServer: () ->
@labels.loadProjectLabelsFromServer()

View file

@ -0,0 +1,13 @@
define [], () ->
class MetadataManager
constructor: (@ide, @$scope, @metadata) ->
@ide.socket.on 'broadcastDocMeta', (data) =>
@metadata.onBroadcastDocMeta data
@$scope.$on 'entity:deleted', @metadata.onEntityDeleted
@$scope.$on 'file:upload:complete', @metadata.fileUploadComplete
loadProjectMetaFromServer: () ->
@metadata.loadProjectMetaFromServer()

View file

@ -2,46 +2,46 @@ define [
"base"
], (App) ->
App.factory 'labels', ($http, ide) ->
App.factory 'metadata', ($http, ide) ->
state = {documents: {}}
labels = {
metadata = {
state: state
}
labels.onBroadcastDocLabels = (data) ->
metadata.onBroadcastDocMeta = (data) ->
if data.docId? and data.meta?
state.documents[data.docId] = data.meta
labels.onEntityDeleted = (e, entity) ->
metadata.onEntityDeleted = (e, entity) ->
if entity.type == 'doc'
delete state.documents[entity.id]
labels.onFileUploadComplete = (e, upload) ->
metadata.onFileUploadComplete = (e, upload) ->
if upload.entity_type == 'doc'
labels.loadDocLabelsFromServer upload.entity_id
metadata.loadDocMetaFromServer upload.entity_id
labels.getAllLabels = () ->
metadata.getAllLabels = () ->
_.flatten(meta.labels for docId, meta of state.documents)
labels.getAllPackages = () ->
metadata.getAllPackages = () ->
_.flatten(meta.packages for docId, meta of state.documents)
labels.loadProjectLabelsFromServer = () ->
metadata.loadProjectMetaFromServer = () ->
$http
.get("/project/#{window.project_id}/labels")
.get("/project/#{window.project_id}/metadata")
.then (response) ->
{ data } = response
if data.projectMeta
for docId, docMeta of data.projectMeta
state.documents[docId] = docMeta.labels
state.documents[docId] = docMeta
labels.loadDocLabelsFromServer = (docId) ->
metadata.loadDocMetaFromServer = (docId) ->
$http
.post(
"/project/#{window.project_id}/doc/#{docId}/labels",
"/project/#{window.project_id}/doc/#{docId}/metadata",
{_csrf: window.csrfToken}
)
return labels
return metadata